[
  {
    "path": ".jscsrc",
    "content": "{\n  \"requireCurlyBraces\": [\"if\", \"else\", \"for\", \"while\", \"do\", \"try\", \"catch\", \"case\"],\n  \"requireSpaceAfterKeywords\": [\"if\", \"else\", \"for\", \"while\", \"do\", \"switch\", \"return\", \"try\", \"catch\"],\n  \"requireSpaceBeforeBlockStatements\": true,\n  \"requireParenthesesAroundIIFE\": true,\n  \"requireSpacesInConditionalExpression\": {\n    \"afterTest\": true,\n    \"beforeConsequent\": true,\n    \"afterConsequent\": true,\n    \"beforeAlternate\": true\n  },\n  \"requireSpacesInFunctionExpression\": {\n    \"beforeOpeningRoundBrace\": true,\n    \"beforeOpeningCurlyBrace\": true\n  },\n  \"requireSpacesInFunctionDeclaration\": {\n    \"beforeOpeningCurlyBrace\": true\n  },\n  \"disallowSpacesInFunctionDeclaration\": {\n    \"beforeOpeningRoundBrace\": true\n  },\n  \"requireMultipleVarDecl\": true,\n  \"requireBlocksOnNewline\": true,\n  \"disallowPaddingNewlinesInBlocks\": true,\n  \"disallowEmptyBlocks\": true,\n  \"disallowSpaceAfterObjectKeys\": true,\n  \"disallowSpaceBeforePostfixUnaryOperators\": [\"++\", \"--\"],\n  \"requireSpaceBeforeBinaryOperators\": [\"=\", \"+\", \"-\", \"/\", \"*\", \"==\", \"===\", \"!=\", \"!==\"],\n  \"requireSpaceAfterBinaryOperators\": [\"=\", \",\", \"+\", \"-\", \"/\", \"*\", \"==\", \"===\", \"!=\", \"!==\"],\n  \"disallowImplicitTypeConversion\": [\"numeric\", \"boolean\", \"binary\", \"string\"],\n  \"disallowKeywords\": [\"with\", \"eval\"],\n  \"disallowMultipleLineStrings\": true,\n  \"disallowMultipleLineBreaks\": true,\n  \"disallowMixedSpacesAndTabs\": true,\n  \"disallowTrailingWhitespace\": true,\n  \"disallowTrailingComma\": true,\n  \"disallowKeywordsOnNewLine\": [\"else\"],\n  \"requireCapitalizedConstructors\": true,\n  \"safeContextKeyword\": \"self\",\n  \"disallowYodaConditions\": true,\n  \"validateJSDoc\": {\n    \"checkParamNames\": true,\n    \"requireParamTypes\": true,\n    \"checkRedundantParams\": true\n  },\n  \"excludeFiles\": [\n    \"node_modules/**\",\n    \"lib/**\",\n    \"storage/**\",\n    \"system/*.json\"\n  ],\n  \"fileExtensions\": [\".js\"]\n}"
  },
  {
    "path": ".jshintrc",
    "content": "{\n  \"nonew\": true,\n  \"curly\": true,\n  \"noarg\": true,\n  \"forin\": true,\n  \"noempty\": true,\n  \"eqeqeq\":true,\n  \"strict\":true,\n  \"undef\":true,\n  \"bitwise\":true,\n  \"browser\":true,\n  \"devel\":true,\n  \"mocha\": true,\n  \"node\": true,\n  \"globals\": {\n    \"describe\": true,\n    \"it\": true,\n    \"executeFile\": true,\n    \"_\": true,\n    \"Core\": true,\n    \"global\": true\n  }\n}\n\n\n"
  },
  {
    "path": ".syscommands",
    "content": "cat /etc/z-way/box_type\nreboot\ncat /etc/timezone\nsh automation/lib/configAP.sh\nsh automation/lib/fetchLog.sh\nsh automation/lib/timezone.sh\ntail -1000 /var/log/z-way-server.log | tac\nip a s dev eth0 | sed -n 's/.*inet \\([0-9.]*\\)\\/.*/\\1/p' | head -n 1\ncat /sys/class/net/eth0/address\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## 10.10.2024 v5.0.1\nNew features:\n* Added externalUrl property in Camera app\nFixes:\n* Fixed screenUrl property in Camera app\n* Fixed bug in Camera app with open/close\n* ZMatter Binding: Thread credentials fixed\n\n## 22.07.2024 v5.0.0\nNew features:\nImprovements:\n* Matter support added\n* Zigbee: Meter cluster added (instanteneous and summation values)\n* Zigbee: WindowCovering added\n* Zigbee: isFailed added\nFixes:\n* Fixed apps active state save problem\n\n## 22.04.2024 v4.1.3\nNew features:\n* Zigbee: add support for CC Temperature-, Pressure-, RelativeHumidity- Measurement, OccupancySensor\nImprovements:\n* Cleanup vDevs in the profile\n* OpenWeather app\n  * if wingust will not be reported the value will be set to windspeed to avoid an empty value\n  * added \"minutes\" to label of refresh rate\n  * app descriptions and https\n  * added devices for using in automation\n  * changed options to pulldown\n  * added option for wind speed units\n  * added option for refresh selection\n  * added option for create temp/hum devices\n  * added option for create wind devices\nFixes:\n* Ignore ZBee in backup/restore\n* Update postfix.json (Philio PAN04, PAN06)\n\n## 18.10.2023 v4.1.2\nNew features:\n* Support for Zigbee clusters OnOff, LevelControl, ColorControl, IasZone and OccupancySensing\n* Added Zigbee support to SwitchControlGenerator\n* Allow custom IP reported from localIP.json file\nImprovements:\n* Reworked technology/bindingName/nodeId attributes of vDevs in Z-Wave/Zigbee/EnOcean/ImportRemoteHA/SwitchControlGenerator\n* defaultConfigs updated, NotificationFiltering and NotificationEmail added\n* Add Battery notifications to inbound notification\n* Be more verbose in ImportHA\nFixes:\n* Fixed double restart on zway.discover() exception\n* Fixes in Zigbee app\n* Fixed ZWave.prototype.applyPostfix error\n* Fixed firmware-fault report\n* Fixed wipeOut handler\n* Typo in getMACAddress\n* Update postfix.json\n\n## 19.07.2023 v4.1.1\nNew features:\n* Zigbee DoorLock support\nImprovements:\n* Rework of SmartStart UI\n* HomeKit: Added Battery Service\nFixes:\n* Fix missing flood sensor icon\n* Fix probeType for motion\n* Update postfix.json for FGS-213\n* Fixed firmware update of Nth chip\n* DummyDevice parseInt fix\n* Set device isFailed based on lastCommunication value\n* Correct logging of Notification channel not assigned to a user\n* Fixed WB config to use Native module\n* Fixed thermostat getCurrentTemperature\n\n## 02.05.2023 v4.1.0\nNew features:\n* Zigbee support added with Z-Wave.Me hardware\nImprovements:\n* MQTT: switchRGBW support\n* Add Battery notifications to inbound notification\n* Allow custom IP reported from localIP.json file\nFixes:\n* Fixed double restart on zway.discover() exception\n* Fixed firmware-fault report\n* Fixed wipeOut handler\n* registerNotificationChannel parseInt(user)\n* Typo in getMACAddress\n* Be more verbose in ImportHA\n* Heating App: Don't set the temperature if it is not defined\n* Postfix for Thermostat fixed\n\n## 22.12.2022 v4.0.2\nNew features:\n* Allow <deviceId:metrics:xxxx> in Notification Filtering\nImprovements:\n* Add URL to the HTTP error message\nFixes:\n* Security restore mode\n\n## 24.11.2022 v4.0.1\nImprovements:\n* Update postfix.json\n\n## 01.11.2022 v4.0.0\nNew features:\n* Full rework of Notification (Alarm) CC widgets: state events produces widgets, stateless produce hidden toggleButton\n* Dummy device:\n  * Added Door lock, Blinds, Siren and Water valve to Dummy device\n* User can generate access tokens now (for easy API integrations)\n* Added HTTP API /ZAutomation/api/v1/devices/%dev%/%property% and /ZAutomation/api/v1/devices/%dev%/metrics/%property% to cimplify integration with third part APIs\n* Postfix handling:\n  * vDev creation based on Configuration parameter with configVDev keyword\n  * vDev based on Notification Status\n  * Window Tilt pre-creation\n* Added uuid, serial and mac fields to /system/info and /system/first-access API calls\nImprovements:\n* New API /encryptionKeys for S0/S2 key extraction (for Zniffer and PC Controller)\n* Notification: improved icons\n* Notification: Added support of eventParameter for Idle\n* Allow disable packet log for slow systems: allow track & save, track only, disable (for slow hardware)\n* Home name and Remote ID added to push messages\n* Better e-mail description on device trigger\n* HomeKitGate 2.2.2\n  * automaticaly add/remove Permanently Hidden devices\n  * minor fixes\n* Added self.trigger in Easy Scripting\nFixes:\n* HTTP API response for 0 and false fixed (before was null)\n* Firmware Upgrade for target > 0 with target 0 not upgradeable\n* AutoLock: minor\n* Security app: arming/disarming schedule and many minor fixes\n* Don't start paused instances after restore\n* New users can set night_mode correctly\n* Fixed profilesByDevice to also list devices in allows room\n* Fix duplicates of Door and AC Alarms\n* Fixed defered save (produced crashes on slow hardware)\n* Set timezone\n* Remove SoundSwitch Mute vDev on device deletion\n* Fix error on logout for local user\n* Fixed default .syscommands on Linux\n* Fix RGB color set\n* Fixed DeviceHistory check period\n* Added meter events in notifications\n\n## 02.04.2022 v3.2.3\nNew features:\n* API for local token generation\n* Allow disable packet log for slow systems or big networks\n* Added uuid, serial and mac fields to /system/info and /system/first-access API calls\n* HomeKitGate setting to allow remove phantom devices\nImprovements:\n* HomeKitGate 2.2.2\n* More commands available in EasyScripting\n* localGMT for getTime API\n* More events on Websoket API (profile and room changes/remove)\nFixes:\n* Error on logout for local user\n* Security app fixes\n* Fixed default .syscommands on Linux\n* EasyScripting description fix\n* SwithcControlGenerator problem with Basic\n* Z-Wave binding stop abort on exception inside controller.device.remove\n* RGB color set\n* Remote Z-Way (ImportHA) RGBW control\n* Don't set Time to itself\n* Fixed DeviceHistory app\n* Postfixes:\n  * Philio PAT13 Temperature Sensor postfix AutoOff on the Alarm button, set Alarm On\n  * Tion 4S SwitchMultilevel.data.interviewDone\n\n## 29.11.2021 v3.2.2\nNew features:\n* Websocket API improved. Now requires same token as for HTTP API\n* Full rework of Security module\n  * Added Entrance group to allow delay for some sensors on armin and disarming\n  * Added support for scenes and buttons for arm/disarm/clear by button\n  * Added Arm condition and Arm failure action to allow checks for sensor state before arming\n* Added ClearPacketLog ZWaveAPI\n* Added duplicate field in packet log\nImprovements:\n* MQTTClient\n  * Added door lock support\n  * Added automatic re-connection\n  * Thermostats are now float, not integer\n* Added Clock.Set() and TimeParameter.Set() daily at night to keep device at home synchronized\nFixes:\n* Save defered saveObjects on Automation stop\n* Fixed homekit-skip being ignored after restart\n* Fixed bug with addTags not notifying subscribers\n* Fixed Secure thermostat and Vitrum switches support\n\n## 15.09.2021 v3.2.1\nFixes:\n* Fixed missing third (immediate) parameter in saveObject\n* Fixed bug in HomeKit with wipeout\n* Fix local user devices list\n\n## 24.05.2021 v3.2.0\nNew features:\n* New MQTTClient app for exporting all devices to MQTT\n* Added devices.wipedOut event\n* Added manufacturer, product and firmware fields to vDev\n* Added Appliance and Water Valve Notification types\n* Adopted to new WebServer API with WebSocket Auth handler and new ws.push parameter with list of IDs to be notified with the event\nImprovements:\n* Added lazy write in saveObject function to save SD card and improve engine speed\n* Full rework of applyPostfix to boost load process\n* HomeKit:\n  * Full rework to fix rooms mix-up on Z-Wave app restart\n  * Made PIN static acoss restarts\n  * Added manufacturer, product and firmware information\n* Security app:\n  * Disarm now works at any time, even if the sensor has triggered\n* Added listing of directory in modulemedia API\n* Improved speed with Date.now() instead of new Date().getTime() and new Date().valueOf()\n* Removed test ws.push for incomingPacket (improved engine speed)\n* Adopted the new lastExcludedDevice DH for proper cleanup on exclusion, zeno.unregister().\n* Improved EnOcean.prototype.dataBind (like ZWave.prototype.dataBind).\nFixes:\n* Fixed EasyScripting app UI slowdown\n* EnOcean devices do not re-appear with same name and in same room after being added back.\n* Fixed GetStatisticsData Z-Wave API and added ClearStatisticsData API.\n\n## 24.03.2021 v3.1.4\nNew features:\n* New EnOcean profiles added\n* Added DecomposeRGB module\nImprovements:\n* EnOcean: periodical save of zddx, Made API non-public by default\n* Improved Security App\n* Improved Heating App\n* ThermostatDevice: Allow calling handler from create event\n* HomeKit support improved\nFixes:\n* Fixed EnOcean duplicate devices\n* Fixed error in NotificationFiltering when Channel is absent\n\n## 09.02.2021 v3.1.3\nNew features:\n* New EnOcean profiles added\n* Added update() to EasyScripting menu\n* Added SVG content-type to the list of loadable images\n* Added ZWAYSessionCookieIgnore header to the auth API\n* Added /devices/:v_dev_id/referenced API to show references to a vDev\nImprovements:\n* Logical Rules 1.5\n* ThermostatDevice with float value\n* Improved InboundNotifications module to allow some duplicate events. General rework\nFixes:\n* Heating App: Correct start after reboot, correct handling of subsequent time slots, correct handling of rooms deletion and device load/unload\n* Heating App: The schedule follows each other without reset to energy save, also when switching to another day. Without a schedule, energy saving is activated\n* Fixed Network Reorganization infinite loop\n* Removed SensorsPolling from default config - it blocks the queue and is not needed for most of customers anymore\n* Removed empty customIcons\n* Fixed a space before namespace that lead to this type of device not being displayed in the drop list\n* Fixed that toogleButtons names were not displayed\n* Sonos app cleanup\n\n## 24.12.2020 v3.1.2\nNew features:\n* Added SimpleAV to SwitchControlGenerator\n* Added demultiplexer API call for HTTP GET request\n* Added lastSeen and IP to sessions in user profile\n* Added support for Window Tilt device\n* Added support for Alarm AC Reconnect/Disconnect widgets\n* FirmwareUpdate added support for 7th gen UZB/RaZberry\n* Added WiFiCli API for Z-Wave.Me Hub to select WiFi network\n* Added IP and RemoteID to first-access API\n* Added profileName (hub name) to MobileAppSupportAPI\n* HomeKit integration reworked and included in standard delivery\nFixes:\n* Fixed problem with local URL in Camera settings\n* Fixed battery error in EnOcean\n* Added support for EnOCean GP\n* Fixed NotificationChannelEmail not to report failure on mail send error\n* Fixed HTTP API search to always match from the beginning\n* Time driven item enabled in Heating widget\n* Heating module. Update the list of rooms after deleting a room, frostProtection field\n* Fixed moduleId in SwitchControlGenerator\n* Do not logout permanent tokens\n* Added CORS Allow-Control-Expose-Headers\n* Added Authorization to Access-Control-Expose-Headers\n* Default config.json updated\n* Improved Alarm CC handler to fix error with undefined forEach\n* Fixed FirmwareUpdate for target > 0\n* Fixed Factory Reset on a controller w/o Z-Wave running (no zway object)\n* Removed 'metrics:removed'\n* Reset vDev to globalRoom if location does not exist\n\n## 16.09.2020 v3.1.1\nFixes:\n* Automation/Climate: current temperature always Comfort\n* Added probeType to Http and Code devices\n* Added probeType: \"thermostat_set_point\"\n\n## 31.08.2020 v3.1.0\nNew features:\n* New notifications style in Automation\n* Added /notificationChannels and /notificationChannels/all API calls\n* Added namespaces:notificationChannels:channelNameEx\n* Added NotificationChannelEmail (replacement for MailNotifier), NotificationChannelSMSru (replacement for old NotificationSMSru)\n* Adopted IfThen, SecurityMode to the new notification style\n* Removed notifications from BatteryPolling - adopting new notifications style\n* Removed modules MailNotifier (replaced by NotificationChannelEmail), Notification (deprecated) and NotificationSMSru (replaced by NotificationChannelSMSru)\n* Added MobileAppSupport and NotificationFiltering.\n* Added Zniffer SetPromisc API\n* Improved Background RSSI measurement, made it more precise in time when polling\nFixes:\n* Fixed EasyScripting Loop detected issue after an error\n* Fixed NotificationChannelEmail userId saved as integer and not as string\n* Temp fix of namespaces - to be reworked\n* Added NotificationChannelEmail and improved NotificationFiltering.\n* Fixed RSSI for sent packet for Zniffer\n* Fixed bug with two dongles\n* Cleanup. CIT code removed\n* Fixed FW update via URL download\n* Allow / in last argument in API router\n* Network reorg fix\n\n## 28.04.2020 v3.0.6\nNew features:\n* EasyScripting app added\n\n## 02.04.2020 v3.0.5\nFixes:\n* Postfix Association wrapped in lastIncludedDevice check\n* Full rework of NetworkReorganization\n* Fixed incoming packet in RouteMap\n* Fixed bug in ThemostatDevice\n* Allow restore of Dummy Device value\n* Added more error logging\n* Added probeType, icon valve and siren.\n* AutomationController.loadModuleMedia handles MIME types\n\n## 20.01.2020 v3.0.4\nNew features:\n* Google Home integration\n* Added Sirent Notification/Alarm type for Goap Luxy\n* Added SoundSwitch CC support\n* Added debugPrintStack for easier debugging\n* EasyScripting app\n* Qubino Flush 1 Relay postfix\n\nFixes:\n* Fixed Base64 bug with 0D 0A -> 0A. This issue resulted in corrupted images in rooms\n* Fixed bug with Thermostat Operation toggle missing after inclusion until reboot\n* Remove redirect_uri from profile and add uniq uuid to each profile\n* Delete full profile on DELETE ZAutomation/api/v1/profile if only one token exists or only the token if there are others\n* OAuth2 profiles metadata cleanup\n* Moved devicesByUser, deviceByUser, locationsByUser and profileByUser to AutomationController\n\n## 06.09.2019 v3.0.2\nFixes:\n* location added to switchMultilevel and battery vDev types\n* Version updated\n* Fixed removal of old sessions\n* fix undefined location\n\n## 18.07.2019 v3.0.0\nNew features:\n* Implemented Authentication Bearer for OAuth2.0.\n* Permanent tokens\n* Per device access for users added\n* Making automaticaly permanent tokens with Authorization Bearer\n* Add locationName attribure to vDev\n* Thermostat commands improved\n* HTTP redirect API added\n* RemoveToken API added.\n* Rework of profiles API\n* Made session permanent and stored in config.js\n* Added new bootloader to Z-Wave OTW\n\nImprovements:\n* EnOcean improvements\n* Updated encryption function for TP Link Wifi Plugs\n* Сapability to change level of sensorMultilevel and sensorBinary, useful for CodeDevice and HTTPDevice\n* Support of postfix application for all devices of the same manufacturer\n\nFixes:\n* Do not return 404 if no rooms granted to the user. Return empty0\n* Save vDev probeType in config.json\n* ThermostatSetPoint posfix fix\n* Removed HttpOnly from the ZWaySession cookie.\n* Duplicate ZWaySession in the header\n* Timezone fixed for Raspberry Pi\n* Fixed RGBW off oldColor save\n* Added missing set of metrics:level for toggleButton\n* Old tokens cleanup fixed.\n* Do not apply Anonymous if there was and attempt to login (Auth Basic, Bearer or SESSID)\n* Remove profile on OAuth2 failures\n* Added WWW-Authenticate header to HTTP 401 reply\n* Fixed bug in MobileAppSupport leading to error\n* SwitchControlGenerator. Do not create device for CentralScene as it is handled in ZWave module\n* Merge pull request #463 from RobertGebauer/master\n* Update check of level to set: must be a number\n* SHUI-546 Fix Info Widget\n* SHUI-543 do not save unneeded instanceId in instance\n* https://github.com/Z-Wave-Me/home-automation/issues/475\n* update MobileAppSupport\n* SHUI-521 add notification to scenes\n* SHUI-534 fix silent and normal alarm\n* SHUI-519 Support to compare 2 devices\n* fix: getting new sid/session although the old session is still available,\n* add default checks to VirtualDevice function for params tags, order, location, creationTime\n* [SHUI-508] fix broken password reset\n* [SHUI-507] Rules: Fix reverse function problem with 0\n* Update check of level to set: must be a number\n* Bugfix. Level \"0\" won't be set with previous check as !!level evaluates to \"false\" for level=0. As level \"0\" should be a valid level to set, the level is checked to be a number now.\n\nAutoOff:\n * Doorlock support for AutoOff module\n\nDeviceHistory:\n * externalAPIRevoke to DeviceHistory stop function added\n\nIfThen:\n * handling dimmer correctly in IfThen\n\nNotificationSMSru:\n * Huawei 3G/4G modems support\n\n## 10.10.2018 v2.3.8\nFeatures:\n* remove uploaded room images\n* new base modules added that combine or enhance functionalities of already well known modules, which are working without Alpca JS.\n  These new modules can be find and configured in SHUI under the Automation menu (gear wheel):\n  * Hazard Notification (combination from Leakage Protection and Fire Protection modules, ready for more)\n  * Rules (combination of If>Then (simple mode) and Logical Rule (expert mode) modules)\n  * Scenes (enhancement of Light Scene module)\n  * Schedules (enhancement of Scheduled Scene module)\n  * Security (refactored and scheduling enhanced)\n  * Heating (enhanced Climate Control module)\n  * transformation added that will optionally transform LogicalRules/IfThen into Rules, LightScene into Scene, ScheduledScene into Schedules instances and deactivate all source instances - so the transformation can be rolled back easily (using http://IP:8083/ZAutomation/api/v1/modules/transform/reverse will remove the transformation flag from all modules)\n\nChanges:\n* node id to vdev of zway devices added\n* add remove location image api\n* add prepareHTTPResponse function to AutomationModule.js\n* ignore list of restore/backup functions refactored\n* ZAutomation history API removed (now it comes from the module itself)\n* storage function enhanced to remove not existing and cleared filenames from list\n* add PNG and GIF to img type check\n* QR-Code isn't stored on z-way-server anymore, it's generated on demand in UI instead (Devices > Mobile > Add)\n* add restriction to QR code API - admin can request all QR codes, users can only request their own\n* logical helper functions from Rules moved and centralized into AutomationModule.js, so also other modules can use them\n* postfix.json updated (changed or added):\n  * added:\n    * Steinel XLED home 2\n    * Steinel Senor-Switched Outdoor LightScene\n    * Foxx Project Door/Window Sensor\n    * Foxx Project Flood Sensor\n    * Everspring/TechniSat RM1\n    * Heiman Smart Smoke Sensor\n    * Aeotec NanoMote One\n    * Aeotec NanoMote Quad\n    * Aeotec TriSensor\n    * TKBHome single/dual wall switch\n    * TKBHOME single/dual dimmer switch\n    * TKB Home Energy Plug In Switch\n    * Everspring Plug\n    * Popp Power Plug\n    * MCO Home Fan Coil Thermostat (2-pipe) V3.0\n    * MCO Home CO2 Monitor\n    * Qubino 3-Phase Smart Meter\n    * Qubino Smart Plug\n\n  * changed:\n    * Philio 4 in 1 Multisensor\n    * Philio Relay Insert Blind\n    * Philio Double Relay Insert 2*1.5 kW with Metering Function\n    * Foxx Project Smart Switch Gen5\n    * POPP Flood / Water Leakage Sensor\n    * TKBHome two channel switch TZX7\n    * TKB Plug Dimmer\n    * Qubino Smart Meter\n    * Qubino Flush Thermostats\n    * Qubino On/Off thermostat\n    * Aeotec Home Energy Meter - Gen5\n    * PAN16 Smart Energy Plug In Switch\n    * Everspring Lamp Holder\n    * Poly Control Dana Lock V3\n    * OOMI Door Window Sensor\n    * MCO Home - Water Heating Thermostat with humidity sensor\n    * MCO Home - Electrical Heating Thermostat with humidity sensor\n    * Sensative Strips Comfort / Drips\n    * Hank Flood Sensor\n\nFixes:\n* ZWave v2.3.0\n  * update of failed status in zway vdevs fixed\n  * thermostat min/max fixed\n  * Public Z-Wave API with Expert UI fixed\n* postfix update fixed\n* Object.keys() error if cc.data is null fixed\n* download URL of skins fixed\n* Cannot select none image for room fixed\n* icon upload and add uppercase extension (GIF,PNG,JPG,JPEG) support fixed\n* missing transformation of main_sensor during update leads to indexOf undefined error - fixed\n\nModules:\n* ZWave v2.3.0\n  * Gas Alarm (V7) 0x12 support added\n  * new alarm type - gas added\n  * to not polute the global namespace area a var was added to postfix logic\n  * Optimized a bit the F/W update code and added support of 40196 bootloader for upgrade UZB 5.07->5.27\n* HTTPDevice v2.2.0\n  * enhancement: can set method GET/POST for update command\n  * helper fixed\n* DeviceHistory v2.0.0\n  * new api HistoryAPI added (moved from ZAutomation and AutomationController to module)\n* BindDevices v1.0.2\n  * sensorMultilevel support added\n* MailNotifier v1.2.0\n  * change logic to handle also different mail adresses in e-mail outgoing\n* BatteryPolling v2.2.0\n  * notifications support module added\n* MobileAppSupport v1.2.7\n  * table of undefined bug fixed\n\n## 23.03.2018 v2.3.7\nFeatures:\n* Added emulateOff postfix to Sensor Binary\n* support for wifiplugs added (TP-Link HS100, TP-Link HS110, EDIMAX SP1101, EDIMAX SP2101)\n* allow probeType postfix in ZWave module\n* IP-address api added\n\nChanges:\n* Set thermostat value only if they are not equal * this will prevent ClimateControl app to set values twice\n* add ip address to qrcode\n* stored QR code is removed, now it is only produced in UI temporarely against successful authorization\n* module categories \"system\" and \"wifiplug\" added\n* rework the ZAutomation/api/v1/icons/upload API to return a name\n* language files refactored\n* postfix.json updated (changed or added):\n  * added:\n    * Popp Z-Weather\n    * Z-Wave.me Dimmer\n    * Danfoss Hydronic Controller 10\n    * Aeotec RGBW Bulb\n    * Aeotec Dual Nano Switch with Meter\n    * Aeotec Indoor Siren Gen5\n    * Aeotec Door Window Sensor 6\n    * Aeotec Dual Nano Switch\n    * Aeotec Water Sensor 6\n    * Secure 7 Day Programmable Thermostat\n    * Secure Temperature Sensor\n    * Secure Wall Thermostat with LCD Display\n    * Secure Z-Wave controlled Boiler Actuator (2 Channels)\n    * Secure Receiver with Relay SSR303\n    * Philio Smart Dimmer Socket PAD02\n    * Philio Double Relay Insert 2*1.5 kW with Metering Function\n    * OOMI Mote\n    * OOMI Plug\n    * OOMI Range Extender\n    * OOMI In-Wall Switch\n    * OOMI In-Wall Dimmer\n    * OOMI Colorstripe\n    * OOMI WATERSENSOR\n    * OOMI Multisensor\n    * Everspring Temperature and Humidity Sensor\n    * Everspring Wall Plug Dimmer\n    * Everspring ST812 Flood Detector\n    * Everspring SE812 Indoor Siren\n    * Devolo Alarmsirene\n    * Devolo Luftfeuchtemelder\n    * Devolo Wassermelder\n    * Devolo Bewegungsmelder\n    * Devolo Funkschalter\n    * Devolo Radiator Thermostat\n    * Devolo Rauchmelder\n    * Devolo KFOB\n    * Devolo Wall Plug 2.0\n    * TKBHOME single/dual dimmer switch\n    * SCHWAIGER * 4 in 1 Multi Sensor Outdoor IP43\n    * Fibaro Door/Window Sensor G5 * RU\n    * Fibaro Single Switch * 1*2.5 kW\n    * Fibaro Heat Controller\n    * MCO Home PM2.5 Sensor\n    * MCO Home Water Heating Thermostat with humidity sensor\n    * MCO Home CO2 Monitor\n    * MCO Home Glass Touch Switch (4 Buttons) British Standard\n    * MCO Home Glass Touch Switch (2 Buttons) British Standard\n    * MCO Home Glass Touch Switch (1 Button)\n    * MCO Home Glass Touch Switch (2 Buttons)\n    * MCO Home * Electrical Heating Thermostat with humidity sensor\n    * Sensative Stripe Multisensor Drip\n    * BeNext Wall Plug with Dimmer Function\n    * Hank Four-Key Scene Contoller\n    * Hank One-Key Scene Contoller\n    * Hank Flood Sensor\n    * Hank Motion Sensor\n    * Hank Smart Plug\n    * NEO Coolcam Door / Window Sensor\n    * NEO Coolcam Motion Sensor\n    * NEO Coolcam Siren\n    * Steinel Indoor Light\n    * Steinel Motion Sensor\n  * changed:\n    * Fibaro Double Relay Switch FGS-222\n    * Fibaro Door/Window Sensor G5\n    * Fibaro Dimmer 2\n    * Danfoss Hydronic Controller 5\n    * Devolo Door/Window Contact\n    * Aeotec Nano Switch 1 Relay\n    * Aeotec Range Extender 6\n    * Aeotec Door Window Sensor 6\n    * Aeotec Recessed Door G5\n    * Aeotec Multisensor Gen 6\n    * Qubino On/Off thermostat\n    * Qubino Flush Thermostat\n    * Qubino Relay Insert 1*2,3 kW\n    * Qubino PWM Thermostat\n    * TKB Plug Dimmer French\n    * WiDom Universal Double Switch\n    * Philio 4 in 1 Multisensor\n    * Philio PST02-5B Motion Sensor\n    * Philio Motionsensor\n    * Philio Relay Insert Blind\n    * Philio Double Relay Insert 2x1,5KW\n    * Philio PAN16 Smart Energy Plug In Switch\n\nFixes:\n* Fix not working time-zone set via shui\n* remote triggered on Z-Way startup\n* fix setDefaultLang function\n* allow probeType postfix in ZWave module\n* save probeType in vdevInfo\n\nModules:\n* TP-Link HS100 v1.0.0\n  * added to support this wifi plug\n* TP-Link HS110 v1.0.0\n  * added to support this wifi plug\n* EDIMAX SP1101 v1.0.0\n  * added to support this wifi plug\n* EDIMAX SP2101 v1.0.0\n  * added to support this wifi plug\n* Sonos v1.2.3:\n  * fixes\n  * icon changed\n* MobileAppSupport v1.2.5:\n  * bugfix catches undefined-error occurred during adding first mobile device\n  * bugfix removing mobile device deletes LOCAL widget\n  * update IOS token\n  * remove devices manually\n* ScheduledScene v2.2.0:\n  * can start scene many times in day\n  * defined default times: 00:00 and 12:00\n  * devices on new path, as example switch: this.config.devices.switches\n  * compatibility with old config\n  * Bugfix: Dimmers, Lock and scenes didn't run.\n* IfThen v2.5.1:\n  * allow negative values for multilevel sensors\n* LightScene v1.1.1:\n  * icon changed\n* AutoLock v1.2:\n  *  added switchBinary support and checkbox Don't send Lock command if doorlock already closed\n* TamperAutoOff v1.1.0:\n  * fix to SETDATA \n\n## 04.10.2017 v2.3.6\nChanges:\n* show more logs on ZWaveBinding error\n* Refactored PacketLog to make it work faster and take smaller RAM/FLASH\n* add location title in front of device names within module configuration dropdowns\n* Modified MobileAppSupport and LogicalRules apps to push user defined notifications\n* add rain and co sensor types\n* updated underscore.js to v1.8.3,\n* add auto installer for E-Mail Me instance (is added automatically after z-way f/w upgrade if e-mail under My Settings was set and no instance is already existing)\n* E-Mail Me instance is added automatically during initial setup - e-mail is set during initial login\n* add \"zway_parsedPackets.json\" to blacklists, to be ignored during backup / restore\n* add topology restore flag to ZAutomation restore api\n* add support for fan and siren (pull request #439 by maros)\n* add removed flag to vDevs\n* add vDevs of failed nodes will be marked as metrics.isFailed:true now\n* nodes with WakeUp CC - except portable remotes - will be checked once a day if they are failed (no wake up during a specific interval)\n* add filterByNode() and filterByCreatorId() to DeviceCollection.js\n* add modules to support Technaxx TX65, TX66, TX67 cams \n* add spanish translation\n* postfix.json updated (changed or added):\n  * Popp 10 year smoke detector with siren\n  * Fibaro Door/Window Sensor G5\n  * Popp Thermostat\n  * Philio PST02-5B Motion Sensor\n  * Philio PAT02-5C Flood Sensor\n  * Foxx Project Range Extender\n  * Foxx Project Smart Switch Gen5\n  * WiDom Universal Double Switch\n  * MCO Home Fan Coil Thermostat (4-pipe)\n  * MCO Home Fan Coil Thermostat (2-pipe)\n  * TKB Plug Dimmer French\n  * Fibaro Door/Window Sensor G3\n  * Fibaro Single Switch 2\n  * Fibaro Double Switch 2\n  * NodOn Micro Smart Plug\n  * Aeotec Door/Window Sensor Gen5\n  * Popp Water Sensor\n  * Qubino Dimmerinsert 0-10V\n  * Aeotec Home Energy Meter - Gen5\n  * PAN16 Smart Energy Plug In Switch\n  * Eurotronic Spirit\n  * EVERSPRING ON/OFF Switch/Screw-In\n  * Aeotec Smart Switch 6\n  * Philio Motionsensor\n  * Fibaro Dimmer 2\n  * Aeotec Heavy Duty Switch\n  * MCOHome Thermostat MH7-WH-EU\n  * Aeotec WallMote Quad\n  * POPP Plug Dimmer\n  * Aeotec WallMote Dual\n  * TKB Plug Dimmer German\n  * Fibaro Keyfob\n  * Fibaro Wall Plug FGWPx-102\n  * Fibaro Universalsensor with Binary Input\n  * Popp Wall Plug Switch Outdoor IP44\n  * Popp Flow Stop\n  * Qubino Relay Insert 1*2,3 kW\n  * Vision Shock Sensor\n  * Popp Radiator Thermostat\n  * AEOTEC LED BULB\n  * Qubino RGBW Dimmer\n  * Vision DC/AC Power Siren\n  * Danfoss Radiator Thermostat\n  * Fibaro RGBW Module\n  * Vision Security Siren G5\n  * Qubino Weatherstation\n  * Domitech ZBulb\n  * Z-Wave.Me Wall Remote\n  * POPP Wall_C Forever - Wall Remote\n  * MCOHome Thermostat MH7-EH-EU\n  * Aeotec Nano Switch 1 Relay\n  * Aeotec Home Energy Meter - Gen5\n  * Aeotec Nano Dimmer ZW111\n  * Popp Z-Rain\n  * Aeotec Nano Switch\n  * Z-Wave.Me Funkwandschalter\n  * Fibaro CO Sensor\n  * Zipato Bulb 2\n  * Devolo Door/Window Contact\n  * Popp Solar Outdoor Siren\n  * Qubino PWM Thermostat\n  * WiDom Energy Driven Switch S/C\n  * Secure Water Meter\n  * Qubino Flush 1 Relay\n  * Qubinio Flush2 Relays\n  * TKB Home Wall Plug Switch\n  * MCO Home MH-S314 EU (UK)\n  * MCO Home CO2 Monitor\n  * MCO Home MH-S412\n  * MCO Home MH-S411\n  * MCO Home MH-S412 UK\n  * Philio 2-in-1 Sensor - Temperature and Humidity\n  * Philio 3-in-1 Sensor - Flood, Temperature and Humidity\n  * Qubino Roller Shutter Insert 2*1 kW with energy meter\n  * Qubino Dimmerinsert with energy meter\n  * Qubino Roller Shutter Insert 12-24V DC\n  * Philio Relay Insert Blind\n  * Aeotec LED Strip\n  * EverSpring Motion Sensor SP816\n  * Fibaro Door/Window Sensor 2\n  * MCOHome Thermostat MH7H-XH-EU\n  * TKB Home Power Meter Socket\n  * Everspring Door/ Window Sensor\n  * Philio Double Relay Insert 2*1.5 KW with Metering Function\n  * Danfoss Hydronic Controller\n  * Secure Z-Wave controlled Boiler Actuator (2 Channels)\n  * Secure Electronic Room Thermostat with Temperature Sensor\n  * Secure Temperature and Humidity Sensor\n  * Popp 10 year smoke detector\n  * Vision Door Lock with Handle\n  * Vision Garage Door Sensor\n  * TKB Digital Heating Thermostat\n  * Remotec IR Extender ZXT-120\n  * Fakro Electric actuator\n  * Everspring mini Plug\n  * Aeonlabs Minimote\n  * Aeonlabs Minimote\n  * POPP Keypad\n\nFixes:\n* fixed LimitedArray class\n* fix rssi output\n* fix endless timeout entries of reorganization\n* fix #442: Uncaught TypeError: Cannot read property 'filter' of undefined when getting notifications\n* ZWave: fix not working set of old multilevel value\n* ZWave: fixed that value and parameter not managed to 0\n* fix not working Hide and hasHistory of elements is after z-way restart\n* fix deleting room sensors from location is vdev moved to new location\n* fix dublicated id's if instances are cloned\n* limit max size of notifications to 2500. Old limit (5000) allowed file size over 1MB that resulted in complete cleared file after z-way restart\n* fix d&d settings are lost after z-way reboot\n\nModules:\n* DeviceHistory:\n  * remove listeners on stop\n  * fix notification bug in DeviceHistory app\n  * remove binary support from DeviceHistory app - it's handles by UI now with a better readable event list\n* MobileAppSupport v1.2.2:\n  * modified to push user defined notifications\n  * add remote/local indentification\n* LogicalRules:\n  * modified to push user defined notifications\n* Camera:\n  * add screen URl for new camera view\n* ZWave:\n  * add rain and co sensor types\n  * add replace smoke image with burglar image for burglar events\n  * fix not working set of old multilevel values\n  * fixed that value and parameter not managed to 0\n  * add isFailed flag to zway vDevs\n  * add SaveData to save once per hour\n* MailNotifier v1.2.0:\n  * extend handler to send mails initialized by IfThen and LogicalRule\n  * add checkbox to allow using an alternative email address next to the preconfigured addresses in user settings\n* LightScene v1.1.1:\n  * change icon type gesture to new type scene\n* Sonos:\n  * Added previous and next song functionality to sonos module (pull request #446 by vuza)\n* OpenWeather:\n  * Added clouds info to metrics:zwaveOpenWeather (pull request #438 by RobertGebauer)\n  * Added optional sunset / sunrise widget (inspired by pull request #229 from manyosit)\n* If/Then v2.5.0\n  * allow use of mail and push notifications if condition is triggered\n\nCIT:\n* fix missing encodeURI\n* send language keys for failed login feedback\n\n## 28.07.2017 v2.3.5\nChanges:\n* saving of notifications / z-way data refactored\n  * now manged by LimitedArray Constructor\n  * notifications file will be cleared on startup if > 1MB - this should avoid z-way-server startup problems \n* enable RSSI check only if implemented\n* ZWave\n  * ZWave module specific files are now per instance\n  * Replaced global vars by local\n  * Better Z-Wave Binding restart code to try 10 times\n  * save old color for switchRGBW in vdev, save old level for switchMultilevel (probeType: switchColor_soft_white, _cold_white, _red, _green, _blue)\n* load Cron as first module, to allow cronjob in ZWave module\n* Update IntelHex2bin.js\n* add app MobileAppSupport as system-app\n* add email.me as system-app\n* loadModuleLang refactored\n* extract unnecessary files from backup file .zab to reduce size\n* remove deprecated saveNotifications() function\n\nFeatures:\n* Support to show html page placed in folder MODULE_NAME/htdocs. You can open html page MODULE_NAME/htdocs/table.html from address: ZAutomation/api/v1/load/modulemedia/MODULE_NAME/table.html\n* BE support for background room images\n* Utils\n  * internet check added\n  * string to object parser added (and refactored in HA)\n* location added to device-info notifications\n* add periodically update of network statistics data\n* BE support for Drag and Drop\n* BE support for room main sensors (three sensors that can be assigned to room in UI)\n* Modules\n  * Icons and Title name fix for modules which generate vDevs\n* New constructor function LimitedArray added (lib/LimitedArray.js)\n\nBugfix:\n* memory problems caused by huge amount of data\n* fix zbw inquery #431\n* UZB/RaZ upgrade fixes\n* Fix updates of manufacturerId = 0 (Sigma Designs) products\n* Fixed IntelHex converter\n* Remove QR code update on profile meta data update\n\nZWaveAPI:\n* PacketLog API added\n\nZAutomationAPI:\n* add api to control ntp service\n* certfxAuth api added\n* move api's zwaveDeviceInfoGet and zwaveDeviceInfoUpdate out of ZWave module into ZAutomation API\n* vendor db API added\n\nModules:\n* HTTPDevice\n  * Added fields Content type and Data\n* InbandNotifications\n  * fix undefined scale unit of device info log\n  * fix empty level in device-info notification\n  * expand device events to include default custom icon information\n  * refactored -> remove saving and polling\n* ZWave\n  * inject zway config to ZWaveAPI\n  * expertsettings expanded + API changed\n  * zwaveDeviceInfoGet and zwaveDeviceInfoUpdate API's removed\n* SmartLight\n  * add support for old Z-Wave.Me Dimmers\n* IfThen 2.5.0\n  * Don't send On command, if device is already turned On, similarly for Off\n \nCIT\n* authentication added\n* profile management added\n* system/info API adjusted\n* configuration added (ntp, wifi, CIT name, TZ)\n\n## 18.04.2017 v2.3.4\nChanges:\n* NetworkReorganization API refactored\n* widget CloudBackup instruction\n\nFeatures:\n* ZWave: \n  * Added support of probeType GAS and WATER\n  \n## 27.03.2017 v2.3.1\nChanges:\n* Added Z-Wave module restart after UZB/RaZberry upgrade\n* box reboot refactored\n* controller function - get instances by module name added\n* Factory reset:\n  * add controller state check after SetDefault()\n  * exclude 'default' from skin uninstaller\n  * add null check to storage cleanup\n  * add notification\n* saveObject():\n  * exclude null entries\n* updateBackendConfig:\n  * add transformation that removes 'null' entries from storage content list\n* User passwords converted to salted hash (sha512)  \n\nBugfix:\n* Fixed crash on title compilation in system with multiple dongles\n* refactor error handling of broken or missing config.json / default-config.json\n* Fixed bug with door lock status not updated\n\nFeatures:\n* Z-Wave MeterPulse CC support added\n* QR code generation for login credentials added\n\nZWaveAPI:\n* CallForALLNIF API added\n* TestNode API added\n* CheckAllLinks API added\n* RSSIGet API added\n* NetworkReorganization API added\n* GetRorganizationLog API added\n* sendZWayReport API added - sends a report including z-way data and last 1000 lines of z-way-server.log\n* ZWave Backup API enhancement - optional up to latest 20000 lines of z-way-server.log can be added to backup package\n\nModules:\n* NotificationSMS.ru\n  * Added filter for notification level\n* PhilioHW\n  * improvements\n* Correct value \n  * added\n\n## 27.01.2017 v2.3.0\nChanges:\n* Added password field to all modules which use password field\n* pull request #385 from pathec/patch-websocket\n* notification api refactored:\n  * prepare redeem and delete of single or more notifications\n* add possibility to redeem or delete already redeemed notifications (via request params)\n* Postfix updated:\n * Philio PST02-5B added\n * Philio Vision PAT02-1A added\n * sensorDiscrete support updated for all CentralScene devices\n* fix debug.console\n * deactivated by default\n * JS/Run/controller.debug=true will activate console.debug output\n* lib file descriptions updated\n* more robust on config.json fault - will use default config.json instead\n\nBugfix:\n* Do not update widgets if type is Invalidated\n\nFeatures:\n* add new device type 'sensorDiscrete'\n  * n-state vDev for CentralScene CC\n  * handles triggered scene in combination with their current key attribute\n* skins api for skins ui feature support:\n  * update and install skins from https://developer.z-wave.me\n  * delete and apply skins\n  * reset skin\n* custom icons api for custom icons ui feature support:\n  * update and install icon packages from https://developer.z-wave.me\n  * upload single icons or custom icon packages locally\n  * delete and apply icons\n  * icons can be applied depending on device type and there different levels or states\n* cloud backup module for cloud backup ui feature support:\n  * only adjustable in SHUI under Configuration > Management > Backup & Restore\n  * needs deposited e-mail adress of user (Configuration > My Settings)\n  * restricted for admin users only\n  * could be triggered manually or automatically by configured schedule\n  * limited to 3 backups per box (remote id)\n  * a request for you cloud backups will verify your email against https://service.z-wave.me/cloudbackup/ and send you a response including accesses to your box backups  \n  * this feature is OPTIONAL, so you can still use the already existing backup (Configuration > Management > Backup & Restore > Download backup to your computer) \n* prepare set for timezone api\n* prepare ZWaveAPI (ZWaveDeviceInfoGet/ZWaveDeviceInfoUpdate) for DB update of device data\n* uploadModule.sh under automation/userModules added to allow upload of packed modules (tar.gz) directly from directory by ssh\n\nZWaveAPI:\n* ZMEFirmwareUpgrade:\n  * Added a way to flash ZMEFirmware from local file\n* ZMEBootloaderUpgrade:\n  * Added a way to flash ZMEBootloader from local file\n* Added Access-Control-Allow-* headers\n* new:\n  * ZWaveDeviceInfoGet ... GET\n  * ZWaveDeviceInfoUpdate ... GET\n\nZAutomation API:\n* new:\n  * /notifications ... PUT/DELETE\n  * /notifications/:notification_id ... PUT/DELETE\n  * /skins/tokens ... GET/PUT/DELETE\n  * /skins ... GET\n  * /skins/install ... POST\n  * /skins/update/:skin_id ... PUT\n  * /skins/setToDefault ... GET\n  * /skins/active ... GET (ANONYMOUS)\n  * /skins/:skin_id ... GET/PUT/DELETE\n  * /icons ... GET\n  * /icons/:icon_id ... DELETE\n  * /icons/upload ... POST\n  * /icons/install ... PUT\n  * /system/timezone ... PUT\n\nModules:\n* ImportRemoteHA 2.0.3\n  * add functionality to tag all remote widgets\n  * enhance url input to add ip adress only (with backward compatibility)\n  * bugfix: vDevs siblings (pull request #393 from xibriz) \n  * bugfix: inherit hidden or dectivated state\n  * bugfix: missing probeType\n* IfThen 2.4.0\n  * add support for Color Switch (in targets)\n  * add support for type 'sensorDiscrete' (in actions)\n  * bugfix: doesn't decide if on/off was triggered - action is still fired\n* ZWave 2.3.0\n  * add new device type 'sensorDiscrete'\n  * do not update vDev if type is Invalidated\n* InbandNotifications 1.1.0\n  * add support for type 'sensorDiscrete'\n  * some refactorings\n* Cron 1.0.0\n  * bugfix: initialization\n* PhilioHW (POPP Hub 2)\n  * no_breath option and WPS LED indication\n  * breath off by default\n* CloudBackup 0.1.2 beta\n  * added to automation/modules\n* OpenWeather 1.0.1\n  * update open weather url's\n* DummyDevice 1.0.1\n  * bugfix: NaN on switchMultilevel initialization\n  \n## 10.11.2016 v2.2.5\n* some performance enhancements in CommunicationLogger and CommunicationHistory\n\n## 21.10.2016 v2.2.4\n\nChanges:\n* pull request #372\n* pull request #342\n* update main.js (//--- Load 3d-party dependencies) for HomeGear support\n* Postfix - (ZWave module):\n * a lot of  changes in internal postfix logic\n * new configuration possibilities:\n  * change device name (new)\n  * change device icon (new)\n  * change node name (new)\n  * hide devices (new)\n  * deactivate devices (new)\n  * suppress device creation\n  * change configuration\n  * change CC data\n  * app switch controller support\n * app major minor condition changed\n * bugfix for fibaro smoke sensor postfix\n * add postfix error messages, postfix.json updated\n* Postfix - (ZWaveAPI):\n * add expertconfig and api ExpertConfigGet + ExperConfigUpdate\n * api's Postfix, PostfixUpdate, PostfixGet, PostfixRemove, PostfixAdd added\n* ZAutomation API:\n * allow also req type object as post object in login\n * fix reload of initial getFirstLoginInfo call, add showWelcome entry - affecting (rebootBox, setLogin)\n\nModules:\n* TamperAutoOff:\n * added, workaround for devices that don't deactivate tamper sensor\n* RoundRobinScenes:\n * new param added in config\n* LightMotionRockerAutocontrol:\n * some bug fixes and improvements\n* ZWave:\n * Timing statistics changed according to new IMA data\n * Added support for new bootloader and OTW to 6.70 SDK\n * new sensortypes, seismic, acceleration x, y and z added\n* IfThen\n * add Thermostat, SensorMultilevel support\n* BindDevices\n * add thermostat support\n * change name to Association\n* Notification\n * descriptions adjusted\n* AutoLock\n * pull request #319\n\nFixes:\n* Z-Wave-Me/zwave-smarthome #190\n* ZWave module:\n * Fixed Communication statistics wrong timestamp\n * Fixed non-working blind stop command\n * fix for: Second Z-Wave module not generate a widgets #369\n * bugfix: cannot read data of undefined / null (incomingPacket)\n*RemoteAccess:\n * bugfix: wrong ID after changing real ZBW ID.\n* ScheduledScene:\n * fixed bug after adding locks to the list of actions\n\n## 12.07.2016 v2.2.3\n\nChanges:\n* Allowing Basic Authentication for Ajax Requests\n* language keys updated\n* dependency / instance handling:\n * fetch undefined and failed instances to avoid error when they were adressed to global variable\n * rework loaded singleton handling - in-/activate instance will not influence that list \n * add new installed and added apps also to loadedModules list, to avoid there reinitialization\n * flags of dependency error messages changed\n * filtering in instantiateModules() changed\n* remove pushNamespaces() for emit 'destroy'\n* CHANGELOG, README, api doc updated\n\nNew features:\n* Scene support for fibaro swipe added (4 scenes)\n* Support fixes added for Philio devices: PST02-5C Door Sensor, PST02-5B Motion Sensor, PAT02-5C Flood Sensor, PSG01 Smoke Sensor\n* /system/info api added\n* LightMotionRockerAutocontrol module added\n\nFixes:\n* bugfix non working increase / decrease command in device api\n* bugfix non loaded modules - double load\n* bugfix 'cannot read property meta of undefined' in module initialization \n* minor refactoring of namespace generator\n\nModules:\n* ScheduledScene: added locks support and send Action function\n* PhilioHW: vDev added, batery charge timer\n* ZWave: alarm probeTypes changed, tamper probe type added, renamed 'door' probe type into 'door-window'\n\n## 11.04.2016 v2.2.2\n\nNew features:\n* Reset to factory default (load default config, clear storage and userModules, set z-Way controller back to factory default, logout if succesful).\n* Reset single device histories.\n* Backup / restore of userModules added (Internet connection necessary).\n* Welcome widget removed from default configs.\n\nFixes:\n* CodeDevice typo.\n* Callback execution error after calling a non existing/registered api.\n* Added correct encoding in backup.\n* Updating user profiles.\n* Issues with set() of virtual devices.\n* Too many bindings problem fixed for Alarm CC.\n* More error messages internationalized.\n\nCommand Classes:\n* Removed Basic CC from NIF, Secure NIF and Channel NIF to fit Z-Wave Plus (new in Z-Wave Plus specification).\n* MaxCmd in MultiCmd changed to 3 (thanks to buggy Danfoss RS).\n* Security Scheme Report value ignored according to spec change (new due to Z-Wave S2).\n* MultiChannelAssociation bit address fixed.\n* MultiChannelAssociation and Association are now limited by max together (sum of both groups) (clarified in Z-Wave specification).\n* Association Remove group=0 fixed according to spec (clarified in Z-Wave specification).\n\nNew Command Classes:\n* SimpleAVControl\n\nStability and security fixes:\n* Better error handling of broken instances.\n* Re-initialization of module refactored:\n * for better error handling\n * instances will be filtered and removed first\n * the module reloaded and all instances created again\n * user will get error output in events\n * instances will not be recreated, if something has broken\n* Version handling added, to check which installed App needs to be prefered (already preinstalled apps with higher version have priority).\n* Description and instances entries of default configs updated.\n* Don't backup/restore notifications.\n* instantiateModules() refactored* depending on their dependencies.\n* Refactoring creating user profiles.\n* Send device in sleep right after inclusion (to save battery).\n* Fix bug with keepAwake false on interview force.\n\nAPI changes:\n* Fixed Z-Way to start secure interview if Primary (no SIS) or if SIS itself.\n* zway.SetLearnMode and controller.SetLearnMode are back to prior to v2.2.0 syntax with true/false parameter. NWI is handled under the hood.\n* Object moduleCategories removed from config.\n* Reverted this feature \"Request NIF for devices that do not have a valid NIF after loading\" (introduced in v2.2.1) due to conflict with Security.\n* Added Function Class ExploreRequestInclusion (used internally in SetLearnMode).\n* Setting probeType refactored (moved completely in to ZWave module).\n* Remove old logic: Ignore SwitchBinary if SwitchMultilevel exists.\n\nApps:\n* SecurityMode: event 'SecurityMode.alert' added by MarioGravel.\n* LightScene: Lock support added + minor enhancements.\n* RoundRobin: update on itself to allow catching own events.\n* RemoteAccess: refactored.\n* DeviceHistory: refactored (new handling for scenes, switchControl added).\n\nDebugging tools:\n* Debug function zway_fc_application_command_handler_inject (zway.InjectPacket) to inject packet from any device like incoming from Z-Wave.\n* Debug zway.SendDataSecure to allow sending commands using Security CC (like zway.SendData but with security forced).\n* Default config in automation/defaultConfigs/config.json for factory reset. Can be used to revert to factory default after screwing up.\n\n\n## 18.02.2016 v2.2.1\n\nUI:\n* Enhanced display on mobile devices and tablets.\n* Added the ability to customize the device from Devices/Manage.\n* Backup and restore.\n* Redirect to the APP detail after module instalation.\n* Rating, download counter and comments of the Apps.\n* Improved modal windows and dropdowns.\n* Remember me checkbox on the login page.\n* Sorting Elements by title, newest....\n* Added icon to deveices list in Events.\n* Added stop button to blinds.\n\nExpert UI:\n* Network/Controller: Firmware Update page for RaZberry.\n* Size of UI optimized.\n\nNew features:\n* Request NIF for devices that do not have a valid NIF after loading.\n\nFixes:\n* Cannot add email address to user #90\n* Climate Control widget displays the correct values.\n* List elements error #82.\n* Can not install user module from store #87.\n* Fixed redirect after post/put a local app.\n* Elements are completely refactored.\n* Replaced Bootstrap modal windows and dropdowns with Angular.\n* Fix zway.devices[X].instances.length problem\n\nStability and security fixes:\n* Fixed SegFault on non-existing CC inside MultiChannel.\n* Fixed rare packet buffer corruption.\n* Fixed devices data loss on bad data from UZB/RaZberry.\n* Backup/restore problems fixed.\n* Mark CC in channel as secure if this CC on instance[0] is secure\n\nAPI changes:\n* Authentication process with Secure Login.\n* Replaced http protocol with https for external APIs.\n* Enable SIS on secondary controller after exclusion\n\n\n## 12.12.2015 v2.2.0\n\nUI:\n* Initial page forces to change default password and add email for password recovery. Password recovery by mail.\n* New design for RGB color picker.\n* Redesign of Dimmer Element. Has now 3 buttons for off, on/last state, on/full state.\n* Events can now be filtered on any device.\n* New design on Setup Menu, all Management functions are in single menu element shortening the menu.\n* New design for device management. EnOcean UI is only shown if Enocean is active, Setup and Management for all different technologies is unified now.\n* Z-Wave management now allows to remove Z-Wave device, either by Exclusion or by Removing a failed node.\n* New Info Page gives valuable data for support.\n* Dashboard Message improved if dashboard is still empty.\n* New design for all elements. They now show the room they are assigned to plus measured values are much larger.\n* Description of the bug report function added.\n* Menu icons for Elements and Rooms are twisted.\n* Whole new design of App store.\n * Now App store is open for third parties.\n * Allow update and delete of apps.\n * Apps are now grouped by theme.\n * Its possible to access private apps using token string.\n * New section \"featured\" for the most important apps.\n* Newly created elements are color marked to find them better.\n* New Icons for Thermostats and different other sensor values.\n* Elements are now ordered by name.\n* Plenty of changes to adapt to different mobile device screen sizes.\n* All devices now belong to a room. There is a wildcard room for devices not assigned yet.\n\nExpert UI:\n* Showing current license in Expert UI.\n* Description of different colors in routing table.\n* Complete redesign of Association Settings page.\n* Redirection to login page if accessed directly without login.\n\nNew features:\n* Added support for WebSocket client and server (not on all platforms yet).\n* notification2ext modules added to save notifications on external flash.\n* Asynchronous DNS resolver for http and sockets not to block JS (not on all platforms yet).\n* Support SendData to broadcast (node 255).\n* Added JS functions for AssignReturnRoute, AssignSUCReturnRoute, DeleteReturnRoute.\n\nFixes:\n* Restore functionality fixed. Make sure to update bootloader and firmware to 5.04 on UZB and RaZberry before running restore!!!\n* Conforms with latest Z-Wave Plus updated specification.\n* Fixed missing scales problem for Multilevel Sensors.\n* New scales added for Multilevel Sensors.\n* Fix incomplete read issue in system() API function.\n* Print module js file:line info when compilation error occurs.\n* Fixed SerialAPI AddNodeToNetwork and RemoveNodeFromNetwork callback mess. Need firmware 5.04 on UZB and RaZberry.\n* ReplaceFailedNode restarts full interview including Security interview.\n* ZMEFreqChange current frequency detection bug fixed.\n* Compatibility: allow setTimeout(fn, 0) which is used sometimes for deferred callbacks.\n* Fixed output of SDK version name of devices and RaZberry/UZB.\n* Remote Access rare problems fixed.\n* All device are now grouped by namespaces to allow easy selection in App settings.\n* OpenWeather now with API Key (according to changed of the service).\n\nNew Command Classes:\n* MultiChannel v4, MultiChannelAssociation v3, Association v2 support\n* ThermostatSetPoint v3\n\nStability and security fixes:\n* More stable interview with Security on slow hardware\n* Few potential crash situations fixed\n\nAPI changes:\n* zway.SetLearnMode and controller.SetLearnMode parameter can now be 0, 1 and 2 to support NWI Learn Mode. See docs.\n* lastExcludedDevice is now updated AFTER device complete removal and is now also updated in RemoveFailed success callback.\n\n\n## 04.09.2015 v2.1.1\n\nCommand Classes:\n* MCAv3 implementation added.\n* Updated CC implementation to the latest Z-Wave standards.\n\nNew features:\n* Frequency request from Z-Wave.Me stick and RaZberry.\n* Authentication added to all HTTP requests.\n* Device specific fixes applied to device inclusion.to fix minor non-interoperability.\n* Add updateOnAction and skipEventIfSameValue flags to HTTPDevice and CodeDevice\n* SwitchMultilevel value is repeatedly requested every 2 seconds until value stops changing.\n\nFixes:\n* loadObject problem fixed on Windows.\n* getsockname (detection of own IP) fixed.\n* Allow named access to command classes even without public functions (like CentralScene or Security).\n* Fix inf and nan problem in JSON* now they are null.\n* CentralScene added to controller default to allow catch them on controller.\n* zway_queue_inspect() call made public.\n* NoOperation now is now issuing an isFailed after undelivered packet and it is sent only once to battery devices (to mark as failed).\n* Many fixes in EnOcean.\n* Show only devices from allowed rooms (don't show unallocated devices),\n* Fixed authentication problems with find.z-wave.me and local user.\n* Removed status field from modules.\n* Fix devices update problem in ZAutomation API.\n* Warning (255) battery values mapped to 0\n* Fixed Thermostat F scale problem\n* LogicalRules Switch on/off action fixed\n* Sonos, RGB, SecurityMode modules fixed\n\nUI:\n* Easy installation of new modules from online store.\n* Thermostats and A/C widgets fixed.\n* Many improvements in Smart Home UI and Expert UI.\n\n\n## 28.06.2015 v2.0.1\n\nCommand Classes:\n* MultiCmd MaxNum changed to 6\n\nNew Command Classes:\n* MultiChannel v4 support\n\nStability and security fixes:\n* Don't allow to call secure commands unsecurely.\n* Fix Security Scheme Inherit.\n* Fix timers issue when clock is adjusted.\n* Fix some non-blocking socket issues in sockets.\n* Check if device still exists after SendData callback.\n* Prevent segfault when unsubscribing data holder callback from within itself\n* Restore function on 6.51.03 works again\n\nNew features:\n* Add remote peer info in WebServer.\n\nUI:\n* Remote access management added to Home Automation UI.\n* Removed UI selector page, access is possible via direct link or Info Widget\n\n\n## 29.05.2015 v2.0.1-rc33\n\nCommand Classes:\n* Make Basic CC mandatory in Secure NIF too\n* MultCmd set maxNum in Defaults.xml.\n* Ignore supported reports for already interviewed\n* SensorBinary/SensorMultilevel command classes (to fix phantom sensors).\n* Add 10 sec grace period for SensorMultilevel v1-4 when new sensor types are still accepted.\n* Support rfStateCap == 0 in Protection CC to correctly handle devices with no RF protection.\n* Update event type parent DH for Alarm/AlarmSensor CC when receiving event reports.\n\nNew Command Classes:\n* MultiChannel v4 fallback support (supported as v3).\n\nFixes:\n* Fix timers and queue hangs issue when clock is adjusted too much.\n* Fix Security scheme inherit logic.\n* Fix Alarm v3 event type mask bug.\n* Make saveObject() atomic.\n* Fix Version CC segfault on version change\n* Workaround for devices not removing Security from NIF in usecure inclusion.\n\nHome Automation:\n* Notification CC (Alarm v3) renders vDev\n* Added Sonos and GlobalCache modules\n* Users management and authentication added\n\nNew features:\n* Made queuing a bit faster: do not NACK job when received SOF while awaiting for ACK, CAN problem fixed.\n* JavaScript sockets module now supports non-blocking, asynchronous, multicast, broadcast and reusable sockets.\n* JavaScript XML module namespaces support added in findOne/findAll.\n* Added possibility to write own V8 extensions. Sample code here: http://razberry.z-wave.me/fileadmin/modsample.tgz\n* Added processPendingCallback() call in JS code (to keep callbacks working while handling slow code in JS).\n* Add UZB driver to Windows installer\n\nUI:\n* Removed Z-Way HA UI and Blue UI.\n* Made new Smart Home UI as default HA.\n\n\n## 03.02.2015 v2.0.1-rc15\n\nZ-Wave Plus certified for US (Certification Number ZC10-15010005).\n\nSupport for UZB1 added. Require additional license from license.z-wave.me (not finished yet !!!!!!).\n\nFrom now Windows is maintained as well.\n\nCommand Classes:\n* FirmwareUpdate progress added.\n* ThermostatSetPoint v3 thermostat modes added.\n* ManufacturerSpecific v2 implemented.\n\nNew Command Classes:\n* MeterPulse\n* BarrierOperator\n* Hail (used to bypass Lutron patent in some old US devices).\n\nNew features:\n* Added crypto module to JavaScript: crypto.sha256() and others (see docs).\n* Added sockets module to control third party devices via TCP and UDP (like Global Cache or Sonos).\n* Allow multi-level form serialization in http.request().\n* Add support for HTTP compression of JS responses.\n* Serve first pre-gzipped static files if present.\n* Sort devices with equal probing score alphabetically (in GuessXML).\n\nFixes:\n* Queueing made more stable. Sleeping secure devices managed better.\n* Interview made more stable:\n ** does not restart on Wakeup Notification from the device.\n ** continue interview on device wakeup.\n ** fixed problems with not all sensors rendered for SensorBinary V2.\n* Restore fixed on UZB1 and 5th gen RaZberry\n* Fixed issue with detached threads in http module.\n* Proxy can handle URLs with &. Used for some cameras.\n* Adopted latest changes in Apple HomeKit.\n* Encoding problems with Unicode in JS API.\n* Fixed problem with CRC16 and MultiCmd rendered due to corrupted packets from RF.\n* Fixed problem with wrong version of Command Class rendered during interview.\n* Fix problems caused by ether noise: ignore supported reports for already interviewed command classes.\n* Stability fixes.\n\nHome Automation:\n* Support for AlarmSensor (used in Fibaro devices and some others) in HA UI.\n* Logical Rules module can be triggered by scenes (not only by device change as previously).\n\nUI:\n* Localization added. You can translate Z-Way Homa Automation in your language in automation/lang/ and automation/modules/*/lang/.\n* RGB (SwitchColor CC) added to Z-Wave binding\n* Many small improvements in Expert UI\n* Small fixes in HA UI\n\nAPI changes:\n* SwitchColor CC now have new dataholder structure (same as other CCs with scales and types)\n* Added _ prefix to functions from z-commons library bytes_to_* and *_to_bytes to minimize risk of overload by user functions.\n* WebSocket API changed: event type added. Server can filter events based on this type before sending to clients.\n\n\n## 21.11.2014 v2.0.0\n\nZ-Wave Plus certified for EU (Certification Number ZC10-14110009).\nZ-Way can work as primary and as secondary controller (to work with other Z-Wave controllers).\nA lot of improvements and stability fixes.\n\nCommand Classes:\n* SensorMultilevel will not create phantom sclaes anymore\n* Alarm v2 fixed\n* MultiCmd adopted to fix DLC 13 problem\n* Security implements inclusion timers for secure inclusion\n* SwitchBinary and SwitchMultilevel can now work as device\n* NodeNaming UTF16 fixed\n* MultiChannel Find Instance implemented\n* AGI bugs fixed\n* Association/MultiChannelAssociation autoconfig logic changed\n* PowerLevel support added\n\nNew features:\n* Completely new software structure\n* HomeKit preliminary support. Waiting for apps in AppStore\n* Proxy implemented in the engine to pass thru WebCams and other content via find.z-wave.me\n* Websockets support\n* Syslog logging support added on Unix/Linux platforms\n* Add diagnostic messages in case of data access without a lock (for libzway users)\n* Support for new 5th gen UZB dongle and RaZberry (AutoFlashAutoProg, NMV, RFPowerLevel, SendTestFrame functions added)\n\nNew Command Classes:\n* Proprietary for few devices on the market using it\n\nMinor changes in the API:\n* FirmwareUpdate dataholders renamed\n* New controller state Resetting assigned during reset to factory process (controller.data.controllerState)\n* Replace python-style DataHolders type names in ZDDX and JS:\n   ** \"NoneType\" changed to \"empty\"\n   ** \"str\" changed to \"string\"\n   ** \"str[]\" changed to \"string[]\"\n* Data Holder JS property name is now hidden and is not returned in JS output neither in /ZWaveAPI/Data/\n* Data Holders C API changes: all \"zway_data_*(zway,\" should be changed to \"zdata_*(\"\n* Changed format of config.xml file and command line parameters. Now all Z-Wave related data moved into appropriate JS module\n* Functions loadJSON(), saveJSON() and similar moved to fs.loadJSON(), added fs.load() to load any file as string\n\nFixes:\n* SUC/SIS handling enhanced\n* Works perfectly as secondary controller\n* PowerLevel full support on 5th gen dongles/RaZberries\n* AddNodeToNetwork and RemoveNodeFromNetwork cancel hang fixed\n* Max packet size handling enhanced\n* Answer-as-requested policy implemented to conform Z-Wave Plus (for Security/MultiCmd/CRC16)\n* zway.bind with EnumerateExisting fixed\n* RemoveFailedNode and ReplaceFailedNode timeout rised\n\nUI:\n* New Expert UI. Old Blue UI kept as second option.\n* Communication statistics added for more network debugging\n* New HA UI improved, more modules added\n\nAbout New Expert UI:\n* More installer friendly\n* Works perfectly on tablets\n* Multi Channel Associations can be set in a user friendly way like simple Associations\n* Communication Statistics for advanced analysis of network stability\n* Map removed from this UI\n* Firmware Upgrade support\n\nWebServer features:\n* It is possible to run many WebServers on different port with different API and handlers\n* Proxy support: webserver.proxify(url, target, [user, passwd]) creates transparent redirect\n* WebSockets clients can receive notification from WebServer via webserver.push(obj) method\n\n\n## 26.07.2014 v1.7.2\n\nFixes and improvements:\n* Fix auth parameter in http.request()\n* Small Z-Way C core fixes and improvements\n* MeterTableMonitor historical data storage fix\n* Fix various minor issues in JS code\n* Fix DH deletion notification for array values\n* Fix memory leak in ZXmlDocument.findOne() and deviceTypeString\n* HTTP module: force adding content type for POST requests if not specified\n* Do not perform url encoding on http headers\n* Added optional timeout (ms) parameter to ZHttp\n* Correctly output JS functions as strings when returning from /JS/Run/func\n* Fix data holder value setter to work for both \"dh.value=xxx\" and \"dh=xxx\"\n\nNew features:\n* New UI selector\n* Function classed for NVM operations for 5th gen dongles (for 6.5x SDK)\n\nCommand Classes:\n* CentralScene: respond to supported get, return number of scenes from config\n* Time: respond with real time offset information, handle time offset report\n* ClimateControlSchedule: added Override Get/Set\n* Add UserCode SetRaw method for devices pretending user code to be binary.\n\nMinor change in the API:\n* givenName added to device dataholder to store names in Expert UI (for future use)\n* User Code data holder type now depends on actual code data (bnary or string)\n* Always read user code payload if present (even if status is 0)\n\n\n## 18.06.2014 v1.7.1\n\nFixes and improvements:\n* Fix memory leak in http.request().\n* Fix issues with too many threads created by many http.request().\n* Make v8 debugger not to crash on ZXmlNode objects and on CC access.\n* Minor fix of UserCode clear.\n* Delivery statistics not recorder for encapsulated packets (only for physicaly sent).\n* z-cfg-update can now convert from very config starting from v1.2.\n* Improve experience with modern secure door locks inclusion.\n* Limited callbacks count on DataHolder from JS not to overkill the server from JS and to easily find bugs in JS code.\n* DataHolder callback with notifications for child events fixed.\n\nNew features:\n* Experimental: v8 remote debugging!\n\nDebugger:\n The debugger is enabled by setting V8_DEBUG environment variable and uses port 8183 (base port + 100).\n Then you can connect either with d8 (./d8*-remote_debugger*-debugger_port=8183) or with node-inspector*-debug-port 8183.\n\n\n## 23.05.2014 v1.7.0\n\nFixes and improvements\n* Check connectivity button fixed (NoOperation is not removed by Force Interview now).\n* Mark Failed Node and Remove Failed Node not always working fixed.\n* Blue UI fixes.\n* A lot small bugs fixed...\n\nNew Command Classes:\n* PowerLevel\n* Version V2\n* FirmwareUpdate\n* ZWave+ Info\n* AssociationGroupInformation\n* DeviceResetLocally\n* CRC16\n* SwitchColor\n* CentralScene\n\nMinor change in the API:\n* Controlled only Command Classes are now also saved on server stop and loaded on starup. Allows to bind to dataholders on controlled Command Classes.\n* Added .supported datholder to all Command Classes data.\n* Battery level 255 is now mapped to 0 (so, 255 will be never seen from now).\n* Defaults.xml format changed!!!\n* xxxxxxxx-DevicesData.xml changed a bit. Added z-cfg-update utility to update xxxxxxxx-DevicesData.xml to the new format.\n* Timeouts rised for AddNodeToNetwork and RequestNodeNeighbourUpdate functions.\n\nNew features:\n* Log JavaScript files and lines on exceptions for easier debug.\n* Log possible exceptions in HTTP.\n* Open serial port exclusively to prevent multiple Z-Way or some other software running in parallel.\n* Added secureInclusion for unsecure interview (set it to false to include device insecurely)\n* Keepalive enabled in Z-Way HTTP server\n* Z-Wave+ Associations made only to Life Line group #1\n* SensorMultilevel new types implemented.\n* Blue UI ZDDX Create button.\n* Remote Access and 8084 port for maintainance added to the distribution.\n\n\n## 13.02.2014 v1.5.0-rc1\n\nNew features:\n* XML parser in JavaScript with XPath (ZXmlDocument JS object).\n* HTTP network operations implemented in JavaScript (http JS object).\n* Basic, SwitchBinary and SwitchMultilevel Set events to controller now have srcInstance and srcNode to distinguish sender.\n\nFixes and improvements:\n* Works now on new Raspbian based on 3.10.x kernels too.\n* Better network management for large networks.\n* Minimize packets flow with Secure nodes (might not work with ald Kwikset doorlock).\n* Better packet flow for sleeping secure devices.\n* Alarm and UserCode CC minor fixes.\n* Basic->SensorBinaryV1 mapping fixed.\n* Backup/Restore SDK names fixed.\n\nMinor change in the API:\n* bind() now returns just bound function instead of undefined\n* Basic dataholders lastset and mylevel removed.\n* SwitchBinary level dataholder made boolean.\n\n\n## 23.10.2013 v1.4.1\n\nNew Command Classes are implemented:\n* Alarm CC V1-3 supported (no expert UI yet).\n* MeterTable CC V2 supported (no expert UI yet).\n\nMinor change in the API:\n* SwitchBinary Set value is now boolean. \n\nNew features:\n* Communication statistics gathered in devices[N].data.lastPacketInfo\n\nFixes:\n* Sensor Binary fixed to receive changes from devices\n* Some fixes in the blue UI\n* Minor bug fixes\n\n\n## 24.09.2013 v1.4\n\nAll available UIs are shipped included now. Go to /index.html page to select a UI:\n* future UI (in development)\n* current UI (old blue for experts)\n* old jQuery mobile UI\n\nNew Command Classes are implemented:\n* ApplicationStatus\n* DoorLockLogging\n* Indicator\n* Meter v3\n* Protection v1 & v2\n* ScheduleEntryLock\n* SensorBinary v2\n* SensorConfiguration\n* ThermostatFanMode\n* ThermostatFanState\n* ThermostatOperatingState v2\n* TimeParameters\n\nHome automation engine poject started (code in development, stored on https://github.com/Z-Wave-Me/home-automation)\n\nImportant API changes:\n* loadJSON function added to API to allow load a file from program folder.\n* Command Class SensorBinary data tree has changed. Now it contains sensor types like SensorMultilevel.\n* SwitchMultilevel commands SetWithDuration and StartLevelChangeWithDuration are removed (Set and StartLevelChange should be used). \n* SwitchMultilevel Set/StartLevelChange are always with duration in C.\n* New ChildCreated event on dataholder added to trap new child node cration.\n* New JavaScript methods: fs.list(dir) and fs.stat(file).\n\nFixes:\n* ThermostatSetPoint, SensorMultilevel, Meter UserCode improved, some minor problems fixed.\n* Full RF power during inclusion/exclusion is restored.\n* Thermostat temperature C/F conversion fixed (mostly for US products)\n\nOther features:\n* New V8 engine is used for better stability and performance. The code was reworked a lot to become faster and more stable.\n* Better logging with log levels (check config.xml).\n\nNB! You need to force interview for all devices with SensorBinary and SensorMultilevel Command Classes.\nGo to Device Configuration tab, toggle Expert mode (bottom right corner) and press Force Interview under Advanced actions cut link.\n\nNB! After backup & restore process it is recommended to re-install Z-Way (using same command as to install it).\nOtherwise it might not run next time after restore. (due to old config/Defaults.xml comming from old package).\n\n \n## 19.05.2013 v1.3.1\n\nNew feature:\n* Backup/Restore implemented. You can restore config files only or full Z-Wave topology.\n \n\n## 17.05.2013 v1.3\n\nNew features and improvements:\n* Full Security support with all certified locks (tested with Kwikset, Vision Security, Yale)\n* Communications with Danfoss living connect tuned to stop battery drain by the thermostat (full re-inclusion is required to heal Danfoss living connect!).\n* Better performance and memory footprint. We have made major refactor of our Z-Wave engine to make it faster and more memory efficient!\n* Better queue handling for failed nodes preventing them from blocking the full queue. Now even unpowered or failed devices in your network will not affect user experience anymore.\n* Added public method in C and JS API to check if command class is supported.\n* Release information stored in Z-Way library.\n\nNew Command Classes:\n* MultiChannel v3\n* SceneActivation\n* SceneControllerConf\n* SceneActuatorConf\n* Clock\n* Time\n\nBug fixes:\n* fix of system() call in JavaScript\n* UserCode.Set()\n* crash on broadcast Basic.Set\n* potential problems with Add/RemoveNodeFromNetwork/ControllerChange/CreateNewPrimary/RemoveFailedNode Function Calls.\n\nChanges in frontend:\n* Translations to Spanish, Russia, Deutsch. We will appreciate your help to translate our UI to your language.\n* Thermostat UI fixed.\n\nMajor changes in software design:\n* devices[x].data.ZDDXMLLang and devices[x].data.ZDDXML removed: client must load the file called devices[x].data.ZDDXMLFile.value from the backend and parse the language content.\n \n!NB Some devices might require interview force to show properly Expert Commands and configuration parameters!\n \n\n## 29.03.2013 v1.2\n\nNew Command Classes:\n* SenorMultilevel V5 support (NB! Structure of SenorMultilevel data holder changed for all versions of this Command Class)\n\nNew features:\n* /ZWaveAPI/Run/[...].data.[...] now returns dataholder tree in same structure as /ZWave/Data/[...]\n* shortcuts for CCs on device and instance in JS syntax: you can now write devices[5].Basic.Set(255) instead of devices[5].instances[0].commandClasses.Basic.Set(255)* both \"commandClasses\" and \"instanes[0]\" can be omitted\n\nFixes:\n* Unnecessary Command Classes on devices removed\n* Queue handling after restart\n* Line endings in ZDDX that caused UI to stop working\n* More sanity checks to prevent crashes\n \n\n## 04.03.2013 v1.1\n\nNew features:\n* Z-Wave secure door locks support\n\nNew Command Classes:\n* Security\n* DoorLock\n* UserCode\n\nNew methods in JavaScript to make more fun with JS. See documentation on documentation RaZberry page.\nMinor bug fixes.\n\n# Release 1.0.1 (in progress)\n\n* Removed `actions` and `metrics` properties from the `module.json` of all modules.\n* Module classes automatically loaded to the controller. Removed `modules` property from the `config.json`.\n* Introduced `skip` property to the `module.json` which instructs AutomationController to skip module class loading.\n* Introduced `autoloadPriority` property to the `module.json` which determines automatic module instantiation order (lower** the sooner).\n* Introduced `caps` property to the Virtual Device which allows to list device capabilities.\n* Widgets moved to the new CommonWidgets module. Creation and registering custom widgets made possible.\n* Module's templates and htdocs folders now resides in ./templates/<ModuleName> and ./htdocs/modules/<ModuleName>\n* `config.json` existence checking on startup\n* New configuration setting `vdevInfo` allows to set human-readable device names and tags\n* Introduced icon VDev metric\n* Introduced `VirtualDevice.deviceTitle` & `VirtualDevice.deviceIcon` methods\n* VirtualDevice now requires `init()` to be called after instantiation\n* Widget's htdocs and Module's templates moded outside of the module's folder (for all modules)\n* Introduced .caps vDev's property which contains device extended capabilities tags (take a look at BatterPolling module)\n* Introduced className property in the widget's meta-description which allows to set custom widget className (essential to custom widgets)\n* UI is now capable of showing widgets created and registered by the customer\n* Renamed AutomationController.widget* to AutomationController.widgetClass* and changed widget subsystem behaviour to resolve ambiguity\n* /ZAutomation/api/widgets/ now replies with widget classes definitions instead of widgets itself. Latter exists and creates only on the client-side, but exact widget's class names described in a vDevs.\n* UI Dashboard refactored according to widgets subsystem changes\n* Fixed bug with loading ZWaveDoorlockDevice. DoorlockWidget implemented.\n* Added `exact` command to the MultilevelSwitch\n* SwitchBinary & SwitchMultilevel now has equal deviceType (switch) and different deviceSubTypes\n* Added tags and locations subsystems\n* Added support multi-profiles\n* Added control widgets position\n* Refactored API (devices, locations) and added new methods (modules, profiles)\n\n# Release 1.0.0\n\n(initial)\n"
  },
  {
    "path": "README.md",
    "content": "Z-Way Home Automation Engine\n====================================\n\n# Introduction #\n<a href=\"https://gitter.im/Z-Wave-Me/home-automation?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge\">\n  <img src=\"https://badges.gitter.im/Join Chat.svg\" alt=\"Join Chat on Gitter\">\n</a>\n\n## Available WebUI's: \n* Smart Home UI: https://github.com/Z-Wave-Me/zwave-smarthome\n* Smart Home Lite UI: https://github.com/Z-Wave-Me/z-wave-smarthome-lite/tree/mobile\n* Expert UI: https://github.com/Z-Wave-Me/ExpertUI\n\n## Pull Requests\nFor a better integration during running developments, please use [Home Automation develop branch](https://github.com/Z-Wave-Me/home-automation/tree/develop) for your pull requests.\n\n## Complete Documentation:\n* [Z-Way Manual](https://z-wave.me/manual/z-way)\n\n## Home Automation Documentation's:\n* https://github.com/Z-Wave-Me/home-automation/wiki\n\n## API Documentation:\n#### ZAutomation:\n* http://docs.zwayhomeautomation.apiary.io/ (still in work)\n\n## Issues, bugs and feature requests are welcome: \n* [Home Automation issues](https://github.com/Z-Wave-Me/home-automation/issues)\n* [Smart Home UI issues](https://github.com/Z-Wave-Me/zwave-smarthome/issues)\n* [Expert UI issues](https://github.com/Z-Wave-Me/ExpertUI/issues)\n* [Z-Way core issues](https://github.com/Z-Wave-Me/z-way-issues/issues)\n\n## Available Z-Way Server Downloads:\n* https://storage.z-wave.me/z-way-server/\n\n## Current changelog's:\n* [Home Automation changelog](https://github.com/Z-Wave-Me/home-automation/blob/master/CHANGELOG.md)\n* [Smart Home UI changelog](https://github.com/Z-Wave-Me/zwave-smarthome/blob/master/README.md)\n* [Expert UI changelog](https://github.com/Z-Wave-Me/ExpertUI/blob/master/README.md)\n* [Full Z-Way changelog](https://storage.z-wave.me/z-way-server/ChangeLog)\n\n## Z-Wave.Me - Developer Console (App Store)\nCreate an account and upload your own Z-Way home automation apps, share them with a special group or verify them for public access.\n* https://developer.z-wave.me/\n\nThere are also some How To's about creating own apps for home automation and what to be considered during creating virtual Devices.\n* [Help and How To's](https://developer.z-wave.me/?uri=help)\n* also checkout the tab Upload-Process to see how it works\n\nYou can also find a list of all [currently published apps](https://developer.z-wave.me/?uri=public#/web/apps) \n## Discussion platforms:\n* https://forum.z-wave.me/ (discussions available in en/de/ru/fr/it/cn, use General or RaZberry forums)\n\n"
  },
  {
    "path": "StorageProvider.js",
    "content": "/*** Main Automation storage module *****************************************\n\nVersion:\n-------------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nCopyright: (c) ZWave.Me, 2014\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- ZAutomationStorageWebRequest\n// ----------------------------------------------------------------------------\n\nfunction ZAutomationStorageWebRequest () {\n\tZAutomationStorageWebRequest.super_.call(this);\n\n\tthis.allow_extensions = ['jpg', 'jpeg', 'png', 'gif', 'svg'];\n\tthis.res = {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json; charset=utf-8\"\n\t\t},\n\t\tbody: null\n\t}\n};\n\ninherits(ZAutomationStorageWebRequest, ZAutomationWebRequest);\n\nZAutomationStorageWebRequest.prototype.statusReport = function () {\n\treturn function () {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: \"OK\",\n\t\t\tcode: 200\n\t\t};\n\n\t\tthis.initResponse(reply);\n\t}\n}\n\nZAutomationStorageWebRequest.prototype.uploadFileFunc = function () {\n\tvar self = this;\n\n\treturn function () {\n\t\tvar reply = {\n\t\t\t\terror: 'Permission dendied',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 403\n\t\t\t};\n\t\t\t\n\t\tif (req.role === controller.auth.ROLE.ADMIN) {\n\t\t\tvar file = self.req.body.file,\n\t\t\t\tdate = new Date(),\n\t\t\t\textension = file.name.split('.').pop().toLowerCase(),\n\t\t\t\tfileName,\n\t\t\t\ttype;\n\n\t\t\treply = {\n\t\t\t\terror: 'Allow extensions ' + self.allow_extensions.join(','),\n\t\t\t\tdata: null,\n\t\t\t\tcode: 400\n\t\t\t};\n\t\t\t\n\t\t\tif (extension === 'jpg') {\n\t\t\t\textension = 'jpeg';\n\t\t\t}\n\t\t\tfileName = 'storage-' + (+date / 1000).toFixed(0) + '.' + extension;\n\t\t\t\n\t\t\tif (self.allow_extensions.indexOf(extension) !== -1) {\n\t\t\t\ttype = 'image/' + extension;\n\t\t\t\tfile.type = type;\n\t\t\t\tfile.createdAt = date.toJSON();\n\n\t\t\t\tsaveObject(fileName, file, true);\n\n\t\t\t\treply = {\n\t\t\t\t\terror: null,\n\t\t\t\t\tdata: {\n\t\t\t\t\t\turi: '/ZAutomation/storage/' + fileName,\n\t\t\t\t\t\toriginalName: file.name,\n\t\t\t\t\t\tlength: file.length,\n\t\t\t\t\t\ttype: type\n\t\t\t\t\t},\n\t\t\t\t\tcode: 200\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tself.initResponse(reply)\n\t}\n};\n\nZAutomationStorageWebRequest.prototype.getFileFunc = function (fileId) {\n\tvar self = this;\n\n\treturn function () {\n\t\tvar file = loadObject(fileId),\n\t\t\tifNoneMatch = self.req.headers.hasOwnProperty('If-None-Match');\n\n\t\tif (file && !ifNoneMatch) {\n\t\t\tself.res.headers = {\n\t\t\t\t'Content-Type': file.type,\n\t\t\t\tETag: 'W/' + fileId + file.createdAt,\n\t\t\t\t'Cache-Control': 'public, max-age=31536000',\n\t\t\t\t'Last-Modified': (new Date(file.createdAt)).toUTCString()\n\t\t\t};\n\t\t\tself.res.body = file.content;\n\t\t\tself.res.code = 200;\n\t\t} else if (file && ifNoneMatch && self.req.headers['If-None-Match'] === 'W/' + fileId + file.createdAt) {\n\t\t\tself.res = {\n\t\t\t\tstatus: 304,\n\t\t\t\theaders: {\n\t\t\t\t\t\"API-Version\": \"2.0.1\",\n\t\t\t\t\t'Content-Type': file.type\n\t\t\t\t},\n\t\t\t\tbody: ''\n\t\t\t};\n\t\t} else {\n\t\t\tself.initResponse({\n\t\t\t\tdata: null,\n\t\t\t\terror: 'File isn\\'t found',\n\t\t\t\tcode: 404\n\t\t\t});\n\t\t}\n\t}\n};\n\nZAutomationStorageWebRequest.prototype.dispatchRequest = function (method, url) {\n\n\t// Default handler is NotFound\n\tvar self = this,\n\t\thandlerFunc = this.NotFound;\n\n\t// ---------- Test exact URIs ---------------------------------------------\n\tif (\"GET\" === method && \"/status\" === url) {\n\t\thandlerFunc = self.statusReport();\n\t} else if (\"POST\" === method) {\n\t\thandlerFunc = self.uploadFileFunc();\n\t}\n\n\t// ---------- Test regexp URIs --------------------------------------------\n\tvar re, reTest, fileId;\n\n\t// --- Perform vDev command\n\tif (handlerFunc === this.NotFound) {\n\t\tre = /\\/(.+)/;\n\t\treTest = re.exec(url);\n\t\tif (!!reTest) {\n\t\t\tfileId = reTest[1];\n\t\t\tif (\"GET\" === method && !!fileId) {\n\t\t\t\thandlerFunc = self.getFileFunc(fileId);\n\t\t\t} else {\n\t\t\t\thandlerFunc = self.uploadFileFunc();\n\t\t\t}\n\t\t}\n\t}\n\n\t// --- Proceed to checkout =)\n\treturn handlerFunc;\n};\n"
  },
  {
    "path": "Utils.js",
    "content": "// Comon utilities and functions\n\nvar console = {\n\tlog: debugPrint,\n\twarn: debugPrint,\n\terror: debugPrint,\n\tdebug: debugPrint,\n\tlogJS: function () {\n\t\tvar arr = [], pretty = undefined;\n\t\tfor (var key in arguments) {\n\t\t\tif (key == 0 && arguments[key] === \"pretty\") { // unstrict key == 0 since it is a string\n\t\t\t\tpretty = \"  \";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tarr.push(JSON.stringify(arguments[key], undefined, pretty));\n\t\t}\n\t\tdebugPrint(arr);\n\t},\n\tlogJSP: function() {\n\t\tArray.prototype.unshift.call(arguments, \"pretty\");\n\t\tconsole.logJS.apply(null, arguments);\n\t}\n};\n\nfunction inherits(ctor, superCtor) {\n\tObject.defineProperty(ctor, \"super_\", {\n\t\tvalue: superCtor,\n\t\tenumerable: false,\n\t\twritable: false,\n\t\tconfigurable: false\n\t});\n\tctor.prototype = Object.create(superCtor.prototype, {\n\t\tconstructor: {\n\t\t\tvalue: ctor,\n\t\t\tenumerable: false,\n\t\t\twritable: true,\n\t\t\tconfigurable: true\n\t\t}\n\t});\n}\n\nfunction in_array(array, value) {\n\treturn -1 !== array.indexOf(value);\n}\n\nfunction is_function(func) {\n\treturn !!(func && func.constructor && func.call && func.apply);\n}\n\nfunction has_key(obj, key) {\n\treturn -1 !== Object.keys(obj).indexOf(key);\n}\n\nfunction get_values(obj) {\n\tvar res = [];\n\n\tObject.keys(obj).forEach(function (key) {\n\t\tres.push(obj[key]);\n\t});\n\n\treturn res;\n}\n\nfunction byteArrayToString(data) {\n\tif (typeof ArrayBuffer !== 'undefined' && (data instanceof ArrayBuffer)) {\n\t\tdata = new Uint8Array(data);\n\t}\n\n\tvar output = \"\";\n\tfor (var i = 0; i < data.byteLength; i++) {\n\t\toutput += String.fromCharCode(data[i]);\n\t}\n\treturn output;\n}\n\nfunction byteArrayToHexString(data) {\n\tvar output = \"\";\n\tfor (var i = 0; i < data.byteLength; i++) {\n\t\toutput += ('0' + data[i].toString(16)).slice(-2);\n\t}\n\treturn output;\n}\n\nfunction generateSalt() {\n\treturn Base64.encode(byteArrayToString(crypto.random(64)));\n}\n\nfunction hashPassword(password, salt) {\n\treturn Base64.encode(byteArrayToString(crypto.sha512(password + salt)));\n}\n\nfunction has_higher_version(newVersion, currVersion) {\n\tvar isHigher = false,\n\t\tnewVersion = newVersion && newVersion.toString() ? newVersion.toString().split('.') : null,\n\t\tcurrVersion = currVersion && currVersion.toString() ? currVersion.toString().split('.') : null;\n\n\tif (!!newVersion && !!currVersion) {\n\t\tfor (var i = 0; i < currVersion.length; i++) {\n\t\t\tif ((parseInt(currVersion[i], 10) < parseInt(newVersion[i], 10)) || ((parseInt(currVersion[i], 10) <= parseInt(newVersion[i], 10)) && (!currVersion[i + 1] && newVersion[i + 1] && parseInt(newVersion[i + 1], 10) > 0))) {\n\t\t\t\tisHigher = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn isHigher;\n}\n\n/*\n * Iterate trough object, find the key and change its value\n * will change all keys that are equal to key\n */\nfunction changeObjectValue(obj, key, value) {\n\tvar objects = [];\n\n\tfor (var i in obj) {\n\n\t\tif (!obj.hasOwnProperty(i)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// arrays and objects are treated as objects  \n\t\tif (!!obj[i] && typeof obj[i] === 'object') {\n\t\t\tobjects = objects.concat(changeObjectValue(obj[i], key));\n\t\t} else if (i === key) {\n\t\t\tobj[i] = value;\n\t\t}\n\t}\n\treturn obj;\n}\n\nvar Base64 = {\n\t_keyStr: \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\n\tencode: function (e) {\n\t\tvar t = \"\";\n\t\tvar n, r, i, s, o, u, a;\n\t\tvar f = 0;\n\t\te = Base64._utf8_encode(e);\n\t\twhile (f < e.length) {\n\t\t\tn = e.charCodeAt(f++);\n\t\t\tr = e.charCodeAt(f++);\n\t\t\ti = e.charCodeAt(f++);\n\t\t\ts = n >> 2;\n\t\t\to = (n & 3) << 4 | r >> 4;\n\t\t\tu = (r & 15) << 2 | i >> 6;\n\t\t\ta = i & 63;\n\t\t\tif (isNaN(r)) {\n\t\t\t\tu = a = 64\n\t\t\t} else if (isNaN(i)) {\n\t\t\t\ta = 64\n\t\t\t}\n\t\t\tt = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)\n\t\t}\n\t\treturn t\n\t},\n\tdecode: function (e) {\n\t\tvar t = \"\";\n\t\tvar n, r, i;\n\t\tvar s, o, u, a;\n\t\tvar f = 0;\n\t\te = e.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\t\twhile (f < e.length) {\n\t\t\ts = this._keyStr.indexOf(e.charAt(f++));\n\t\t\to = this._keyStr.indexOf(e.charAt(f++));\n\t\t\tu = this._keyStr.indexOf(e.charAt(f++));\n\t\t\ta = this._keyStr.indexOf(e.charAt(f++));\n\t\t\tn = s << 2 | o >> 4;\n\t\t\tr = (o & 15) << 4 | u >> 2;\n\t\t\ti = (u & 3) << 6 | a;\n\t\t\tt = t + String.fromCharCode(n);\n\t\t\tif (u != 64) {\n\t\t\t\tt = t + String.fromCharCode(r)\n\t\t\t}\n\t\t\tif (a != 64) {\n\t\t\t\tt = t + String.fromCharCode(i)\n\t\t\t}\n\t\t}\n\t\tt = Base64._utf8_decode(t);\n\t\treturn t\n\t},\n\t_utf8_encode: function (e) {\n\t\tvar t = \"\";\n\t\tfor (var n = 0; n < e.length; n++) {\n\t\t\tvar r = e.charCodeAt(n);\n\t\t\tif (r < 128) {\n\t\t\t\tt += String.fromCharCode(r)\n\t\t\t} else if (r > 127 && r < 2048) {\n\t\t\t\tt += String.fromCharCode(r >> 6 | 192);\n\t\t\t\tt += String.fromCharCode(r & 63 | 128)\n\t\t\t} else {\n\t\t\t\tt += String.fromCharCode(r >> 12 | 224);\n\t\t\t\tt += String.fromCharCode(r >> 6 & 63 | 128);\n\t\t\t\tt += String.fromCharCode(r & 63 | 128)\n\t\t\t}\n\t\t}\n\t\treturn t\n\t},\n\t_utf8_decode: function (e) {\n\t\tvar t = \"\";\n\t\tvar n = 0;\n\t\tvar r = c1 = c2 = 0;\n\t\twhile (n < e.length) {\n\t\t\tr = e.charCodeAt(n);\n\t\t\tif (r < 128) {\n\t\t\t\tt += String.fromCharCode(r);\n\t\t\t\tn++\n\t\t\t} else if (r > 191 && r < 224) {\n\t\t\t\tc2 = e.charCodeAt(n + 1);\n\t\t\t\tt += String.fromCharCode((r & 31) << 6 | c2 & 63);\n\t\t\t\tn += 2\n\t\t\t} else {\n\t\t\t\tc2 = e.charCodeAt(n + 1);\n\t\t\t\tc3 = e.charCodeAt(n + 2);\n\t\t\t\tt += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);\n\t\t\t\tn += 3\n\t\t\t}\n\t\t}\n\t\treturn t\n\t}\n};\n\nvar formRequest = {\n\t_randomString: function () {\n\t\tvar chars = \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\";\n\t\tvar rString = '';\n\t\tfor (var i = 0; i < 15; i++) {\n\t\t\tvar rnum = Math.floor(Math.random() * chars.length);\n\t\t\trString += chars.substring(rnum, rnum + 1);\n\t\t}\n\t\treturn rString;\n\t},\n\tsend: function (formElements, method, url) {\n\t\tvar boundary = \"----WebKitFormBoundary\" + formRequest._randomString();\n\t\tvar obj = {};\n\t\t// set method\n\t\tobj.method = method;\n\t\t// set headers\n\t\tobj.headers = {\n\t\t\t\"Content-Type\": \"multipart/form-data; boundary=\" + boundary\n\t\t};\n\t\t// set url\n\t\tobj.url = url;\n\t\t// init data\n\t\tobj.data = \"\";\n\t\t// create form boundary\n\t\tfor (var index in formElements) {\n\t\t\tobj.data += '--' + boundary + '\\r\\n';\n\t\t\tobj.data += 'Content-Disposition: form-data; name=\"' + formElements[index].name + '\"' + (formElements[index].filename ? ('; filename=\"' + formElements[index].filename) + '\"' : '') + '\\r\\n';\n\t\t\tobj.data += formElements[index].type ? ('Content-Type: ' + formElements[index].type + '\\r\\n\\r\\n') : '\\r\\n';\n\t\t\tobj.data += formElements[index].value + '\\r\\n';\n\t\t}\n\t\t;\n\t\t// end of boundary\n\t\tobj.data += '\\r\\n--' + boundary + '--\\r\\n';\n\t\t// return cloud server response\n\t\treturn http.request(obj);\n\t}\n};\n\nfunction getHRDateformat(now) {\n\tvar ts = now.getFullYear() + \"-\";\n\tts += (\"0\" + (now.getMonth() + 1)).slice(-2) + \"-\";\n\tts += (\"0\" + now.getDate()).slice(-2) + \"-\";\n\tts += (\"0\" + now.getHours()).slice(-2) + \"-\";\n\tts += (\"0\" + now.getMinutes()).slice(-2);\n\n\treturn ts;\n};\n\nfunction checkBoxtype(type) {\n\tvar match = false;\n\n\ttry {\n\t\tvar bT = system('cat /etc/z-way/box_type');\n\n\t\tbT.forEach(function (bType) {\n\t\t\tmatch = typeof bType === 'string' && (bType.indexOf(type) > -1 || bType === type) ? true : false;\n\t\t});\n\t} catch (e) {\n\t}\n\n\treturn match;\n};\n\nfunction parseToObject(object) {\n\treturn object && typeof object === \"string\" ? JSON.parse(object) : object;\n};\n\nfunction checkInternetConnection(host_url) {\n\tvar cn = false,\n\t\tresponse = 'in progress',\n\t\td = Date.now() + 15000; // wait not more than 15 sec\n\n\t// try to reach google to check for internet connection\n\thttp.request({\n\t\turl: host_url,\n\t\tasync: true,\n\t\tsuccess: function (res) {\n\t\t\tresponse = 'done';\n\t\t\tcn = true;\n\t\t},\n\t\terror: function (res) {\n\t\t\tresponse = 'failed';\n\t\t}\n\t});\n\n\t// wait for response\n\twhile (Date.now() < d && response === 'in progress') {\n\t\tprocessPendingCallbacks();\n\t}\n\n\tif (response === 'in progress') {\n\t\tresponse = 'failed';\n\t}\n\n\treturn cn;\n};\n\n/*\n* check for true / false\n* also if the variable is from type string e.g. 'true' / 'false'\n*/\nfunction retBoolean(boolean) {\n\tif (boolean === true || boolean === 'true') {\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\n* find the smallest not assigned value (integer) of a specific key within array objects\n*/\nfunction findSmallestNotAssignedIntegerValue (array, key) {\n\tvar value = 1,\n\t\tmaxValue = null,\n\t\tlistValues = [];\n\n\tlistValues = array.map(function(entry) {\n\t\treturn Number.isInteger(entry[key]) ? entry[key] : parseInt(entry[key],10);\n\t});\n\n\tmaxValue = Math.max.apply(null, listValues);\n\n\tfor (var i = 1; i <= maxValue; i++) {\n\t\tif (listValues.indexOf(i) < 0) {\n\t\t\tvalue = i;\n\t\t\tbreak;\n\t\t} else if (i == maxValue) {\n\t\t\tvalue = i + 1;\n\t\t}\n\t}\n\n\treturn value;\n};\n\n/*\n * transform the publicKey into usual dsk format: xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx \n */\n function transformPublicKeyToDSK (publicKey) {\n \tvar dsk = '';\n\n \tif (_.isArray(publicKey) && publicKey.length > 0) {\n \t\tdsk = publicKey.map(function(x, i, a) { if (i % 2 == 0) return x * 256 + a[i + 1]; }).filter(function(x) { return x != undefined; }).map(function(x) { return (\"00000\" + x).slice(-5); }).slice(0, 8).join('-');\n \t}\n\n \treturn dsk;\n }\n\n\n/*\n * Dump object and fix circular references to output it\n * (for debug purposes)\n */\nfunction dumpObject(obj, ancetors) {\n\tif (typeof obj !== \"object\") return obj;\n\tif (obj === null) return null;\n\tif (obj === undefined) return undefined;\n\t\n\tvar result = Array.isArray(obj) ? [] : {} ;\n\tvar keys = Object.keys(obj);\n\t\n\tif (!ancetors) ancetors = [];\n\t\t\n\tfor (var i in keys) {\n\t\tvar key = keys[i];\n\t\tif (typeof obj[key] === \"object\") {\n\t\t\tvar circular = false;\n\t\t\t\n\t\t\tfor (var j in ancetors) {\n\t\t\t\tif (obj[key] === ancetors[j]) {\n\t\t\t\t\tcircular = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (circular) {\n\t\t\t\tresult[key] = \"circular reference to ancetor (\" + (ancetors.length - j) + \" up)\";\n\t\t\t} else {\n\t\t\t\tvar new_ancetors = ancetors.slice(); // copy array\n\t\t\t\tnew_ancetors.push(obj);\n\t\t\t\tresult[key] = dumpObject(obj[key], new_ancetors);\n\t\t\t}\n\t\t} else {\n\t\t\tresult[key] = obj[key];\n\t\t}\n\t}\n\t\n\treturn result;\n}\n\nfunction debugPrintStack() {\n\ttry {\n\t\tthrow new Error(\"Printing stack trace\");\n\t} catch(e) {\n\t\tconsole.log(e.stack);\n\t}\n}\n"
  },
  {
    "path": "Webserver.js",
    "content": "/*** Initialize Webserver and Handlers *****************************************\n\n Version:\n -------------------------------------------------------------------------------\n Author: Serguei Poltorak <ps@zwave.me>\n Copyright: (c) ZWave.Me, 2015\n\n ******************************************************************************/\n\nws = new WebServer(8083, function(req) {\n\tif (req.method === \"OPTIONS\") {\n\t\treturn this.addHTTPHeaders({\n\t\t\tstatus: 200\n\t\t});\n\t}\n\n\tvar found = ws.find(req);\t\n\tif (found) {\n\t\tvar auth = controller.auth.resolve(req, found.role);\n\t\tif (!auth) {\n\t\t\treturn this.addHTTPHeaders({\n\t\t\t\tstatus: 401,\n\t\t\t\tbody: \"Not logged in\"\n\t\t\t});\n\t\t} else if (controller.auth.isAuthorized(auth.role, found.role)) {\n\t\t\treturn this.addHTTPHeaders(ws.execute(found.name, req, auth));\n\t\t} else {\n\t\t\treturn this.addHTTPHeaders({\n\t\t\t\tstatus: 403,\n\t\t\t\tbody: 'Permission denied'\n\t\t\t});\n\t\t}\n\t}\n\t\n\treturn null;\n}, function(req) {\n\tvar auth = controller.auth.resolve(req, controller.auth.ROLE.USER);\n\tif (!auth) {\n\t\treturn 0; // there is no profile with Id = 0\n\t} else {\n\t\treturn auth.user;\n\t}\n}, function(user, msg) {\n\tvar obj = JSON.parse(msg);\n\t\n\tvar profile = controller.getProfile(user);\n\t\n\tif (profile && obj.event === \"httpEncapsulatedRequest\") {\n\t\tvar role = profile.role;\n\t\t\n\t\t// authentication data\n\t\tvar auth = { user: user, role: role, token: \".....\" };\n\n\t\t// extract query string\t\t\n\t\tvar query = {};\n\t\tvar url = obj.data.url;\n\t\t\n\t\tvar i = url.indexOf(\"?\");\n\t\tif (i > -1) {\n\t\t\turl.substring(i + 1).split(\"&\").map(function(q) {\n\t\t\t\tvar qq = q.split(\"=\");\n\t\t\t\tquery[qq[0]] = qq[1]\n\t\t\t});\n\t\t\turl = url.substring(0, i);\n\t\t}\n\n\t\t// body\n\t\tvar body = obj.data.body;\n\t\t\n\t\tvar responseEvent = obj.responseEvent;\n\t\t\n\t\tvar req = {\n\t\t\tmethod: obj.data.method ? obj.data.method.toUpperCase() : \"GET\",\n\t\t\turl: url,\n\t\t\tfullUrl: obj.data.url,\n\t\t\tquery: query,\n\t\t\tbody: (typeof body === \"string\" || typeof body === \"undefined\") ? body : JSON.stringify(body),\n\t\t\tpeer: {\n\t\t\t\taddress: \"....\",\n\t\t\t\tport: 0000\n\t\t\t},\n\t\t\theaders: {},\n\t\t\t__authMethod: \"....\",\n\t\t\tuser: auth.user,\n\t\t\trole: auth.role,\n\t\t\tauthToken: auth.token\n\t\t};\n\n\t\tvar found = ws.find(req);\n\t\t\n\t\tvar response;\n\t\tif (found && controller.auth.isAuthorized(role, found.role)) {\n\t\t\tresponse = ws.execute(found.name, req, auth);\n\t\t} else {\n\t\t\tresponse = {\n\t\t\t\tstatus: 404\n\t\t\t};\n\t\t}\n\t\t\n\t\treturn {\n\t\t\t\"ws-reply-type\": responseEvent,\n\t\t\t\"ws-reply-data\": response\n\t\t};\n\t}\n}, {\n\tdocument_root: \"htdocs\"\n});\n\nws.find = function(req) {\n\tvar q = req.url.substring(1).replace(/\\//g, '.');\n\tif (!q) return null;\n\t\n\tvar found = null;\n\tif (this.externalNames.some(function(ext) {\n\t\tfound = ext;\n\t\treturn (ext.name.length < q.length && q.slice(0, ext.name.length + 1) === ext.name + \".\") || (ext.name === q);\n\t})) {\n\t\treturn found;\n\t} else {\n\t\treturn null;\n\t}\n};\n\nws.execute = function(name, req, auth) {\n\tvar cache = this.evalCache || (this.evalCache = {});\n\tvar handler = cache[name] || (cache[name] = evalPath(name));\n\treturn handler(req.url.substring(name.length + 1), req, auth);\n};\n\nws.externalNames = []; // array of object {name, role}\nws.allowExternalAccess = function(name, role) {\n\t// refresh cache anyways, even if adding duplicate name\n\tif (this.evalCache)\n\t\tdelete this.evalCache[name];\n\n\tvar idx = this.externalNames.map(function (ext) { return ext.name}).indexOf(name);\n\tif (idx >= 0) return;\n\n\tthis.externalNames.push({name: name, role: role || controller.auth.ROLE.ADMIN});\n\tthis.externalNames.sort(function(x, y) {\n\t\treturn (y.name.length - x.name.length) || (x.name > y.name ? 1 : -1);\n\t});\n};\nws.revokeExternalAccess = function(name) {\n\t// remove cached handler (if any)\n\tif (this.evalCache)\n\t\tdelete this.evalCache[name];\n\n\tvar idx = this.externalNames.map(function (ext) { return ext.name}).indexOf(name);\n\tif (idx === -1) return;\n\t\n\tthis.externalNames.splice(idx, 1);\n};\n\n// Standard HTTP headers: HTTP and keep-laive\nws.allow_headers = [\n\t\t'Authorization',\n\t\t'Accept-Ranges',\n\t\t'Content-Encoding',\n\t\t'Content-Length',\n\t\t'Content-Range',\n\t\t'Content-Type',\n\t\t'ETag',\n\t\t'X-API-VERSION',\n\t\t'Date',\n\t\t'Cache-Control',\n\t\t'If-None-Match',\n\t\t'Content-Language',\n\t\t'Accept-Language',\n\t\t'X-ZBW-SESSID',\n\t\t'ZWAYSession'\n\t].join(', ');\n\nws.addHTTPHeaders = function (ret) {\n\tif (!ret.headers) ret.headers = {};\n\tret.headers['Access-Control-Allow-Origin'] = '*';\n\tret.headers['Access-Control-Allow-Methods'] = 'GET, PUT, POST, DELETE, OPTIONS';\n\tret.headers['Access-Control-Allow-Headers'] = this.allow_headers;\n\tret.headers['Access-Control-Expose-Headers'] = this.allow_headers;\n\tret.headers['Connection'] = 'keep-alive';\n\tret.headers['Date'] = (new Date()).toUTCString();\n\t\n\treturn ret;\n};\n"
  },
  {
    "path": "WebserverRequestRouter.js",
    "content": "/*** ZAutomationAPI Web Request Handler *****************************************\n\n Version:\n -------------------------------------------------------------------------------\n Author: Stanislav Morozov <r3b@seoarmy.ru>\n Copyright: (c) ZWave.Me, 2014\n\n ******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- ZAutomationWebRequest\n// ----------------------------------------------------------------------------\n\nfunction ZAutomationWebRequest() {\n\n\tthis.req = {};\n\tthis.res = {\n\t\tstatus: 501,\n\t\theaders: {\n\t\t\t\"X-API-VERSION\": \"2.0.1\",\n\t\t\t\"Content-Type\": \"text/plain; charset=utf-8\"\n\t\t},\n\t\tbody: null\n\t};\n\tthis.error = null;\n}\n\nZAutomationWebRequest.prototype.handlerFunc = function () {\n\tvar self = this;\n\n\treturn function () {\n\t\treturn self.handleRequest.apply(self, arguments);\n\t};\n};\n\nZAutomationWebRequest.prototype.initResponse = function (response) {\n\tvar that = this,\n\t\treply,\n\t\tversion = \"2.0.1\",\n\t\tfields,\n\t\tobject = {},\n\t\tdata,\n\t\tmainKey = null,\n\t\tsubPaths = ['notifications', 'devices'],\n\t\ttempData,\n\t\tpager = null,\n\t\tlimit = that.req.query.hasOwnProperty('limit') ? parseInt(that.req.query['limit']) : 10,\n\t\toffset = that.req.query.hasOwnProperty('offset') ? parseInt(that.req.query['offset']) : 0,\n\t\tpagination = that.req.query.hasOwnProperty('pagination') ? that.req.query['pagination'] : false,\n\t\tquery = that.req.query.hasOwnProperty('q') ? String(that.req.query['q']).toLowerCase() : null,\n\t\thttpCode = {\n\t\t\t200: \"200 OK\",\n\t\t\t201: \"201 Created\",\n\t\t\t204: \"204 No Content\",\n\t\t\t304: \"304 Not Modified\",\n\t\t\t400: \"400 Bad Request\",\n\t\t\t401: \"401 Unauthorized\",\n\t\t\t403: \"403 Forbidden\",\n\t\t\t404: \"404 Not Found\",\n\t\t\t405: \"405 Method Not Allowed\",\n\t\t\t501: \"501 Not Implemented\",\n\t\t\t500: \"500 Internal server error\"\n\t\t};\n\n\tresponse.data = response.data === undefined ? null : response.data;\n\tresponse.error = response.error || null;\n\tresponse.code = response.code || 200;\n\tresponse.contentType = response.contentType || \"application/json; charset=utf-8\";\n\tresponse.message = response.message || null;\n\n\ttempData = response.data;\n\tdata = response.data;\n\n\tif (data) {\n\t\tsubPaths.forEach(function (path) {\n\t\t\tif (response.data.hasOwnProperty(path)) {\n\t\t\t\tmainKey = path;\n\t\t\t\ttempData = response.data[path];\n\t\t\t\tdata = response.data[path];\n\t\t\t}\n\t\t});\n\t}\n\n\t// filter fields\n\tif (!!tempData && response.code === 200 && that.req.query.hasOwnProperty('fields')) {\n\t\tfields = that.req.query['fields'].split(',');\n\t\tif (fields.length) {\n\t\t\tif (Array.isArray(tempData)) {\n\t\t\t\tdata = [];\n\t\t\t\ttempData.forEach(function (model) {\n\t\t\t\t\tobject = {};\n\t\t\t\t\tObject.keys(model).forEach(function (key) {\n\t\t\t\t\t\tif (fields.indexOf(key) !== -1) {\n\t\t\t\t\t\t\tobject[key] = model[key];\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tdata.push(object);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tdata = {};\n\t\t\t\tObject.keys(response.data).forEach(function (key) {\n\t\t\t\t\tif (fields.indexOf(key) !== -1) {\n\t\t\t\t\t\tdata[key] = response.data[key];\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tif (Array.isArray(tempData) && mainKey) {\n\t\t// search\n\t\tif (query && Array.isArray(tempData)) {\n\t\t\ttempData = [];\n\t\t\tif (mainKey === 'devices') {\n\t\t\t\tdata.forEach(function (obj) {\n\t\t\t\t\tif (obj.metrics.title.toLowerCase().indexOf(query) !== -1) {\n\t\t\t\t\t\ttempData.push(obj);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else if (mainKey === 'notifications') {\n\t\t\t\tdata.forEach(function (obj) {\n\t\t\t\t\tif (obj.message.toLowerCase().indexOf(query) !== -1) {\n\t\t\t\t\t\ttempData.push(obj);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tdata = tempData;\n\t\t}\n\n\t\t// pager\n\t\tif (limit > 0 && offset >= 0 && String(pagination) === 'true') {\n\t\t\tdata = data.slice(offset, offset + limit);\n\t\t\tpager = {\n\t\t\t\ttotal: data.length,\n\t\t\t\ttotalPage: Math.round(data.length / limit),\n\t\t\t\tlimit: limit,\n\t\t\t\toffset: offset,\n\t\t\t\tpage: (offset + limit) / limit\n\t\t\t};\n\t\t}\n\t}\n\n\t// include\n\tif (!!mainKey) {\n\t\tresponse.data[mainKey] = data;\n\t\tdata = response.data;\n\t}\n\n\tif (that.req.query.hasOwnProperty('suppress_response_codes') && String(that.req.query.suppress_response_code) === 'true') {\n\t\tresponse.code = '200';\n\t} else {\n\t\tif (!!data) {\n\t\t\tresponse.code = response.code || 200;\n\t\t} else if (that.req.method === 'DELETE' || !data) {\n\t\t\tresponse.code = response.code || 204;\n\t\t\tresponse.data = null;\n\t\t\tresponse.message = '204 No Content';\n\t\t}\n\t}\n\n\tif (String(pagination) === 'true') {\n\t\t_.extend(data, {\n\t\t\tpager: {\n\t\t\t\toffset: offset,\n\t\t\t\tlimit: limit,\n\t\t\t\tpage_total: response.data[mainKey].length\n\t\t\t}\n\t\t});\n\t}\n\n\treply = {\n\t\tdata: data,\n\t\tcode: response.code,\n\t\tmessage: httpCode[response.code],\n\t\terror: response.error\n\t};\n\n\tif (pager) {\n\t\treply.pager = pager;\n\t}\n\n\tvar headers = {\n\t\t'Content-Type': response.contentType,\n\t\t'X-API-VERSION': version,\n\t};\n\t\n\tif (response.code === 401 && !response.suppress401Auth) {\n\t\t_.extend(headers, {'WWW-Authenticate': 'Basic realm=\"Z-Way ZAutomation API\"'});\n\t}\n\t\n\tif (response.headers) {\n\t\tfor (var hname in response.headers) {\n\t\t\theaders[hname] = response.headers[hname];\n\t\t}\n\t}\n\n\tthat.res = {\n\t\tstatus: response.code,\n\t\tbody: JSON.stringify(reply),\n\t\theaders: headers\n\t};\n\n\treturn that.res;\n};\n\nZAutomationWebRequest.prototype.dispatchRequest = function (method, url) {\n\treturn this.NotImplementedReply;\n};\n\nZAutomationWebRequest.prototype.handleRequest = function (url, request) {\n\tvar self = this,\n\t\trequestProcessorFunc,\n\t\tbodyLength,\n\t\tresponse;\n\n\tresponse = {\n\t\tdata: null,\n\t\terror: null,\n\t\tcode: 200,\n\t\tmessage: null\n\t};\n\n\t// Fill internal structures\n\tthis.req.url = url;\n\tthis.req.fullUrl = request.fullUrl || \"\";\n\tthis.req.method = request.method;\n\tthis.req.query = request.query || {};\n\tthis.req.body = request.body || request.data;\n\tthis.req.headers = request.headers || {};\n\tthis.req.peer = request.peer;\n\tthis.req.user = request.user;\n\tthis.req.role = request.role;\n\tthis.req.authToken = request.authToken;\n\tvar contentType = request.headers['Content-Type'] || \"\";\n\n\t// set defaultLang\n\tif (self.req.query.hasOwnProperty('lang') || self.req.headers['Accept-Language']) {\n\t\tself.controller.setDefaultLang(self.req.query.lang || self.req.headers['Accept-Language']);\n\t}\n\t\n\tif (['PUT', 'POST'].indexOf(this.req.method) !== -1 && contentType.toLowerCase().indexOf('application/json') !== -1) {\n\t\ttry {\n\t\t\tthis.req.reqObj = JSON.parse(this.req.body);\n\t\t} catch (ex) {\n\t\t\tresponse.code = 500;\n\t\t\tresponse.error = 'JSON Parse Error [Syntax Error]';\n\t\t}\n\t}\n\n\tif (response.error === null) {\n\t\t// Get and run request processor func\n\t\trequestProcessorFunc = this.dispatchRequest(request.method, url);\n\t\tresponse = requestProcessorFunc.call(this);\n\t}\n\n\t// Return to the z-way-http\n\treturn response ? this.initResponse(response) : this.res;\n};\n\nZAutomationWebRequest.prototype.NotImplementedReply = function () {\n\tthis.res = {\n\t\tstatus: 501,\n\t\tbody: \"Not implemented, yet\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"text/plain; charset=utf-8\"\n\t\t}\n\t};\n};\n\nZAutomationWebRequest.prototype.NotFound = function () {\n\tthis.res = {\n\t\tstatus: 404,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"text/plain; charset=utf-8\"\n\t\t},\n\t\tbody: \"Not Found\"\n\t};\n};\n"
  },
  {
    "path": "ZAutomationAPIProvider.js",
    "content": "/*** ZAutomationAPI Provider **************************************************\n\nVersion:\n-------------------------------------------------------------------------------\nAuthor: Gregory Sitnin <sitnin@z-wave.me>\nCopyright: (c) ZWave.Me, 2013\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- ZAutomationAPIWebRequest\n// ----------------------------------------------------------------------------\n\nexecuteFile(\"router.js\");\n\nfunction ZAutomationAPIWebRequest(controller) {\n\tZAutomationAPIWebRequest.super_.call(this);\n\n\tthis.ROLE = controller.auth.ROLE;\n\n\tthis.router = new Router(\"/v1\");\n\tthis.controller = controller;\n\tthis.res = {\n\t\tstatus: 200,\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json; charset=utf-8\"\n\t\t},\n\t\tbody: null\n\t};\n\n\tthis.registerRoutes();\n};\n\nvar ZAutomationWebRequest = ZAutomationWebRequest || function() {};\ninherits(ZAutomationAPIWebRequest, ZAutomationWebRequest);\n\n_.extend(ZAutomationAPIWebRequest.prototype, {\n\tregisterRoutes: function() {\n\t\tthis.router.get(\"/status\", this.ROLE.USER, this.statusReport);\n\t\tthis.router.get(\"/session\", this.ROLE.ANONYMOUS, this.verifySession);\n\t\tthis.router.post(\"/login\", this.ROLE.ANONYMOUS, this.verifyLogin);\n\t\tthis.router.get(\"/logout\", this.ROLE.USER, this.doLogout);\n\t\tthis.router.get(\"/notifications\", this.ROLE.USER, this.exposeNotifications);\n\t\tthis.router.put(\"/notifications\", this.ROLE.ADMIN, this.redeemNotifications);\n\t\tthis.router.del(\"/notifications\", this.ROLE.ADMIN, this.deleteNotifications);\n\t\tthis.router.get(\"/devices\", this.ROLE.USER, this.listDevices);\n\t\tthis.router.get(\"/restart\", this.ROLE.ADMIN, this.restartController);\n\t\tthis.router.get(\"/locations\", this.ROLE.USER, this.listLocations);\n\t\tthis.router.get(\"/profiles\", this.ROLE.USER, this.listProfiles);\n\t\tthis.router.get(\"/namespaces\", this.ROLE.ADMIN, this.listNamespaces);\n\t\tthis.router.post(\"/profiles\", this.ROLE.ADMIN, this.createProfile);\n\t\tthis.router.get(\"/locations/add\", this.ROLE.ADMIN, this.addLocation);\n\t\tthis.router.post(\"/locations\", this.ROLE.ADMIN, this.addLocation);\n\t\tthis.router.get(\"/locations/remove\", this.ROLE.ADMIN, this.removeLocation);\n\t\tthis.router.get(\"/locations/update\", this.ROLE.ADMIN, this.updateLocation);\n\t\tthis.router.get(\"/modules\", this.ROLE.ADMIN, this.listModules);\n\t\tthis.router.get(\"/modules/categories\", this.ROLE.ADMIN, this.listModulesCategories);\n\n\t\t// module installation / update\n\t\tthis.router.post(\"/modules/install\", this.ROLE.ADMIN, this.installModule);\n\t\tthis.router.post(\"/modules/update\", this.ROLE.ADMIN, this.updateModule);\n\n\t\t// module tokens\n\t\tthis.router.get(\"/modules/tokens\", this.ROLE.ADMIN, this.getModuleTokens);\n\t\tthis.router.put(\"/modules/tokens\", this.ROLE.ADMIN, this.storeModuleToken);\n\t\tthis.router.del(\"/modules/tokens\", this.ROLE.ADMIN, this.deleteModuleToken);\n\n\t\tthis.router.get(\"/instances\", this.ROLE.ADMIN, this.listInstances);\n\t\tthis.router.post(\"/instances\", this.ROLE.ADMIN, this.createInstance);\n\n\t\tthis.router.post(\"/upload/file\", this.ROLE.ADMIN, this.uploadFile);\n\n\t\t// patterned routes, right now we are going to just send in the wrapper\n\t\t// function. We will let the handler consumer handle the application of\n\t\t// the parameters.\n\t\tthis.router.get(\"/devices/:v_dev_id/command/:command_id\", this.ROLE.USER, this.performVDevCommandFunc);\n\t\tthis.router.get(\"/devices/:v_dev_id/referenced\", this.ROLE.ADMIN, this.getDeviceReference);\n\n\t\tthis.router.get('/devices/:dev_id/:param/:innerParam', this.ROLE.USER, this.getVDevParam);\n\t\tthis.router.get('/devices/:dev_id/:param', this.ROLE.USER, this.getVDevParam);\n\n\t\tthis.router.get(\"/locations/:location_id/namespaces/:namespace_id\", this.ROLE.ADMIN, this.getLocationNamespacesFunc);\n\t\tthis.router.get(\"/locations/:location_id/namespaces\", this.ROLE.ADMIN, this.getLocationNamespacesFunc);\n\n\t\tthis.router.del(\"/locations/image/:location_id\", this.ROLE.ADMIN, this.removeLocationImage, [parseInt]);\n\t\tthis.router.del(\"/locations/:location_id\", this.ROLE.ADMIN, this.removeLocation, [parseInt]);\n\t\tthis.router.put(\"/locations/:location_id\", this.ROLE.ADMIN, this.updateLocation, [parseInt]);\n\t\tthis.router.get(\"/locations/:location_id\", this.ROLE.ADMIN, this.getLocationFunc);\n\n\t\tthis.router.get(\"/notifications/:notification_id\", this.ROLE.USER, this.exposeNotifications, [parseInt]);\n\t\tthis.router.del(\"/notifications/:notification_id\", this.ROLE.USER, this.deleteNotifications, [parseInt]);\n\t\tthis.router.put(\"/notifications/:notification_id\", this.ROLE.USER, this.redeemNotifications, [parseInt]);\n\n\t\tthis.router.post(\"/profiles/qrcode/:profile_id\", this.ROLE.USER, this.getQRCodeString, [parseInt]);\n\t\tthis.router.del(\"/profiles/:profile_id/token/:token\", this.ROLE.USER, this.removeToken, [parseInt, undefined]);\n\n\t\tthis.router.put(\"/profiles/:profile_id/token/:token\", this.ROLE.USER, this.permanentToken, [parseInt, undefined]);\n\n\t\tthis.router.get(\"/profiles/token/local/:profile_id\", this.ROLE.USER, this.generateLocalAccessToken, [parseInt]);\n\n\t\tthis.router.del(\"/profiles/:profile_id\", this.ROLE.ADMIN, this.removeProfile, [parseInt]);\n\t\tthis.router.put(\"/profiles/:profile_id\", this.ROLE.USER, this.updateProfile, [parseInt]);\n\t\tthis.router.get(\"/profiles/:profile_id\", this.ROLE.USER, this.listProfiles, [parseInt]);\n\t\tthis.router.del(\"/profile\", this.ROLE.USER, this.removeOwnProfile);\n\t\tthis.router.post(\"/oauth2\", this.ROLE.ADMIN, this.createOAuth2Profile);\n\n\t\tthis.router.get(\"/notificationFiltering\", this.ROLE.USER, this.notificationFilteringGet);\n\t\tthis.router.put(\"/notificationFiltering\", this.ROLE.USER, this.notificationFilteringSet);\n\t\tthis.router.get(\"/notificationChannels\", this.ROLE.USER, this.notificationChannelsGet);\n\t\tthis.router.get(\"/notificationChannels/all\", this.ROLE.ADMIN, this.notificationChannelsGetAll);\n\n\t\tthis.router.post(\"/auth/forgotten\", this.ROLE.ANONYMOUS, this.restorePassword);\n\t\tthis.router.post(\"/auth/forgotten/:profile_id\", this.ROLE.ANONYMOUS, this.restorePassword, [parseInt]);\n\t\tthis.router.put(\"/auth/update/:profile_id\", this.ROLE.ANONYMOUS, this.updateProfileAuth, [parseInt]);\n\n\t\tthis.router.put(\"/devices/:dev_id\", this.ROLE.USER, this.setVDevFunc);\n\t\tthis.router.get(\"/devices/:dev_id\", this.ROLE.USER, this.getVDevFunc);\n\n\n\t\tthis.router.get(\"/instances/:instance_id\", this.ROLE.ADMIN, this.getInstanceFunc);\n\t\tthis.router.put(\"/instances/:instance_id\", this.ROLE.ADMIN, this.reconfigureInstanceFunc, [parseInt]);\n\t\tthis.router.del(\"/instances/:instance_id\", this.ROLE.ADMIN, this.deleteInstanceFunc, [parseInt]);\n\n\t\tthis.router.post(\"/modules/reset/:module_id\", this.ROLE.ADMIN, this.resetModule);\n\t\tthis.router.del(\"/modules/delete/:module_id\", this.ROLE.ADMIN, this.deleteModule);\n\n\t\t// reinitialize apps from /modules or /userModules directory\n\t\tthis.router.get(\"/modules/reinitialize/:module_id\", this.ROLE.ADMIN, this.reinitializeModule);\n\n\t\tthis.router.get(\"/modules/categories/:category_id\", this.ROLE.ADMIN, this.getModuleCategoryFunc);\n\t\tthis.router.get(\"/modules/transform/reverse\", this.ROLE.ADMIN, this.revertTransformModuleFlag);\n\t\tthis.router.post(\"/modules/transform\", this.ROLE.ADMIN, this.transformModule);\n\n\t\tthis.router.get(\"/modules/:module_id\", this.ROLE.ADMIN, this.getModuleFunc);\n\n\t\tthis.router.get(\"/namespaces/:namespace_id\", this.ROLE.ADMIN, this.getNamespaceFunc);\n\n\t\tthis.router.get(\"/load/modulemedia/:module_name/:file_name\", this.ROLE.ANONYMOUS, this.loadModuleMedia);\n\n\t\tthis.router.get(\"/load/image/:img_name\", this.ROLE.ANONYMOUS, this.loadImage);\n\n\t\tthis.router.get(\"/backup\", this.ROLE.ADMIN, this.backup);\n\t\tthis.router.post(\"/restore\", this.ROLE.ADMIN, this.restore);\n\t\tthis.router.get(\"/resetToFactoryDefault\", this.ROLE.ADMIN, this.resetToFactoryDefault);\n\n\t\t// skins tokens\n\t\tthis.router.get(\"/skins/tokens\", this.ROLE.ADMIN, this.getSkinTokens);\n\t\tthis.router.put(\"/skins/tokens\", this.ROLE.ADMIN, this.storeSkinToken);\n\t\tthis.router.del(\"/skins/tokens\", this.ROLE.ADMIN, this.deleteSkinToken);\n\n\t\tthis.router.get(\"/skins\", this.ROLE.ADMIN, this.getSkins);\n\t\tthis.router.post(\"/skins/install\", this.ROLE.ADMIN, this.addOrUpdateSkin);\n\t\tthis.router.put(\"/skins/update/:skin_id\", this.ROLE.ADMIN, this.addOrUpdateSkin);\n\t\tthis.router.get(\"/skins/setToDefault\", this.ROLE.ADMIN, this.setDefaultSkin);\n\t\tthis.router.get(\"/skins/active\", this.ROLE.ANONYMOUS, this.getActiveSkin);\n\t\tthis.router.get(\"/skins/:skin_id\", this.ROLE.ADMIN, this.getSkin);\n\t\tthis.router.put(\"/skins/:skin_id\", this.ROLE.ADMIN, this.activateOrDeactivateSkin);\n\t\tthis.router.del(\"/skins/:skin_id\", this.ROLE.ADMIN, this.deleteSkin);\n\n\t\tthis.router.get(\"/icons\", this.ROLE.ADMIN, this.getIcons);\n\t\tthis.router.del(\"/icons/:icon_id\", this.ROLE.ADMIN, this.deleteIcons);\n\t\tthis.router.post(\"/icons/upload\", this.ROLE.ADMIN, this.uploadIcon);\n\t\tthis.router.post(\"/icons/install\", this.ROLE.ADMIN, this.addOrUpdateIcons);\n\n\t\tthis.router.get(\"/system/webif-access\", this.ROLE.ADMIN, this.setWebifAccessTimout);\n\t\tthis.router.get(\"/system/reboot\", this.ROLE.ADMIN, this.rebootBox);\n\t\tthis.router.get(\"/system/wifiCli/settings\", this.ROLE.ADMIN, this.getWiFiCliSettings);\n\t\tthis.router.post(\"/system/wifiCli/settings\", this.ROLE.ADMIN, this.setWiFiCliSettings);\n\t\tthis.router.get(\"/system/connectionType\", this.ROLE.ADMIN, this.getConnectionType);\n\n\t\tthis.router.post(\"/system/timezone\", this.ROLE.ADMIN, this.setTimezone);\n\t\tthis.router.get(\"/system/time/get\", this.ROLE.ANONYMOUS, this.getTime);\n\t\tthis.router.get(\"system/time/ntp/:action\", this.ROLE.ADMIN, this.configNtp);\n\n\t\tthis.router.get(\"/system/remote-id\", this.ROLE.ANONYMOUS, this.getRemoteId);\n\t\tthis.router.get(\"/system/ip-address\", this.ROLE.ANONYMOUS, this.getIPAddress);\n\t\tthis.router.get(\"/system/first-access\", this.ROLE.ANONYMOUS, this.getFirstLoginInfo);\n\t\tthis.router.get(\"/system/info\", this.ROLE.ANONYMOUS, this.getSystemInfo);\n\n\t\tthis.router.post(\"/system/wifi/settings\", this.ROLE.ADMIN, this.setWifiSettings);\n\t\tthis.router.get(\"/system/wifi/settings\", this.ROLE.ADMIN, this.getWifiSettings);\n\n\t\tthis.router.get(\"/system/zwave/deviceInfoGet\", this.ROLE.ADMIN, this.zwaveDeviceInfoGet);\n\t\tthis.router.get(\"/system/zwave/deviceInfoUpdate\", this.ROLE.ADMIN, this.zwaveDeviceInfoUpdate);\n\t\tthis.router.get(\"/system/zwave/vendorsInfoGet\", this.ROLE.ADMIN, this.zwaveVendorsInfoGet);\n\t\tthis.router.get(\"/system/zwave/vendorsInfoUpdate\", this.ROLE.ADMIN, this.zwaveVendorsInfoUpdate);\n\n\t\tthis.router.put(\"/devices/reorder\", this.ROLE.ADMIN, this.reorderDevices);\n\t\t\n\t\tthis.router.get(\"/redirect\", this.ROLE.ANONYMOUS, this.redirectURL);\n\t\tthis.router.post(\"/redirect\", this.ROLE.ANONYMOUS, this.redirectURL);\n\t\t\n\t\tthis.router.get(\"/demultiplex/:paths\", this.ROLE.ANONYMOUS, this.demultiplex);\n\n\t\tthis.router.get('/expert/deviceDescription/:deviceId', this.ROLE.ADMIN, this.getDeviceDescription, [parseInt]);\n\n\t\tthis.router.get('/encryptionKeys', this.ROLE.ADMIN, this.encryptionKeys)\n\t},\n\n\t// Used by the android app to request server status\n\tstatusReport: function() {\n\t\tvar currentDateTime = new Date(),\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: 'OK',\n\t\t\t\tcode: 200\n\t\t\t};\n\n\t\tif (Boolean(this.error)) {\n\t\t\treply.error = \"Internal server error. Please fill in bug report with request_id='\" + this.error + \"'\";\n\t\t\treply.data = null;\n\t\t\treply.code = 503;\n\t\t\treply.message = \"Service Unavailable\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\n\tsetLogin: function(profile, req) {\n\t\tvar sid, resProfile = {};\n\n\t\tsid = this.controller.auth.checkIn(profile, req);\n\n\t\tresProfile = this.controller.safeProfile(profile, [\"authTokens\"]);\n\t\tresProfile.sid = sid;\n\n\t\tif (profile.password !== 'admin' && !this.controller.config.hasOwnProperty('firstaccess') || this.controller.config.firstaccess === true) {\n\t\t\tthis.controller.config.firstaccess = false;\n\t\t}\n\n\t\t// if showWelcome flag is set in controller add showWelcome flag to profile and remove it from controller\n\t\tif (!this.controller.config.firstaccess && this.controller.config.showWelcome) {\n\t\t\tresProfile.showWelcome = true;\n\n\t\t\tdelete this.controller.config.showWelcome;\n\t\t\tthis.controller.saveConfig(true);\n\t\t}\n\n\t\treturn {\n\t\t\terror: null,\n\t\t\tdata: resProfile,\n\t\t\tcode: 200,\n\t\t\theaders: {\n\t\t\t\t\"ZWAYSession\": resProfile.sid,\n\t\t\t\t\"Set-Cookie\": \"ZWAYSession=\" + sid + \"; Path=/\" // set cookie - it will duplicate header just in case client prefers cookies\n\t\t\t}\n\t\t};\n\t},\n\t// Method to return a 401 to the user\n\tdenyLogin: function(error) {\n\t\treturn {\n\t\t\terror: error,\n\t\t\tdata: null,\n\t\t\tcode: 401,\n\t\t\tsuppress401Auth: true, // to suppress basic auth form from the browser\n\t\t\theaders: {\n\t\t\t\t\"Set-Cookie\": \"ZWAYSession=deleted; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT\" // clean cookie\n\t\t\t}\n\t\t}\n\t},\n\t// Returns user session information for the smarthome UI\n\tverifySession: function() {\n\t\tvar auth = controller.auth.resolve(this.req, controller.auth.ROLE.USER);\n\n\t\tif (!auth) {\n\t\t\treturn this.denyLogin(\"No valid user session found\");\n\t\t}\n\n\t\tvar profile = _.find(this.controller.profiles, function(profile) {\n\t\t\treturn profile.id === auth.user;\n\t\t});\n\n\t\tres = _.extend(this.controller.safeProfile(profile, [\"authTokens\"]), {sid: controller.auth.getSessionId(this.req)});\n\n\t\treturn {\n\t\t\terror: null,\n\t\t\tdata: res,\n\t\t\tcode: 200,\n\t\t\theaders: {\n\t\t\t\t\"ZWAYSession\": res.sid,\n\t\t\t\t\"Set-Cookie\": \"ZWAYSession=\" + res.sid + \"; Path=/\" // set cookie - it will duplicate header just in case client prefers cookies\n\t\t\t}\n\t\t};\n\t},\n\t// Check if login exists and password is correct\n\tverifyLogin: function() {\n\t\tvar reqObj;\n\n\t\ttry {\n\t\t\treqObj = parseToObject(this.req.body);\n\t\t} catch (ex) {\n\t\t\treturn {\n\t\t\t\terror: ex.message,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\theaders: null\n\t\t\t};\n\t\t}\n\n\t\tvar profile = _.find(this.controller.profiles, function(profile) {\n\t\t\treturn profile.login === reqObj.login;\n\t\t});\n\n\t\tif (profile) {\n\t\t\t// check if the pwd matches\n\t\t\tvar pwd_check = reqObj.password ? (!profile.salt && profile.password === reqObj.password) || (profile.salt && profile.password === hashPassword(reqObj.password, profile.salt)) : false;\n\n\t\t\tif (pwd_check) {\n\t\t\t\treturn this.setLogin(profile, this.req);\n\t\t\t} else {\n\t\t\t\treturn this.denyLogin();\n\t\t\t}\n\t\t} else {\n\t\t\treturn this.denyLogin();\n\t\t}\n\t},\n\n\tdoLogout: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 400,\n\t\t\t\theaders: null\n\t\t\t},\n\t\t\tself = this,\n\t\t\tsession;\n\n\t\treply.headers = {\n\t\t\t\"Set-Cookie\": \"ZWAYSession=deleted; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT\" // clean cookie\n\t\t};\n\n\t\treply.code = 200;\n\t\t\t\n\t\tvar sessionId = this.controller.auth.getSessionId(this.req);\n\n\t\tif (sessionId) {\n\t\t\tvar session = {};\n\t\t\tvar sessionProfile = _.find(this.controller.profiles, function(profile) {\n\t\t\t\tvar sess = _.find(profile.authTokens, function(authToken) {\n\t\t\t\t\treturn authToken.sid == sessionId;\n\t\t\t\t});\n\t\t\t\tif (sess) session = sess;\n\t\t\t\treturn sess;\n\t\t\t});\n\t\t\tif (session.expire !== 0) {\n\t\t\t\t// do not logout from permanent tokens - they should be deleted explicitelly via remoteToken API call\n\t\t\t\tthis.controller.removeToken(sessionProfile, session.sid);\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn reply;\n\t},\n\t// Devices\n\tlistDevices: function() {\n\t\tvar nowTS = Math.floor(Date.now() / 1000),\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tstructureChanged: false,\n\t\t\t\t\tupdateTime: nowTS,\n\t\t\t\t\tdevices: []\n\t\t\t\t}\n\t\t\t},\n\t\t\tsince = this.req.query.hasOwnProperty(\"since\") ? parseInt(this.req.query.since, 10) : 0;\n\n\t\treply.data.structureChanged = this.controller.lastStructureChangeTime >= since && since? true : false;\n\t\treply.data.devices = this.controller.devicesByUser(this.req.user, function(dev) {\n\t\t\treturn dev.get(\"updateTime\") >= (reply.data.structureChanged ? 0 : since);\n\t\t});\n\t\tif (Boolean(this.req.query.pagination)) {\n\t\t\treply.data.total_count = devices.length;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetVDevFunc: function(vDevId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\tdevice = _.find(this.controller.devicesByUser(this.req.user), function(device) {\n\t\t\t\treturn device.id === vDevId;\n\t\t\t});\n\n\t\tif (device) {\n\t\t\treply.code = 200;\n\t\t\treply.data = device.toJSON();\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Device \" + vDevId + \" doesn't exist\";\n\t\t}\n\t\treturn reply;\n\t},\n\tgetVDevParam: function (vDevId, param, innerParam) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\tdevice = _.find(this.controller.devicesByUser(this.req.user), function(device) {\n\t\t\t\treturn device.id === vDevId;\n\t\t\t});\n\t\tif (device) {\n\t\t\tdevice = device.toJSON();\n\t\t\tif (device.hasOwnProperty(param)) {\n\t\t\t\tvar field = device[param];\n\t\t\t\tif (innerParam) {\n\t\t\t\t\tif (field.hasOwnProperty(innerParam)) {\n\t\t\t\t\t\treply.code = 200;\n\t\t\t\t\t\treply.data = field[innerParam];\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\treply.error = 'Parameter ' + param + '.' + innerParam +' in device ' + vDevId + ' doesn\\'t exist';\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.data = field;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'Parameter ' + param + ' in device ' + vDevId + ' doesn\\'t exist';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Device \" + vDevId + \" doesn't exist\";\n\t\t}\n\t\treturn reply;\n\t},\n\tsetVDevFunc: function(vDevId) {\n\t\tvar reqObj,\n\t\t\tdevice = null,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t},\n\t\t\tresult = false;\n\n\t\ttry {\n\t\t\treqObj = typeof this.req.body === 'string' ? JSON.parse(this.req.body) : this.req.body;\n\t\t} catch (ex) {\n\t\t\treply.error = ex.message;\n\t\t\treturn reply;\n\t\t}\n\n\t\t// check security hole here!!!!\n\t\t\n\t\tif (this.req.query.hasOwnProperty('icon')) {\n\t\t\tdevice = this.controller.devices.get(vDevId);\n\t\t\tif (device) {\n\t\t\t\tdevice.set('customIcons', reqObj.customicons, {\n\t\t\t\t\tsilent: true\n\t\t\t\t});\n\t\t\t\treply.data = \"OK\";\n\t\t\t\tresult = true;\n\t\t\t}\n\t\t} else {\n\t\t\tdevice = this.controller.deviceByUser(vDevId, this.req.user);\n\t\t\tif (device) {\n\t\t\t\treply.data = device.set(reqObj);\n\t\t\t\tresult = true;\n\t\t\t}\n\t\t}\n\n\t\tif (result) {\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Device \" + vDevId + \" doesn't exist\";\n\t\t}\n\t\treturn reply;\n\t},\n\tperformVDevCommandFunc: function(vDevId, commandId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\tresult_execution_command,\n\t\t\tvDev = this.controller.deviceByUser(vDevId, this.req.user);\n\n\t\tif (vDev) {\n\t\t\tresult_execution_command = vDev.performCommand.call(vDev, commandId, this.req.query);\n\t\t\treply.data = !!result_execution_command ? result_execution_command : null;\n\t\t} else {\n\t\t\treply.data = null;\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Device \" + vDevId + \" doesn't exist\";\n\t\t}\n\t\treturn reply;\n\t},\n\tgetDeviceReference: function(vDevId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: this.controller.findModulesReferencingDeviceId(vDevId),\n\t\t\t\tcode: 200\n\t\t\t};\n\n\t\treturn reply;\n\t},\n\t// Notifications\n\texposeNotifications: function(notificationId) {\n\t\tvar notifications,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\ttimestamp = Date.now(),\n\t\t\tsince = this.req.query.hasOwnProperty(\"since\") ? parseInt(this.req.query.since, 10) : 0,\n\t\t\tto = (this.req.query.hasOwnProperty(\"to\") ? parseInt(this.req.query.to, 10) : 0) || timestamp,\n\t\t\tprofile = this.controller.profileByUser(this.req.user),\n\t\t\tdevices = this.controller.devicesByUser(this.req.user).map(function(device) {\n\t\t\t\treturn device.id;\n\t\t\t}),\n\t\t\ttest = function(n) {\n\t\t\t\treturn ((profile.hide_system_events === false && n.level !== 'device-info') || // hide_system_events = false\n\t\t\t\t\t\t(profile.hide_all_device_events === false && n.level === 'device-info')) && // hide_device_events = false\n\t\t\t\t\t(!profile.hide_single_device_events || profile.hide_single_device_events.indexOf(n.source) === -1) && // remove events from devices to hide\n\t\t\t\t\t((n.level !== 'device-info' && devices.indexOf(n.source) === -1) || (n.level === 'device-info' && devices.indexOf(n.source) > -1)); //  filter device by user\n\t\t\t};\n\n\t\tif (notificationId) {\n\n\t\t\tnotification = this.controller.notifications.get().filter(function(notification) {\n\t\t\t\treturn notification.id === notificationId && // filter by id\n\t\t\t\t\ttest(notification); // check against 2nd filter\n\t\t\t});\n\n\t\t\tif (notification.length > 0) {\n\t\t\t\treply.data = notification[0];\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'Not found';\n\t\t\t}\n\n\t\t} else {\n\t\t\tnotifications = this.controller.notifications.get().filter(function(notification) {\n\t\t\t\treturn notification.id >= since && notification.id <= to && // filter by time\n\t\t\t\t\ttest(notification); // check against 2nd filter\n\t\t\t});\n\n\t\t\treply.data = {\n\t\t\t\tupdateTime: Math.floor(timestamp / 1000),\n\t\t\t\tnotifications: notifications\n\t\t\t};\n\t\t}\n\n\t\tif (Boolean(this.req.query.pagination)) {\n\t\t\treply.data.total_count = notifications.length;\n\t\t\t// !!! fix pagination\n\t\t\tnotifications = notifications.slice();\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// delete single notifications or all privious by a choosen timestamp\n\tdeleteNotifications: function(notificationId) {\n\n\t\tvar id = notificationId ? parseInt(notificationId) : 0,\n\t\t\treply = {\n\t\t\t\tcode: 500,\n\t\t\t\tdata: null,\n\t\t\t\terror: \"Something went wrong.\"\n\t\t\t},\n\t\t\tbefore;\n\n\t\tbefore = this.req.query.hasOwnProperty(\"allPrevious\") ? Boolean(this.req.query.allPrevious) : false;\n\t\tredeemed = this.req.query.hasOwnProperty(\"allRedeemed\") ? Boolean(this.req.query.allRedeemed) : false;\n\n\t\tif (!redeemed) {\n\t\t\tthis.controller.deleteNotifications(id, before, function(notice) {\n\t\t\t\tif (notice) {\n\t\t\t\t\treply.code = 204;\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.error = null;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.error = \"Notifications not found.\";\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.controller.deleteAllRedeemedNotifications(function(notice) {\n\t\t\t\tif (notice) {\n\t\t\t\t\treply.code = 204;\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.error = null;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// redeem single or all notifications (true/false)\n\tredeemNotifications: function(notificationId) {\n\n\t\tvar id = notificationId ? parseInt(notificationId) : 0,\n\t\t\treply = {\n\t\t\t\tcode: 500,\n\t\t\t\tdata: null,\n\t\t\t\terror: \"Something went wrong.\"\n\t\t\t};\n\n\t\tredeemed = this.req.body.hasOwnProperty(\"set_redeemed\") ? retBoolean(this.req.body.set_redeemed) : false;\n\t\tall = this.req.body.hasOwnProperty(\"all\") ? retBoolean(this.req.body.all) : false;\n\n\t\tif (!all) {\n\t\t\tthis.controller.redeemNotification(id, redeemed, function(notice) {\n\t\t\t\tif (notice) {\n\t\t\t\t\treply.code = 204;\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.error = null;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.error = 'Notification not found.';\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tthis.controller.redeemAllNotifications(redeemed, function(notice) {\n\t\t\t\tif (notice) {\n\t\t\t\t\treply.code = 204;\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.error = null;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn reply;\n\t},\n\t//locations\n\tlistLocations: function() {\n\t\tvar reply = {\n\t\t\t\tdata: null,\n\t\t\t\terror: null\n\t\t\t},\n\t\t\tlocations = this.controller.locationsByUser(this.req.user),\n\t\t\texpLocations = [];\n\n\t\t// generate namespaces per location\n\t\treply.code = 200;\n\t\treply.data = locations;\n\n\t\treturn reply;\n\t},\n\t// get location\n\tgetLocationFunc: function(locationId) {\n\t\tvar reply = {\n\t\t\t\tdata: null,\n\t\t\t\terror: null\n\t\t\t},\n\t\t\tlocations = this.controller.locationsByUser(this.req.user),\n\t\t\t_location = [],\n\t\t\tlocationId = !isNaN(locationId) ? parseInt(locationId, 10) : locationId;\n\n\t\t_location = this.controller.getLocation(locations, locationId);\n\n\t\t// generate namespaces for location\n\t\tif (_location) {\n\t\t\treply.data = _location;\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Location \" + locationId + \" not found\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\t//filter location namespaces\n\tgetLocationNamespacesFunc: function(locationId, namespaceId) {\n\t\tvar reply = {\n\t\t\t\tdata: null,\n\t\t\t\terror: null\n\t\t\t},\n\t\t\tlocations = this.controller.locationsByUser(this.req.user),\n\t\t\t_location = [],\n\t\t\tlocationId = !isNaN(locationId) ? parseInt(locationId, 10) : locationId;\n\n\t\t_location = this.controller.getLocation(locations, locationId);\n\n\t\t// generate namespaces for location and get its namespaces\n\t\tif (_location) {\n\n\t\t\t// get namespaces by path (namespaceId)\n\t\t\tif (!namespaceId) {\n\t\t\t\tgetFilteredNspc = _location.namespaces;\n\t\t\t} else {\n\t\t\t\tgetFilteredNspc = this.controller.getListNamespaces(namespaceId, _location.namespaces);\n\t\t\t}\n\n\t\t\tif (!getFilteredNspc || (_.isArray(getFilteredNspc) && getFilteredNspc.length < 1)) {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = \"Couldn't find namespaces entry with: '\" + namespaceId + \"'\";\n\t\t\t} else {\n\t\t\t\treply.data = getFilteredNspc;\n\t\t\t\treply.code = 200;\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Location \" + locationId === 0 ? 'globalRoom' : locationId + \" not found\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\taddLocation: function() {\n\t\tvar title,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\treqObj,\n\t\t\tlocProps = {};\n\n\t\tif (this.req.method === 'GET') {\n\n\t\t\treqObj = this.req.query;\n\n\t\t} else if (this.req.method === 'POST') { // POST\n\t\t\ttry {\n\t\t\t\treqObj = JSON.parse(this.req.body);\n\t\t\t} catch (ex) {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Cannot parse POST request. ERROR:\" + ex.message;\n\t\t\t}\n\t\t}\n\n\t\tfor (var property in reqObj) {\n\t\t\tif (property !== 'id') {\n\t\t\t\tlocProps[property] = reqObj[property] ? reqObj[property] : null;\n\t\t\t}\n\t\t}\n\n\t\tif (!!locProps.title) {\n\t\t\tthis.controller.addLocation(locProps, function(data) {\n\t\t\t\tif (data) {\n\t\t\t\t\treply.code = 201;\n\t\t\t\t\treply.data = data;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 500;\n\t\t\t\t\treply.error = \"Location doesn't created: Parsing the arguments has failed.\";\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\treply.code = 500;\n\t\t\treply.error = \"Argument 'title' is required.\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tremoveLocation: function(locationId) {\n\t\tvar id,\n\t\t\treqObj,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t};\n\n\t\tif (this.req.method === 'GET') {\n\t\t\tid = parseInt(this.req.query.id);\n\t\t} else if (this.req.method === 'DELETE' && locationId === undefined) {\n\t\t\ttry {\n\t\t\t\treqObj = JSON.parse(this.req.body);\n\t\t\t} catch (ex) {\n\t\t\t\treply.error = ex.message;\n\t\t\t}\n\t\t\tid = reqObj.id;\n\t\t} else if (this.req.method === 'DELETE' && locationId !== undefined) {\n\t\t\tid = locationId;\n\t\t}\n\n\t\tif (!!id) {\n\t\t\tif (id !== 0) {\n\t\t\t\tthis.controller.removeLocation(id, function(result) {\n\t\t\t\t\tif (result) {\n\t\t\t\t\t\treply.code = 204;\n\t\t\t\t\t\treply.data = null;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\treply.error = \"Location \" + id + \" doesn't exist\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Permission denied\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 400;\n\t\t\treply.error = \"Argument id is required\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tremoveLocationImage: function(locationId) {\n\t\tvar id,\n\t\t\tuser_img,\n\t\t\treqObj,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t};\n\n\t\tif (this.req.method === 'DELETE' && locationId === undefined) {\n\t\t\ttry {\n\t\t\t\treqObj = JSON.parse(this.req.body);\n\t\t\t} catch (ex) {\n\t\t\t\treply.error = ex.message;\n\t\t\t}\n\t\t\tid = reqObj.id;\n\t\t\tuser_img = reqObj.user_img;\n\n\t\t} else if (this.req.method === 'DELETE' && locationId !== undefined) {\n\t\t\tid = locationId;\n\t\t\tuser_img = this.req.query.user_img;\n\t\t}\n\n\t\tif (!!id || user_img !== \"\") {\n\t\t\tif (id !== 0) {\n\t\t\t\tvar location = this.controller.getLocation(this.controller.locations, id);\n\t\t\t\tif (location) {\n\t\t\t\t\t// check custom image exists\n\t\t\t\t\tif (!loadObject(user_img)) {\n\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\treply.error = \"Location image \" + user_img + \" doesn't exist or already deleted.\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// delete custom room image\n\t\t\t\t\t\tsaveObject(user_img, null, true);\n\t\t\t\t\t\tif (location.user_img == user_img && location.img_type == 'user') {\n\t\t\t\t\t\t\tlocation.user_img = '';\n\t\t\t\t\t\t\tlocation.img_type = '';\n\t\t\t\t\t\t\tlocation.show_background = false;\n\t\t\t\t\t\t} else if (location.user_img == user_img) {\n\t\t\t\t\t\t\tlocation.user_img = '';\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// update affected location\n\t\t\t\t\t\tthis.controller.updateLocation(location.id, location.title, location.user_img, location.default_img, location.img_type, location.show_background, location.main_sensors, function(data) {\n\t\t\t\t\t\t\tif (data) {\n\t\t\t\t\t\t\t\treply.data = data;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\t\t\treply.error = \"Location \" + id + \" doesn't exist.\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = \"Location \" + id + \" doesn't exist.\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Permission denied.\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 400;\n\t\t\treply.error = \"Argument id, user_img is required.\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tupdateLocation: function(locationId) {\n\t\tvar id,\n\t\t\ttitle,\n\t\t\tuser_img,\n\t\t\tdefault_img,\n\t\t\timg_type,\n\t\t\tshow_background,\n\t\t\tmain_sensors,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\treqObj;\n\n\t\tif (locationId !== 0) {\n\t\t\tif (this.req.method === 'GET') {\n\t\t\t\tid = parseInt(this.req.query.id);\n\t\t\t\ttitle = this.req.query.title;\n\t\t\t} else if (this.req.method === 'PUT') {\n\t\t\t\ttry {\n\t\t\t\t\treqObj = JSON.parse(this.req.body);\n\t\t\t\t} catch (ex) {\n\t\t\t\t\treply.error = ex.message;\n\t\t\t\t}\n\t\t\t\tid = locationId || reqObj.id;\n\t\t\t\ttitle = reqObj.title;\n\t\t\t\tuser_img = reqObj.user_img || '';\n\t\t\t\tdefault_img = reqObj.default_img || '';\n\t\t\t\timg_type = reqObj.img_type || '';\n\t\t\t\tshow_background = reqObj.show_background || false;\n\t\t\t\tmain_sensors = reqObj.main_sensors || [];\n\t\t\t}\n\n\t\t\tif (!!title && title.length > 0) {\n\t\t\t\tthis.controller.updateLocation(id, title, user_img, default_img, img_type, show_background, main_sensors, function(data) {\n\t\t\t\t\tif (data) {\n\t\t\t\t\t\treply.data = data;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\treply.error = \"Location \" + id + \" doesn't exist\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\treply.code = 400;\n\t\t\t\treply.error = \"Arguments id & title are required\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 403;\n\t\t\treply.error = \"Permission denied.\";\n\t\t}\n\n\n\t\treturn reply;\n\t},\n\t// modules\n\tlistModules: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: [],\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\tmodule = null;\n\n\t\tObject.keys(this.controller.modules).sort().forEach(function(className) {\n\t\t\tmodule = this.controller.getModuleData(className);\n\t\t\tmodule.className = className;\n\n\t\t\tif (module.location === ('userModules/' + className) && fs.list('modules/' + className)) {\n\t\t\t\tmodule.hasReset = true;\n\t\t\t} else {\n\t\t\t\tmodule.hasReset = false;\n\t\t\t}\n\n\t\t\tif (module.singleton && _.any(this.controller.instances, function(instance) {\n\t\t\t\t\treturn instance.moduleId === module.id;\n\t\t\t\t})) {\n\t\t\t\tmodule.created = true;\n\t\t\t} else {\n\t\t\t\tmodule.created = false;\n\t\t\t}\n\t\t\treply.data.push(module);\n\t\t});\n\n\t\treturn reply;\n\t},\n\tgetModuleFunc: function(moduleId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: null\n\t\t\t},\n\t\t\tmoduleData;\n\n\t\tif (!this.controller.modules.hasOwnProperty(moduleId)) {\n\t\t\treply.code = 404;\n\t\t\treply.error = 'Instance ' + moduleId + ' not found';\n\t\t} else {\n\t\t\t// get module data\n\t\t\tmoduleData = this.controller.getModuleData(moduleId);\n\n\t\t\tif (moduleData.location === ('userModules/' + moduleId) && fs.list('modules/' + moduleId)) {\n\t\t\t\tmoduleData.hasReset = true;\n\t\t\t} else {\n\t\t\t\tmoduleData.hasReset = false;\n\t\t\t}\n\n\t\t\treply.code = 200;\n\t\t\t// replace namspace filters\n\t\t\treply.data = this.controller.replaceNamespaceFilters(moduleData);\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// modules categories\n\tlistModulesCategories: function() {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 200\n\t\t};\n\n\t\treply.data = this.controller.getListModulesCategories();\n\n\t\treturn reply;\n\t},\n\tgetModuleCategoryFunc: function(categoryId) {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tcategory = this.controller.getListModulesCategories(categoryId);\n\n\t\tif (!Boolean(category)) {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Categories \" + categoryId + \" not found\";\n\t\t} else {\n\t\t\treply.code = 200;\n\t\t\treply.data = category;\n\t\t}\n\n\t\treturn reply;\n\t},\n\ttransformModule: function() {\n\t\tvar reply = {\n\t\t\t\terror: 'Something went wrong.',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\tsources = ['IfThen', 'LogicalRules', 'ScheduledScene', 'LightScene'],\n\t\t\ttargets = ['Rules', 'Schedules', 'Scenes'],\n\t\t\tsource = reqObj.source && ['IfThen', 'LogicalRules', 'ScheduledScene', 'LightScene'].indexOf(reqObj.source) > -1 ? reqObj.source : null,\n\t\t\ttarget = reqObj.target && ['Rules', 'Schedules', 'Scenes'].indexOf(reqObj.target) > -1 ? reqObj.target : null,\n\t\t\tpairing = false,\n\t\t\tresultList = [];\n\n\t\ttry {\n\t\t\tpairing = (target === 'Rules' && (source === 'IfThen' || source === 'LogicalRules')) ||\n\t\t\t\t(target === 'Schedules' && source === 'ScheduledScene') ||\n\t\t\t\t(target === 'Scenes' && source === 'LightScene');\n\n\t\t\tif (pairing) {\n\t\t\t\tresultList = this.controller.transformIntoNewInstance(source);\n\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = resultList;\n\t\t\t\treply.error = null;\n\t\t\t} else {\n\t\t\t\treply.code = 400;\n\t\t\t\treply.error = 'Bad Request. Following transformations are allowed: IfThen/LogicalRules > Rules, ScheduledScene > Schedules, LightScene > Scenes';\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\treply.error += ' Error: ' + e.toString();\n\t\t}\n\n\t\treturn reply;\n\t},\n\trevertTransformModuleFlag: function() {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: 'Something went wrong.',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\ttransformationsDone = false;\n\n\t\ttry {\n\n\t\t\t_.forEach(this.controller.instances, function(instance) {\n\t\t\t\tif (instance.params.moduleAPITransformed) {\n\t\t\t\t\t// remove transformed flag\n\t\t\t\t\tdelete instance.params.moduleAPITransformed;\n\t\t\t\t\tself.controller.reconfigureInstance(instance.id, instance);\n\t\t\t\t\ttransformationsDone = true;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treply.code = 200;\n\t\t\treply.data = transformationsDone ? 'successfull' : 'No transformations found.';\n\t\t\treply.error = null;\n\n\t\t} catch (e) {\n\t\t\treply.error += ' Error: ' + e.toString();\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// install module\n\tinstallModule: function() {\n\t\tvar reply = {\n\t\t\t\terror: {\n\t\t\t\t\tkey: null,\n\t\t\t\t\terrorMsg: null\n\t\t\t\t},\n\t\t\t\tdata: {\n\t\t\t\t\tkey: null,\n\t\t\t\t\tappendix: null\n\t\t\t\t},\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tmoduleUrl = parseToObject(this.req.body).moduleUrl,\n\t\t\tresult = \"\",\n\t\t\tmoduleId = moduleUrl.split(/[\\/]+/).pop().split(/[.]+/).shift();\n\n\t\tif (!this.controller.modules[moduleId]) {\n\n\t\t\t// download and install the module\n\t\t\tresult = this.controller.installModule(moduleUrl, moduleId);\n\n\t\t\tif (result === \"done\") {\n\n\t\t\t\tloadSuccessfully = this.controller.loadInstalledModule(moduleId, 'userModules/', false);\n\n\t\t\t\tif (loadSuccessfully) {\n\t\t\t\t\treply.code = 201;\n\t\t\t\t\treply.data.key = \"app_installation_successful\"; // send language key as response\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 201;\n\t\t\t\t\treply.data.key = \"app_installation_successful_but_restart_necessary\"; // send language key as response\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error.key = 'app_failed_to_install';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 409;\n\t\t\treply.error.key = 'app_from_url_already_exist';\n\t\t}\n\t\treturn reply;\n\t},\n\tupdateModule: function() {\n\t\tvar reply = {\n\t\t\t\terror: {\n\t\t\t\t\tkey: null,\n\t\t\t\t\terrorMsg: null\n\t\t\t\t},\n\t\t\t\tdata: {\n\t\t\t\t\tkey: null,\n\t\t\t\t\tappendix: null\n\t\t\t\t},\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tmoduleUrl = parseToObject(this.req.body).moduleUrl,\n\t\t\tresult = \"\",\n\t\t\tmoduleId = moduleUrl.split(/[\\/]+/).pop().split(/[.]+/).shift();\n\n\t\tif (this.controller.modules[moduleId]) {\n\n\t\t\t// download and install/overwrite the module\n\t\t\tresult = this.controller.installModule(moduleUrl, moduleId);\n\n\t\t\tif (result === \"done\") {\n\n\t\t\t\tloadSuccessfully = this.controller.reinitializeModule(moduleId, 'userModules/');\n\n\t\t\t\tif (loadSuccessfully) {\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.data.key = \"app_update_successful\"; // send language key as response\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.data.key = \"app_update_successful_but_restart_necessary\"; // send language key as response\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error.key = 'app_failed_to_update';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error.key = 'app_from_url_not_exist';\n\t\t}\n\t\treturn reply;\n\t},\n\tdeleteModule: function(moduleId) {\n\t\tvar reply = {\n\t\t\t\terror: {\n\t\t\t\t\tkey: null\n\t\t\t\t},\n\t\t\t\tdata: {\n\t\t\t\t\tkey: null,\n\t\t\t\t\tappendix: null\n\t\t\t\t},\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tuninstall = false;\n\n\t\tif (this.controller.modules[moduleId]) {\n\n\t\t\tuninstall = this.controller.uninstallModule(moduleId);\n\n\t\t\tif (uninstall) {\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data.key = \"app_delete_successful\"; // send language key as response\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error.key = 'app_failed_to_delete';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error.key = 'app_not_exist';\n\t\t}\n\t\treturn reply;\n\t},\n\tresetModule: function(moduleId) {\n\t\tvar reply = {\n\t\t\t\terror: {},\n\t\t\t\tdata: {},\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tunload;\n\n\t\tvar result = \"in progress\";\n\n\t\tif (this.controller.modules[moduleId]) {\n\n\t\t\tif (this.controller.modules[moduleId].location === ('userModules/' + moduleId) && fs.list('modules/' + moduleId)) {\n\n\t\t\t\tuninstall = this.controller.uninstallModule(moduleId, true);\n\n\t\t\t\tif (uninstall) {\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.data.key = 'app_reset_successful_to_version';\n\t\t\t\t\treply.data.appendix = this.controller.modules[moduleId].meta.version;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 500;\n\t\t\t\t\treply.error = 'There was an error during resetting the app ' + moduleId + '. Maybe a server restart could solve this problem.';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 412;\n\t\t\t\treply.error.key = 'app_is_still_reseted';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error.key = 'app_not_exist';\n\t\t}\n\t\treturn reply;\n\t},\n\tgetModuleTokens: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\ttokenObj = {\n\t\t\t\ttokens: []\n\t\t\t},\n\t\t\tgetTokens = function() {\n\t\t\t\treturn loadObject('moduleTokens.json');\n\t\t\t};\n\n\t\tif (getTokens() === null) {\n\t\t\tsaveObject('moduleTokens.json', tokenObj, true);\n\t\t}\n\n\t\tif (!!getTokens()) {\n\t\t\treply.data = getTokens();\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_tokens';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tstoreModuleToken: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\ttokenObj = loadObject('moduleTokens.json');\n\n\t\tif (tokenObj === null) {\n\t\t\tsaveObject('moduleTokens.json', tokenObj, true);\n\n\t\t\t// try to load it again\n\t\t\ttokenObj = loadObject('moduleTokens.json');\n\t\t}\n\n\t\tif (reqObj && reqObj.token && !!tokenObj && tokenObj.tokens) {\n\t\t\tif (tokenObj.tokens.indexOf(reqObj.token) < 0) {\n\t\t\t\t// add new token id\n\t\t\t\ttokenObj.tokens.push(reqObj.token);\n\n\t\t\t\t// save tokens\n\t\t\t\tsaveObject('moduleTokens.json', tokenObj, true);\n\n\t\t\t\treply.data = tokenObj;\n\t\t\t\treply.code = 201;\n\t\t\t} else {\n\t\t\t\treply.code = 409;\n\t\t\t\treply.error = 'token_not_unique';\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_tokens';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tdeleteModuleToken: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\ttokenObj = loadObject('moduleTokens.json');\n\n\t\tif (reqObj && reqObj.token && !!tokenObj && tokenObj.tokens) {\n\t\t\tif (tokenObj.tokens.indexOf(reqObj.token) > -1) {\n\t\t\t\t// add new token id\n\t\t\t\ttokenObj.tokens = _.filter(tokenObj.tokens, function(token) {\n\t\t\t\t\treturn token !== reqObj.token;\n\t\t\t\t});\n\n\t\t\t\t// save tokens\n\t\t\t\tsaveObject('moduleTokens.json', tokenObj, true);\n\n\t\t\t\treply.data = tokenObj;\n\t\t\t\treply.code = 200;\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'not_existing_token';\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_tokens';\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// reinitialize modules\n\treinitializeModule: function(moduleId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tlocation = [],\n\t\t\tloadSuccessfully = 0;\n\n\t\tif (fs.list('modules/' + moduleId)) {\n\t\t\tlocation.push('modules/');\n\t\t}\n\n\t\tif (fs.list('userModules/' + moduleId)) {\n\t\t\tlocation.push('userModules/');\n\t\t}\n\n\t\tif (location.length > 0) {\n\t\t\ttry {\n\n\t\t\t\t_.forEach(location, function(loc) {\n\t\t\t\t\tloadSuccessfully += this.controller.reinitializeModule(moduleId, loc);\n\t\t\t\t});\n\n\t\t\t\tif (loadSuccessfully > 0) {\n\t\t\t\t\treply.data = 'Reinitialization of app \"' + moduleId + '\" successfull.';\n\t\t\t\t\treply.code = 200;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\treply.error = e.toString();\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"App not found.\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// instances\n\tlistInstances: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\tinstances = this.controller.listInstances();\n\t\tif (instances) {\n\t\t\treply.data = instances;\n\t\t} else {\n\t\t\treply.code = 500;\n\t\t\treply.error = 'Could not list Instances.';\n\t\t}\n\n\n\t\treturn reply;\n\t},\n\tcreateInstance: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = this.req.reqObj,\n\t\t\tinstance;\n\n\t\tif (this.controller.modules.hasOwnProperty(reqObj.moduleId)) {\n\t\t\tinstance = this.controller.createInstance(reqObj);\n\t\t\tif (!!instance && instance) {\n\t\t\t\treply.code = 201;\n\t\t\t\treply.data = instance;\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Cannot instantiate module \" + reqObj.moduleId;\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Module \" + reqObj.moduleId + \" doesn't exist\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetInstanceFunc: function(instanceId) {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tif (isNaN(instanceId)) {\n\t\t\tinstance = _.filter(this.controller.instances, function(i) {\n\t\t\t\treturn instanceId === i.moduleId;\n\t\t\t});\n\t\t} else {\n\t\t\tinstance = _.find(this.controller.instances, function(i) {\n\t\t\t\treturn parseInt(instanceId) === i.id;\n\t\t\t});\n\t\t}\n\n\t\tif (!Boolean(instance) || instance.length === 0) {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Instance \" + instanceId + \" is not found\";\n\t\t} else {\n\t\t\treply.code = 200;\n\t\t\treply.data = instance;\n\t\t}\n\n\t\treturn reply;\n\t},\n\treconfigureInstanceFunc: function(instanceId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\treqObj = this.req.reqObj,\n\t\t\tinstance;\n\n\t\tif (!_.any(this.controller.instances, function(instance) {\n\t\t\t\treturn instanceId === instance.id;\n\t\t\t})) {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Instance \" + instanceId + \" doesn't exist\";\n\t\t} else {\n\t\t\tinstance = this.controller.reconfigureInstance(instanceId, reqObj);\n\t\t\tif (instance) {\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = instance;\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Cannot reconfigure module \" + instanceId + \" config\";\n\t\t\t}\n\t\t}\n\n\t\treturn reply;\n\t},\n\tdeleteInstanceFunc: function(instanceId) {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 200\n\t\t};\n\n\t\tif (!_.any(this.controller.instances, function(instance) {\n\t\t\t\treturn instance.id === instanceId;\n\t\t\t})) {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Instance \" + instanceId + \" not found\";\n\t\t} else {\n\t\t\treply.code = 204;\n\t\t\treply.data = null;\n\t\t\tthis.controller.deleteInstance(instanceId);\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// profiles\n\tlistProfiles: function(profileId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tprofiles,\n\t\t\tgetProfile,\n\t\t\texcl = [];\n\n\t\t// list all profiles only if user has 'admin' permissions\n\t\tif (!_.isNumber(profileId)) {\n\t\t\tif (this.req.role === this.ROLE.ADMIN) {\n\t\t\t\tprofiles = this.controller.getListProfiles();\n\t\t\t} else {\n\t\t\t\tgetProfile = this.controller.safeProfile(this.controller.getProfile(this.req.user), [\"role\", \"authTokens\"]);\n\t\t\t\tif (getProfile) {\n\t\t\t\t\tprofiles = [getProfile];\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!Array.isArray(profiles)) {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Unknown error\";\n\t\t\t} else {\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = profiles;\n\t\t\t}\n\t\t} else {\n\t\t\tgetProfile = this.controller.getProfile(profileId);\n\t\t\tif (!!getProfile && (this.req.role === this.ROLE.ADMIN || (this.req.role === this.ROLE.USER && this.req.user === getProfile.id))) {\n\n\t\t\t\t// do not send password (also role if user is not admin)\n\t\t\t\tif (this.req.role === this.ROLE.ADMIN) {\n\t\t\t\t\texcl = [];\n\t\t\t\t} else {\n\t\t\t\t\texcl = [\"role\"];\n\t\t\t\t}\n\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = this.controller.safeProfile(getProfile);\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = \"Profile not found.\";\n\t\t\t}\n\t\t}\n\n\t\treturn reply;\n\t},\n\tcreateProfile: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj,\n\t\t\tprofile,\n\t\t\tuniqueEmail = [],\n\t\t\tuniqueLogin = [];\n\n\t\ttry {\n\t\t\treqObj = JSON.parse(this.req.body);\n\t\t} catch (ex) {\n\t\t\treply.error = ex.message;\n\t\t\treturn reply;\n\t\t}\n\n\t\tuniqueEmail = _.filter(this.controller.profiles, function(p) {\n\t\t\treturn p.email !== '' && p.email === reqObj.email;\n\t\t});\n\n\t\tuniqueLogin = _.filter(this.controller.profiles, function(p) {\n\t\t\treturn p.login !== '' && p.login === reqObj.login;\n\t\t});\n\n\t\tif (uniqueEmail.length > 0) {\n\t\t\treply.code = 409;\n\t\t\treply.error = 'nonunique_email';\n\t\t} else if (uniqueLogin.length > 0) {\n\t\t\treply.code = 409;\n\t\t\treply.error = 'nonunique_user';\n\t\t} else {\n\t\t\t_.defaults(reqObj, {\n\t\t\t\trole: null,\n\t\t\t\tname: 'User',\n\t\t\t\temail: '',\n\t\t\t\tlang: 'en',\n\t\t\t\tdashboard: [],\n\t\t\t\tinterval: 2000,\n\t\t\t\trooms: reqObj.role === this.ROLE.ADMIN ? [0] : [],\n\t\t\t\tdevices: [],\n\t\t\t\texpert_view: false,\n\t\t\t\thide_all_device_events: false,\n\t\t\t\thide_system_events: false,\n\t\t\t\thide_single_device_events: [],\n\t\t\t\tskin: '',\n\t\t\t\tnight_mode: false,\n\t\t\t});\n\n\t\t\t// skip OAuth2 and other metadata\n\t\t\treqObj = _.omit(reqObj, 'passwordConfirm', 'client_id', 'response_type', 'redirect_uri');\n\n\t\t\tprofile = this.controller.createProfile(reqObj);\n\t\t\tif (profile !== undefined && profile.id !== undefined) {\n\t\t\t\treply.data = this.controller.safeProfile(profile);\n\t\t\t\treply.code = 201;\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Profile creation error\";\n\t\t\t}\n\t\t}\n\n\t\treturn reply;\n\t},\n\tcreateOAuth2Profile: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj,\n\t\t\tprofile,\n\t\t\tprofileReply,\n\t\t\tzbwToken,\n\t\t\tsid,\n\t\t\toauthReply,\n\t\t\tauthToken,\n\t\t\tclientId;\n\t\t\n\t\t// check that find.z-wave.me token is present\n\t\tif (this.req.headers['Cookie']) {\n\t\t\tvar zbwCookie = this.req.headers['Cookie'].split(\";\").map(function(el) { return el.trim().split(\"=\"); }).filter(function(el) { return el[0] === \"ZBW_SESSID\" })[0];\n\t\t\tif (zbwCookie) zbwToken = zbwCookie[1];\n\t\t}\n\t\tif (!zbwToken) {\n\t\t\treply.code = 405;\n\t\t\treply.error = \"This method must be called thru find.z-wave.me\";\n\t\t\treturn reply;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\treqObj = JSON.parse(this.req.body);\n\t\t\tclientId = reqObj.client_id;\n\t\t\tredirectUri = reqObj.redirect_uri;\n\t\t\tresponseType = reqObj.response_type;\n\t\t} catch (ex) {\n\t\t\treply.code = 500;\n\t\t\treply.error = ex.message;\n\t\t\treturn reply;\n\t\t}\n\t\t\n\t\tprofileReply = this.createProfile();\n\t\t\n\t\tif (profileReply.code !== 200 && profileReply.code !== 201) return profileReply;\n\t\t\n\t\t// profileReply.data is a safe copy, so get the original profile for checkIn\n\t\tprofile = _.find(this.controller.profiles, function (_profile) {\n\t\t\treturn _profile.id == profileReply.data.id;\n\t\t});\n\t\t\n\t\t// create permanent auth token for this user\n\t\tsid = this.controller.auth.checkIn(profile, this.req, true);\n\t\tdata = {\n\t\t\taccess_token: zbwToken + \"/\" + sid,\n\t\t\tclient_id: clientId,\n\t\t\tredirect_uri: redirectUri,\n\t\t\tresponse_type: responseType\n\t\t}\n\t\toauthReply = http.request({\n\t\t\turl: \"https://oauth2.z-wave.me:5000/saveToken\",\n\t\t\tmethod: \"POST\",\n\t\t\tasync: false,\n\t\t\theaders: {\n\t\t\t\t'Content-Type':'application/json'\n\t\t\t},\n\t\t\tdata: JSON.stringify(data)\n\t\t});\n\t\tif (oauthReply.status != 200) {\n\t\t\tthis.removeProfile(profile.id); // revert creation of the user\n\t\t\treply.code = oauthReply.status;\n\t\t\treply.error = oauthReply.statusText;\n\t\t\treturn reply\n\t\t}\n\t\tauthCode = oauthReply.data.auth_code;\n\t\tif (!authCode) {\n\t\t\tthis.removeProfile(profile.id); // revert creation of the user\n\t\t\treply.code = 500;\n\t\t\treply.error = \"OAuth2 auth token is empty\";\n\t\t\treturn reply\n\t\t}\n\t\t\n\t\treply.code = 200;\n\t\treply.data = {\n\t\t\tauth_code: authCode\n\t\t};\n\t\treturn reply;\n\t},\n\tupdateProfile: function(profileId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj,\n\t\t\tprofile = _.clone(this.controller.getProfile(profileId)), // clone to allow check changes in controller.updateProfile\n\t\t\tuniqueProfProps = [];\n\n\t\tif (profile && (this.req.role === this.ROLE.ADMIN || (this.req.role === this.ROLE.USER && this.req.user === profile.id))) {\n\t\t\treqObj = JSON.parse(this.req.body);\n\n\t\t\tif (profile.id === this.req.user && profile.role === this.ROLE.ADMIN && reqObj.role !== this.ROLE.ADMIN) {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Revoking self Admin priviledge is not allowed.\";\n\t\t\t} else {\n\t\t\t\t// check that e-mail is unique or empty\n\t\t\t\tuniqueProfProps = _.filter(this.controller.profiles, function(p) {\n\t\t\t\t\treturn (p.email !== '' && p.email === reqObj.email) &&\n\t\t\t\t\t\tp.id !== profileId;\n\t\t\t\t});\n\n\t\t\t\tif (uniqueProfProps.length === 0) {\n\t\t\t\t\t// only Admin can change critical parameters\n\t\t\t\t\tif (this.req.role === this.ROLE.ADMIN) {\n\t\t\t\t\t\t// id is never changeable\n\t\t\t\t\t\t// login is changed by updateProfileAuth()\n\t\t\t\t\t\tprofile.role = reqObj.role;\n\t\t\t\t\t\tprofile.rooms = reqObj.rooms.indexOf(0) === -1 && reqObj.role === this.ROLE.ADMIN ? reqObj.rooms.push(0) : reqObj.rooms;\n\t\t\t\t\t\tprofile.devices = reqObj.devices || [];\n\t\t\t\t\t\tprofile.expert_view = reqObj.expert_view;\n\t\t\t\t\t\tprofile.beta = reqObj.beta;\n\t\t\t\t\t}\n\t\t\t\t\t// could be changed by user role\n\t\t\t\t\tprofile.name = reqObj.name; // profile name\n\t\t\t\t\tprofile.interval = reqObj.interval; // update interval from ui\n\t\t\t\t\tprofile.hide_system_events = reqObj.hide_system_events;\n\t\t\t\t\tprofile.hide_all_device_events = reqObj.hide_all_device_events;\n\t\t\t\t\tprofile.lang = reqObj.lang;\n\t\t\t\t\tprofile.dashboard = reqObj.dashboard;\n\t\t\t\t\tprofile.hide_single_device_events = reqObj.hide_single_device_events;\n\t\t\t\t\tprofile.email = reqObj.email;\n\t\t\t\t\tprofile.night_mode = reqObj.night_mode;\n\n\t\t\t\t\tprofile = this.controller.updateProfile(profile, profile.id);\n\n\t\t\t\t\tif (profile !== undefined && profile.id !== undefined) {\n\t\t\t\t\t\treply.data = this.controller.safeProfile(profile);\n\t\t\t\t\t\treply.code = 200;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.code = 500;\n\t\t\t\t\t\treply.error = \"Profile was not created\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 409;\n\t\t\t\t\treply.error = 'nonunique_email';\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found.\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// different pipe for updating authentication values\n\tupdateProfileAuth: function(profileId) {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj,\n\t\t\tprofile = this.controller.getProfile(profileId),\n\t\t\tuniqueLogin = [],\n\t\t\treqToken = this.req.reqObj.hasOwnProperty(\"token\") ? this.req.reqObj.token : null,\n\t\t\ttokenObj = {};\n\n\t\treqObj = JSON.parse(this.req.body);\n\n\t\tif (profile && (this.req.role === this.ROLE.ADMIN || (this.req.role === this.ROLE.USER && this.req.user === profile.id))) {\n\n\t\t\tuniqueLogin = _.filter(this.controller.profiles, function(p) {\n\t\t\t\tif (self.req.role === self.ROLE.ADMIN && self.req.user !== parseInt(reqObj.id, 10)) {\n\t\t\t\t\treturn p.login !== '' && p.login === reqObj.login && p.id !== parseInt(reqObj.id, 10);\n\t\t\t\t} else {\n\t\t\t\t\treturn p.login !== '' && p.login === reqObj.login && p.id !== self.req.user;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (uniqueLogin.length < 1) {\n\t\t\t\tprofile = this.controller.updateProfileAuth(reqObj, profileId);\n\n\t\t\t\tif (!!profile && profile.id !== undefined) {\n\t\t\t\t\treply.data = this.controller.safeProfile(profile);\n\t\t\t\t\treply.code = 200;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 500;\n\t\t\t\t\treply.error = \"Was not able to update password.\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 409;\n\t\t\t\treply.error = 'nonunique_user';\n\t\t\t}\n\t\t} else if (this.req.role === this.ROLE.ANONYMOUS && profileId && !!reqToken) {\n\t\t\ttokenObj = self.controller.auth.getForgottenPwdToken(reqToken);\n\n\t\t\tif (tokenObj && !!tokenObj) {\n\t\t\t\tprofile = this.controller.updateProfileAuth(reqObj, profileId);\n\n\t\t\t\tif (!!profile && profile.id !== undefined) {\n\t\t\t\t\t// remove forgotten token\n\t\t\t\t\tself.controller.auth.removeForgottenPwdEntry(reqToken);\n\n\t\t\t\t\treply.code = 200;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 500;\n\t\t\t\t\treply.error = \"Was not able to update password.\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = \"Token not found.\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 403;\n\t\t\treply.error = \"Forbidden.\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\trestorePassword: function(profileId) {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = typeof this.req.body !== 'object' ? JSON.parse(this.req.body) : this.req.body,\n\t\t\treqToken = this.req.query.hasOwnProperty(\"token\") ? this.req.query.token : null,\n\t\t\tprofile,\n\t\t\temailExists = [],\n\t\t\ttokenObj;\n\n\t\tif (reqObj.email) {\n\t\t\temailExists = _.filter(self.controller.profiles, function(profile) {\n\t\t\t\treturn profile.email !== '' && profile.email === reqObj.email;\n\t\t\t});\n\t\t}\n\n\t\tif (reqToken === null && emailExists.length > 0 && !profileId) {\n\n\t\t\ttry {\n\t\t\t\tvar tkn = crypto.guid(),\n\t\t\t\t\tsuccess = self.controller.auth.forgottenPwd(reqObj.email, tkn);\n\n\t\t\t\tif (success) {\n\t\t\t\t\treply.data = {\n\t\t\t\t\t\ttoken: tkn\n\t\t\t\t\t};\n\t\t\t\t\treply.code = 200;\n\t\t\t\t} else {\n\t\t\t\t\treply.error = \"Token request for e-mail already exists.\";\n\t\t\t\t\treply.code = 409;\n\t\t\t\t}\n\n\t\t\t} catch (e) {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Internal server error.\";\n\t\t\t}\n\t\t} else if (!!reqToken && emailExists.length < 1 && !profileId) {\n\t\t\ttry {\n\t\t\t\ttokenObj = self.controller.auth.getForgottenPwdToken(reqToken);\n\n\t\t\t\tif (tokenObj && !!tokenObj) {\n\n\t\t\t\t\tprofile = _.filter(self.controller.profiles, function(p) {\n\t\t\t\t\t\treturn p.email === tokenObj.email;\n\t\t\t\t\t});\n\n\t\t\t\t\tif (profile[0]) {\n\t\t\t\t\t\treply.code = 200;\n\t\t\t\t\t\treply.data = {\n\t\t\t\t\t\t\tuserId: profile[0].id\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\treply.error = \"User not found.\";\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = \"Token not found.\";\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Internal server error.\";\n\t\t\t}\n\t\t} else if (!!reqToken && emailExists.length < 1 && profileId) {\n\n\t\t\tprofile = self.controller.updateProfileAuth(reqObj, profileId);\n\n\t\t\tif (!!profile && profile.id !== undefined) {\n\t\t\t\treply.code = 200;\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Wasn't able to update password.\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Email not found.\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tremoveProfile: function(profileId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tprofile = this.controller.getProfile(profileId);\n\n\t\tif (profile) {\n\t\t\t// It is not possible to delete own profile\n\t\t\tif (profile.id !== this.req.user) {\n\t\t\t\tthis.controller.removeProfile(profileId);\n\t\t\t\treply.data = null;\n\t\t\t\treply.code = 204;\n\t\t\t} else {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Deleting own profile is not allowed.\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tremoveOwnProfile: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tprofile = this.controller.getProfile(this.req.user);\n\t\tif (profile) {\n\t\t\t// It is possible to delete own profile if the role is USER\n\t\t\tif (this.req.role === profile.role) {\n\t\t\t\tif (profile.authTokens.length == 1) {\n\t\t\t\t\t// remove full profile\n\t\t\t\t\tthis.controller.removeProfile(this.req.user);\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.code = 204;\n\t\t\t\t} else if (profile.authTokens.length > 1) {\n\t\t\t\t\t// remove single token\n\t\t\t\t\tthis.controller.removeToken(profile, this.req.token)\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.code = 204;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = \"No tokens found - how have you logged in?\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Deleting is possible only for own user profile.\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found\";\n\t\t}\n\t\treturn reply;\n\t},\n\tremoveToken: function(profileId, token) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tprofile = this.controller.getProfile(profileId);\n\n\t\tif (profile) {\n\t\t\t// Manage own tokens for users or any token for admin\n\t\t\tif (profile.id === this.req.user && this.req.role === this.ROLE.USER || this.req.role === this.ROLE.ADMIN) {\n\t\t\t\tif (this.controller.removeToken(profile, token)) {\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.code = 204;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = \"Token not found\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Permission denied\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tpermanentToken: function(profileId, token) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tprofile = this.controller.getProfile(profileId);\n\n\t\tif (profile) {\n\t\t\t// Manage own tokens for users or any token for admin\n\t\t\tif (profile.id === this.req.user && this.req.role === this.ROLE.USER || this.req.role === this.ROLE.ADMIN) {\n\t\t\t\tif (this.controller.permanentToken(profile, token)) {\n\t\t\t\t\treply.data = null;\n\t\t\t\t\treply.code = 204;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = \"Token not found\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 403;\n\t\t\t\treply.error = \"Permission denied\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetQRCodeString: function(profileId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tprofile = this.controller.getProfile(profileId);\n\n\t\ttry {\n\t\t\tvar reqObj = parseToObject(this.req.body);\n\t\t} catch (e) {\n\t\t\treturn reply.error = e.message;\n\t\t}\n\n\t\tif (profile) {\n\t\t\tif (this.req.role === this.ROLE.ADMIN || (this.req.role === this.ROLE.USER && this.req.user === profileId)) {\n\t\t\t\tvar pwd_check = reqObj.password ? (!profile.salt && profile.password === reqObj.password) || (profile.salt && profile.password === hashPassword(reqObj.password, profile.salt)) : false;\n\t\t\t\tif (pwd_check) {\n\t\t\t\t\tvar qrcode_str = this.controller.getQRCodeData(profile, reqObj.password);\n\n\t\t\t\t\tif (qrcode_str !== undefined) {\n\t\t\t\t\t\treply.code = 200;\n\t\t\t\t\t\treply.data = qrcode_str;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.code = 500;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treply.error = \"wrong_password\";\n\t\t\t\t\treply.code = 500;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.error = \"Forbidden\";\n\t\t\t\treply.code = 403;\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\t/* Generating a local access token for the user. */\n\tgenerateLocalAccessToken: function (profileId) {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\t\tvar profile = _.find(this.controller.profiles, function (_profile) {\n\t\t\treturn _profile.id === profileId;\n\t\t});\n\t\tif (profile) {\n\t\t\tvar sid = this.controller.auth.checkIn(profile, this.req, true);\n\t\t\tvar remoteId = this.controller.getRemoteId();\n\t\t\treply.code = 200;\n\t\t\treply.data =  {\n\t\t\t\ttoken: sid,\n\t\t\t\tremoteId: remoteId\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Profile not found\";\n\t\t}\n\t\treturn reply;\n\t},\n\tnotificationFilteringGet: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t    self = this;\n\t\t\n\t\tvar userDevices = this.controller.devicesByUser(this.req.user).map(function(dev) { return dev.id; });\n\t\tvar nfInstance = this.controller.listInstances().filter(function(i) { return i.moduleId === \"NotificationFiltering\"})[0]; // dirty hack - think about exported function by NotificationFiltering app\n\t\t\n\t\tif (nfInstance) {\n\t\t\tvar devsStruct = [];\n\t\t\tvar arr = nfInstance.params.rules.filter(function(rule) {\n\t\t\t\tvar channel = self.controller.getNotificationChannel(rule.channel);\n\t\t\t\treturn false || \n\t\t\t\t   (rule.recipient_type === \"user\" && rule.user == self.req.user) || // non-strict == because might be as string in module params\n\t\t\t\t   (rule.recipient_type === \"channel\" && channel && channel.user == self.req.user); // non-strict == because might be as string in module params\n\t\t\t}).forEach(function(rule) { // flatten structure\n\t\t\t\trule.devices.forEach(function(devStruct) {\n\t\t\t\t\tif (userDevices.indexOf(devStruct[devStruct[\"dev_filter\"]][\"dev_select\"]) > -1) { // filter devices by allowed list\n\t\t\t\t\t\tvar _devStruct = _.clone(devStruct);\n\t\t\t\t\t\t_devStruct.channel = rule.recipient_type === \"channel\" ? rule.channel : null;\n\t\t\t\t\t\tdevsStruct.push(_devStruct);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t\treply.data = devsStruct;\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.code = 501;\n\t\t\treply.error = \"Not implemented. Activate NotificationFilter app\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tnotificationFilteringSet: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t    self = this;\n\n\t\tvar userConfig = [];\n\t\ttry {\n\t\t\tvar reqObj = parseToObject(this.req.body);\n\t\t\t\n\t\t\t// Transform to NotificationFiltring format\n\t\t\t// Do sanity check not to let user break global NotificationFiltring config\n\t\t\treqObj.forEach(function(rule) {\n\t\t\t\tvar channel = rule.channel;\n\t\t\t\trule.channel = undefined;\n\t\t\t\t\n\t\t\t\tif (!rule[\"dev_filter\"] || !rule[rule[\"dev_filter\"]][\"dev_select\"]) return;\n\t\t\t\t\n\t\t\t\tuserConfig.push({\n\t\t\t\t\trecipient_type: channel ? \"channel\" : \"user\",\n\t\t\t\t\tuser: channel ? undefined : self.req.user,\n\t\t\t\t\tchannel: channel ? channel : undefined,\n\t\t\t\t\tlogLevel: \"\",\n\t\t\t\t\tdevices: [rule]\n\t\t\t\t});\n\t\t\t});\n\t\t} catch (e) {\n\t\t\treturn reply.error = e.message;\n\t\t}\n\t\t\n\t\tthis.controller.emit('notificationFiltering.userConfigUpdate', this.req.user, userConfig);\n\t\t\n\t\treply.code = 200;\n\n\t\treturn reply;\n\t},\n\tnotificationChannelsGet: function(all) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t    self = this;\n\t\t\n\t\tvar channels = this.controller.notificationChannels;\n\t\t\n\t\treply.data = Object.keys(channels).map(function(ch) {\n\t\t\tvar profile = self.controller.getProfile(channels[ch].user);\n\t\t\treturn _.extend({id: ch, userName: profile ? profile.name : \"-\" }, channels[ch]);\n\t\t}).filter(function(ch) {\n\t\t\treturn ch.user == self.req.user || (all && self.req.role === self.ROLE.ADMIN);\n\t\t});\n\t\treply.code = 200;\n\n\t\treturn reply;\n\t},\n\tnotificationChannelsGetAll: function() {\n\t\treturn this.notificationChannelsGet(true);\n\t},\n\t// namespaces\n\tlistNamespaces: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tnspc;\n\n\t\tnspc = this.controller.namespaces;\n\n\t\tif (_.isArray(nspc) && nspc.length > 0) {\n\t\t\treply.data = nspc;\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"Namespaces array is null\";\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetNamespaceFunc: function(namespaceId) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tnamespace;\n\n\t\tnamespace = this.controller.getListNamespaces(namespaceId, this.controller.namespaces);\n\t\tif (!namespace || (_.isArray(namespace) && namespace.length < 1)) {\n\t\t\treply.code = 404;\n\t\t\treply.error = \"No namespaces found with this path: \" + namespaceId;\n\t\t} else {\n\t\t\treply.data = namespace;\n\t\t\treply.code = 200;\n\t\t}\n\n\t\treturn reply;\n\t},\n\t// restart\n\trestartController: function(profileId) {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 200\n\t\t};\n\n\t\tthis.controller.restart();\n\t\treturn reply;\n\t},\n\tloadModuleMedia: function(moduleName, fileName) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\tobj, _obj;\n\n\t\tif ((moduleName !== '' || !!moduleName || moduleName) && (fileName !== '' || !!fileName || fileName)) {\n\t\t\tobj = this.controller.loadModuleMedia(moduleName, fileName);\n\t\t\t\n\t\t\tif (obj && obj.data === \"\") { // for folder we will get empty - try to open index.html\n\t\t\t\t_obj = this.controller.loadModuleMedia(moduleName, fileName + \"/index.html\");\n\t\t\t\tif (_obj && !!_obj.data) {\n\t\t\t\t\tobj = _obj;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!this.controller.modules[moduleName]) {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = \"Can't load file from app because app '\" + moduleName + \"' was not found.\";\n\n\t\t\t\treturn reply;\n\n\t\t\t} else if (obj !== null) {\n\t\t\t\tthis.res.status = 200;\n\t\t\t\tthis.res.headers = {\n\t\t\t\t\t\"Content-Type\": obj.ct\n\t\t\t\t};\n\t\t\t\tthis.res.body = obj.data;\n\n\t\t\t\treturn null; // let handleRequest take this.res as is\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Failed to load file from module.\";\n\n\t\t\t\treturn reply;\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 400;\n\t\t\treply.error = \"Incorrect app or file name\";\n\n\t\t\treturn reply;\n\t\t}\n\t},\n\tloadImage: function(imageName) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\tdata;\n\n\t\tdata = this.controller.loadImage(imageName);\n\n\t\tif (data !== null) {\n\t\t\tthis.res.status = 200;\n\t\t\tthis.res.headers = {\n\t\t\t\t\"Content-Type\": \"image/*\"\n\t\t\t};\n\t\t\tthis.res.body = data;\n\n\t\t\treturn null; // let handleRequest take this.res as is\n\t\t} else {\n\t\t\treply.code = 500;\n\t\t\treply.error = \"Failed to load file.\";\n\n\t\t\treturn reply;\n\t\t}\n\t},\n\tuploadFile: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 200\n\t\t\t},\n\t\t\tfile;\n\n\t\tif (this.req.method === \"POST\" && this.req.body) {\n\n\t\t\tfor (prop in this.req.body) {\n\t\t\t\tif (this.req.body[prop]['content']) {\n\t\t\t\t\tfile = this.req.body[prop];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (_.isArray(file)) {\n\t\t\t\tfile = file[0];\n\t\t\t}\n\n\t\t\tif (file && file.name && file.content || (_.isArray(file) && file.length > 0)) {\n\n\t\t\t\tif (~file.name.indexOf('.csv') && typeof Papa === 'object') {\n\t\t\t\t\tvar csv = null;\n\t\t\t\t\tPapa.parse(file.content, {\n\t\t\t\t\t\theader: true,\n\t\t\t\t\t\tdynamicTyping: true,\n\t\t\t\t\t\tcomplete: function(results) {\n\t\t\t\t\t\t\tcsv = results;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!!csv) {\n\t\t\t\t\t\tsaveObject(file.name, csv, true);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Create Base64 Object\n\t\t\t\t\tsaveObject(file.name, Base64.encode(file.content), true);\n\t\t\t\t}\n\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = file.name;\n\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = \"Failed to upload file\";\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 400;\n\t\t\treply.error = \"Invalid request\";\n\t\t}\n\t\treturn reply;\n\t},\n\tbackup: function() {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t};\n\n\t\tvar now = new Date();\n\t\t// create a timestamp in format yyyy-MM-dd-HH-mm\n\t\tvar ts = getHRDateformat(now);\n\n\t\ttry {\n\n\t\t\tvar backupJSON = self.controller.createBackup();\n\n\t\t\treply.headers = {\n\t\t\t\t\"Content-Type\": \"application/octet-stream\", // application/x-download octet-stream\n\t\t\t\t\"Content-Disposition\": \"attachment; filename=z-way-backup-\" + ts + \".zab\"\n\t\t\t};\n\n\t\t\treply.code = 200;\n\t\t\treply.data = Base64.encode(JSON.stringify(backupJSON));\n\t\t} catch (e) {\n\t\t\treply.code = 500;\n\t\t\treply.error = e.toString();\n\t\t}\n\n\t\treturn reply;\n\t},\n\trestore: function() {\n\t\tvar self = this,\n\t\t\treqObj,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tresult = \"\",\n\t\t\tlangfile = this.controller.loadMainLang(),\n\t\t\tdontSave = this.controller.getIgnoredStorageFiles([\n\t\t\t\t\"__ZWay\",\n\t\t\t\t\"__ZBee\",\n\t\t\t\t\"__EnOcean\",\n\t\t\t\t\"__userModules\",\n\t\t\t\t\"__userSkins\"\n\t\t\t]);\n\n\t\tfunction waitForInstallation(allreadyInstalled, reqKey) {\n\t\t\tvar d = Date.now() + 300000; // wait not more than 5 min\n\n\t\t\twhile (Date.now() < d && allreadyInstalled.length <= reqObj.data[reqKey].length) {\n\n\t\t\t\tif (allreadyInstalled.length === reqObj.data[reqKey].length) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (allreadyInstalled.length === reqObj.data[reqKey].length) {\n\t\t\t\t// success\n\t\t\t\treply.code = 200;\n\t\t\t}\n\t\t}\n\n\t\t// get flag that network information should be overwritten\n\t\tallowTopoRestore = this.req.body.hasOwnProperty(\"overwriteNetwork\") ? retBoolean(this.req.body.overwriteNetwork) : false;\n\n\t\ttry {\n\t\t\tfunction utf8Decode(bytes) {\n\t\t\t\tvar chars = [];\n\n\t\t\t\tfor (var i = 0; i < bytes.length; i++) {\n\t\t\t\t\tchars[i] = bytes.charCodeAt(i);\n\t\t\t\t}\n\n\t\t\t\treturn chars;\n\t\t\t}\n\n\t\t\treqObj = parseToObject(this.req.body.backupFile.content);\n\n\t\t\tif (typeof reqObj.data === 'string') {\n\t\t\t\t// new .zab files are base64 encoded, while old are not\n\t\t\t\tdecodeData = Base64.decode(reqObj.data);\n\t\t\t\t// to JSON\n\t\t\t\treqObj.data = JSON.parse(decodeData);\n\t\t\t}\n\n\t\t\t// check if data is not empty\n\t\t\tif (!reqObj.data) {\n\t\t\t\t// missing file\n\t\t\t\treply.code = 400;\n\t\t\t\treply.error = \"Bad Request. Please input a .zab backup file.\";\n\n\t\t\t\treturn reply;\n\t\t\t}\n\n\t\t\t// stop the controller\n\t\t\tthis.controller.stop();\n\n\n\t\t\tfor (var obj in reqObj.data) {\n\n\t\t\t\tif (dontSave.indexOf(obj) === -1) {\n\t\t\t\t\tsaveObject(obj, reqObj.data[obj], true);\n\t\t\t\t\tconsole.log('Restore', obj, '... done');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start controller with reload flag to apply config.json\n\t\t\tthis.controller.start(true);\n\n\t\t\t// restore Z-Wave, Zigbee and EnOcean\n\t\t\t!!reqObj.data[\"__ZWay\"] && Object.keys(reqObj.data[\"__ZWay\"]).forEach(function(zwayName) {\n\t\t\t\tvar zwayData = utf8Decode(reqObj.data[\"__ZWay\"][zwayName]);\n\t\t\t\tglobal.ZWave[zwayName] && global.ZWave[zwayName].zway.controller.Restore(zwayData, allowTopoRestore);\n\t\t\t});\n\n\t\t\t/* TODO\n\t\t\t!!reqObj.data[\"__ZBee\"] && Object.keys(reqObj.data[\"__ZBee\"]).forEach(function(zbeeName) {\n\t\t\t\tvar zbeeData = utf8Decode(reqObj.data[\"__ZBee\"][zbeeName]);\n\t\t\t\tglobal.Zigbee[zbeeName] && global.Zigbee[zbeeName].zbee.controller.Restore(zbeeData, allowTopoRestore);\n\t\t\t});\n\t\t\t*/\n\n\t\t\t/* TODO\n\t\t\t!!reqObj.data[\"__EnOcean\"] && reqObj.data[\"__EnOcean\"].forEach(function(zenoName) {\n\t\t\t\t// global.EnOcean[zenoName] && global.EnOcean[zenoName].zeno.Restore(reqObj.data[\"__EnOcean\"][zenoName]);\n\t\t\t});\n\t\t\t*/\n\n\t\t\t// install userModules\n\t\t\tif (reqObj.data[\"__userModules\"]) {\n\t\t\t\tvar installedModules = [];\n\n\t\t\t\t_.forEach(reqObj.data[\"__userModules\"], function(entry) {\n\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: 'https://developer.z-wave.me/?uri=api-module-archive/' + entry.name,\n\t\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tsuccess: function(res) {\n\t\t\t\t\t\t\tvar archiv = [],\n\t\t\t\t\t\t\t\titem = {\n\t\t\t\t\t\t\t\t\tname: entry.name\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tlocation = 'modules/' + entry.name,\n\t\t\t\t\t\t\t\toverwriteCoreModule = false;\n\n\t\t\t\t\t\t\tif (res.data.data && res.data.data.length > 0) {\n\t\t\t\t\t\t\t\tarchiv = _.filter(res.data.data, function(appEntry) {\n\t\t\t\t\t\t\t\t\treturn appEntry.version === entry.version.toString();\n\t\t\t\t\t\t\t\t})\n\n\t\t\t\t\t\t\t\t// check if already loaded module is a core module\n\t\t\t\t\t\t\t\tcoreModule = self.controller.modules[entry.name] && self.controller.modules[entry.name].meta ? (self.controller.modules[entry.name].meta.location === location) : false;\n\n\t\t\t\t\t\t\t\t// check if version of core module isn't higher than the restored one\n\t\t\t\t\t\t\t\tif (coreModule) {\n\t\t\t\t\t\t\t\t\toverwriteCoreModule = has_higher_version(entry.version, self.controller.modules[entry.name].meta.version);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// if achive was found try to download it\n\t\t\t\t\t\t\t\tif (archiv.length > 0 && (!coreModule || (coreModule && overwriteCoreModule))) {\n\n\t\t\t\t\t\t\t\t\tconsole.log('Restore userModule', archiv[0].modulename, 'v' + archiv[0].version);\n\t\t\t\t\t\t\t\t\tresult = self.controller.installModule('https://developer.z-wave.me/archiv/' + archiv[0].archiv, archiv[0].modulename);\n\n\t\t\t\t\t\t\t\t\titem.status = result;\n\t\t\t\t\t\t\t\t\tif (result === \"done\") {\n\t\t\t\t\t\t\t\t\t\tloadSuccessfully = self.controller.reinitializeModule(entry.name, 'userModules/', true);\n\n\t\t\t\t\t\t\t\t\t\tif (!loadSuccessfully) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.addNotification(\"warning\", langfile.zaap_war_restart_necessary + ' :: ' + entry.name + ' ' + 'v' + archiv[0].version, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tself.controller.addNotification(\"warning\", langfile.zaap_err_app_install + ' :: ' + entry.name + ' ' + 'v' + archiv[0].version, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// downlaod latest if it isn't already there\n\t\t\t\t\t\t\t\t\tif (overwriteCoreModule) {\n\n\t\t\t\t\t\t\t\t\t\tconsole.log(entry.name + ':', 'No archive with this version found. Install latest ...');\n\t\t\t\t\t\t\t\t\t\tresult = self.controller.installModule('https://developer.z-wave.me/modules/' + entry.name + '.tar.gz', entry.name);\n\n\t\t\t\t\t\t\t\t\t\titem.status = result;\n\n\t\t\t\t\t\t\t\t\t\tif (result === \"done\") {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.reinitializeModule(entry.name, 'userModules/', false);\n\t\t\t\t\t\t\t\t\t\t\tself.controller.addNotification(\"warning\", langfile.zaap_war_app_installed_corrupt_instance + ' :: ' + entry.name, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_app_install + ' :: ' + entry.name, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tself.controller.addNotification(\"warning\", langfile.zaap_war_core_app_is_newer + ' :: ' + entry.name, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\t\t\t\titem.status = 'failed';\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_no_archives + ' :: ' + entry.name, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\t\titem.status = 'failed';\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tinstalledModules.push(item);\n\t\t\t\t\t\t},\n\t\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_server + ' :: ' + entry.name + '::' + res.statusText, \"core\", \"AppInstaller\");\n\t\t\t\t\t\t\tinstalledModules.push({\n\t\t\t\t\t\t\t\tname: entry.name,\n\t\t\t\t\t\t\t\tstatus: 'failed'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\n\t\t\t\twaitForInstallation(installedModules, \"__userModules\");\n\n\t\t\t}\n\n\t\t\t// install userSkins\n\t\t\tif (reqObj.data[\"__userSkins\"]) {\n\t\t\t\tvar installedSkins = [],\n\t\t\t\t\tremoteSkins = [];\n\n\t\t\t\thttp.request({\n\t\t\t\t\t// get online list of all existing modules first\n\t\t\t\t\turl: 'https://developer.z-wave.me/?uri=api-skins',\n\t\t\t\t\tmethod: 'GET',\n\t\t\t\t\tasync: true,\n\t\t\t\t\tsuccess: function(res) {\n\t\t\t\t\t\tif (res.data.data) {\n\t\t\t\t\t\t\tremoteSkins = res.data.data;\n\n\t\t\t\t\t\t\t// download all skins that are online available\n\t\t\t\t\t\t\t_.forEach(reqObj.data[\"__userSkins\"], function(entry) {\n\t\t\t\t\t\t\t\tvar item = {\n\t\t\t\t\t\t\t\t\t\tname: entry.name,\n\t\t\t\t\t\t\t\t\t\tstatus: 'failed'\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t// check if backed up skin is in online list\n\t\t\t\t\t\t\t\t\tremSkinObj = _.filter(remoteSkins, function(skin) {\n\t\t\t\t\t\t\t\t\t\treturn skin.name === entry.name;\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\tif (remSkinObj[0]) {\n\n\t\t\t\t\t\t\t\t\tindex = _.findIndex(self.controller.skins, function(skin) {\n\t\t\t\t\t\t\t\t\t\treturn skin.name === entry.name;\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t// install skin\n\t\t\t\t\t\t\t\t\t\tresult = self.controller.installSkin(remSkinObj[0], entry.name, index);\n\t\t\t\t\t\t\t\t\t\titem.status = result;\n\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_no_archives + ' :: ' + entry.name, \"core\", \"SkinInstaller\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tinstalledSkins.push(item);\n\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_server + ' :: ' + res.statusText, \"core\", \"SkinInstaller\");\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\twaitForInstallation(installedSkins, \"__userSkins\");\n\n\t\t\t}\n\n\t\t\t// success\n\t\t\treply.code = 200;\n\t\t\treply.data = {\n\t\t\t\tuserModules: installedModules,\n\t\t\t\tuserSkins: installedSkins\n\t\t\t};\n\n\t\t} catch (e) {\n\t\t\treply.error = e.toString();\n\t\t}\n\n\t\treturn reply;\n\t},\n\tresetToFactoryDefault: function() {\n\t\tvar self = this,\n\t\t\tlangFile = this.controller.loadMainLang();\n\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t};\n\n\t\t{\n\t\t\tvar backupCfg = loadObject(\"backupConfig\"),\n\t\t\tstorageContentList = loadObject(\"__storageContent\"),\n\t\t\tdefaultConfigExists = fs.stat('defaultConfigs/config.json'), // will be added during build - build depending\n\t\t\tdefaultConfig = {},\n\t\t\tdefaultSkins = [{\n\t\t\t\tname: \"default\",\n\t\t\t\ttitle: \"Default\",\n\t\t\t\tdescription: \"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.\",\n\t\t\t\tversion: \"1.0.3\",\n\t\t\t\ticon: true,\n\t\t\t\tauthor: \"Martin Vach\",\n\t\t\t\thomepage: \"http://www.zwave.eu\",\n\t\t\t\tactive: true\n\t\t\t}],\n\t\t\tnow = new Date();\n\n\t\t\ttry {\n\n\t\t\t\tif (defaultConfigExists && defaultConfigExists.type !== 'dir' && defaultConfigExists.size > 0) {\n\t\t\t\t\tdefaultConfig = fs.loadJSON('defaultConfigs/config.json');\n\t\t\t\t}\n\n\t\t\t\tif (!!defaultConfig && !_.isEmpty(defaultConfig)) {\n\n\t\t\t\t\tvar ts = now.getFullYear() + \"-\";\n\t\t\t\t\tts += (\"0\" + (now.getMonth() + 1)).slice(-2) + \"-\";\n\t\t\t\t\tts += (\"0\" + now.getDate()).slice(-2) + \"-\";\n\t\t\t\t\tts += (\"0\" + now.getHours()).slice(-2) + \"-\";\n\t\t\t\t\tts += (\"0\" + now.getMinutes()).slice(-2);\n\n\t\t\t\t\tconsole.log('Backup config ...');\n\t\t\t\t\t// make backup of current config.json\n\t\t\t\t\tsaveObject('backupConfig' + ts, loadObject('config.json'), true);\n\n\t\t\t\t\t// remove all active instances of moduleId\n\t\t\t\t\tthis.controller.instances.forEach(function(instance) {\n\t\t\t\t\t\tif (instance.moduleId !== 'ZWave') {\n\t\t\t\t\t\t\tself.controller.deleteInstance(instance.id);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (typeof zway !== \"undefined\" && zway) {\n\t\t\t\t\t\t// reset z-way controller\n\t\t\t\t\t\tconsole.log('Reset Controller ...');\n\t\t\t\t\t\tvar d = Date.now() + 15000; // wait not more than 15 sec\n\n\t\t\t\t\t\tzway.controller.SetDefault();\n\n\t\t\t\t\t\twhile (Date.now() < d && zway.controller.data.controllerState.value === 20) {\n\t\t\t\t\t\t\tprocessPendingCallbacks();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// remove instances of ZWave at least\n\t\t\t\t\t\t// filter for instances of ZWave\n\t\t\t\t\t\tzwInstances = this.controller.instances.filter(function(instance) {\n\t\t\t\t\t\t\treturn instance.moduleId === 'ZWave';\n\t\t\t\t\t\t}).map(function(instance) {\n\t\t\t\t\t\t\treturn instance.id;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// remove instance of ZWave\n\t\t\t\t\t\tif (zwInstances.length > 0) {\n\t\t\t\t\t\t\tzwInstances.forEach(function(instanceId) {\n\t\t\t\t\t\t\t\tconsole.log('Remove ZWave instance: ' + instanceId);\n\t\t\t\t\t\t\t\tself.controller.deleteInstance(instanceId);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconsole.log('Remove and unload userModules apps ...');\n\t\t\t\t\t// unload and remove modules\n\t\t\t\t\tObject.keys(this.controller.modules).forEach(function(className) {\n\t\t\t\t\t\tvar meta = self.controller.modules[className],\n\t\t\t\t\t\t\tunload = '',\n\t\t\t\t\t\t\tlocPath = meta.location.split('/'),\n\t\t\t\t\t\t\tsuccess = false;\n\n\t\t\t\t\t\tif (locPath[0] === 'userModules') {\n\t\t\t\t\t\t\tconsole.log(className + ' remove it ...');\n\n\t\t\t\t\t\t\tsuccess = self.controller.uninstallModule(className);\n\n\t\t\t\t\t\t\tif (success) {\n\t\t\t\t\t\t\t\tconsole.log(className + ' has been successfully removed.');\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tconsole.log('Cannot remove app: ' + className);\n\t\t\t\t\t\t\t\tself.addNotification(\"warning\", langFile.zaap_err_uninstall_mod + ' ' + className, \"core\", \"AutomationController\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t});\n\n\t\t\t\t\t// remove skins\n\t\t\t\t\t_.forEach(this.controller.skins, function(skin) {\n\t\t\t\t\t\tif (skin.name !== 'default') {\n\t\t\t\t\t\t\tself.controller.uninstallSkin(skin.name);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t// stop the controller\n\t\t\t\t\tthis.controller.stop();\n\n\t\t\t\t\t// clean up storage\n\t\t\t\t\tfor (var ind in storageContentList) {\n\t\t\t\t\t\tif (storageContentList[ind].indexOf('backupConfig') < 0 && !!storageContentList[ind]) {\n\t\t\t\t\t\t\tsaveObject(storageContentList[ind], null, true);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// clean up storageContent\n\t\t\t\t\tif (__storageContent.length > 0) {\n\t\t\t\t\t\t__saveObject(\"__storageContent\", []);\n\t\t\t\t\t\t__storageContent = [];\n\t\t\t\t\t}\n\n\t\t\t\t\t// set back to default config\n\t\t\t\t\tsaveObject('config.json', defaultConfig, true);\n\t\t\t\t\tsaveObject('userSkins.json', defaultSkins, true);\n\n\t\t\t\t\t// start controller with reload flag to apply config.json\n\t\t\t\t\tthis.controller.start(true);\n\n\t\t\t\t\treply.code = 200;\n\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tself.doLogout();\n\t\t\t\t\t}, 3000);\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = 'No default configuration file found.';\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\treply.error = 'Something went wrong. Error: ' + e.toString();\n\t\t\t}\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetSkins: function() {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tif (this.controller.skins) {\n\t\t\treply.data = this.controller.skins;\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_skins';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetSkin: function(skinName) {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tif (this.controller.skins) {\n\t\t\tindex = _.findIndex(this.controller.skins, function(skin) {\n\t\t\t\treturn skin.name === skinName;\n\t\t\t});\n\n\t\t\tif (index > -1) {\n\t\t\t\treply.data = this.controller.skins[index];\n\t\t\t\treply.code = 200;\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'skin_not_exists';\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_skins';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetActiveSkin: function() {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tif (this.controller.skins) {\n\t\t\tindex = _.findIndex(this.controller.skins, function(skin) {\n\t\t\t\treturn skin.active === true;\n\t\t\t});\n\n\t\t\tif (index > -1) {\n\t\t\t\treply.data = this.controller.skins[index];\n\t\t\t\treply.code = 200;\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'skin_not_exists';\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_skins';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tactivateOrDeactivateSkin: function(skinName) {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\tskin = null;\n\n\t\tskin = this.controller.setSkinState(skinName, reqObj);\n\n\t\ttry {\n\t\t\tif (!!skin) {\n\t\t\t\treply.data = skin;\n\t\t\t\treply.code = 200;\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'skin_not_exists';\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.error = 'failed_to_load_skins';\n\t\t\treply.message = e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\taddOrUpdateSkin: function(skinName) {\n\t\tvar reply = {\n\t\t\t\terror: 'skin_failed_to_install',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\tresult = \"\",\n\t\t\tskName = skinName || reqObj.name;\n\n\t\tif (skName !== 'default') {\n\n\t\t\tindex = _.findIndex(this.controller.skins, function(skin) {\n\t\t\t\treturn skin.name === skName;\n\t\t\t});\n\n\t\t\tif ((index < 0 && this.req.method === 'POST') ||\n\t\t\t\t(index > -1 && this.req.method === 'PUT' && skinName)) {\n\n\t\t\t\t// download and install the skin\n\t\t\t\tresult = this.controller.installSkin(reqObj, skName, index);\n\n\t\t\t\tif (result === \"done\") {\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.data = this.req.method === 'POST' ? \"skin_installation_successful\" : \"skin_update_successful\"; // send language key as response\n\t\t\t\t\treply.error = null;\n\t\t\t\t}\n\n\t\t\t} else if (this.req.method === 'POST' && !skinName) {\n\t\t\t\treply.code = 409;\n\t\t\t\treply.error = 'skin_from_url_already_exists';\n\t\t\t} else if (this.req.method === 'PUT' && skinName) {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'skin_not_exists';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 403;\n\t\t\treply.error = 'No Permission';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tdeleteSkin: function(skinName) {\n\t\tvar reply = {\n\t\t\t\terror: 'skin_failed_to_delete',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tuninstall = false;\n\n\t\tif (skinName !== 'default') {\n\t\t\tindex = _.findIndex(this.controller.skins, function(skin) {\n\t\t\t\treturn skin.name === skinName;\n\t\t\t});\n\n\t\t\tif (index > -1) {\n\n\t\t\t\tuninstall = this.controller.uninstallSkin(skinName);\n\n\t\t\t\tif (uninstall) {\n\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.data = \"skin_delete_successful\"; // send language key as response\n\t\t\t\t\treply.error = null;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'skin_not_exists';\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 403;\n\t\t\treply.error = 'No Permission';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tsetDefaultSkin: function() {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t};\n\n\t\ttry {\n\n\t\t\t// deactivate all skins and set default skin to active: true\n\t\t\t_.forEach(this.controller.skins, function(skin) {\n\t\t\t\tskin.active = skin.name === 'default' ? true : false;\n\t\t\t})\n\n\t\t\tsaveObject(\"userSkins.json\", this.controller.skins, true);\n\n\t\t\treply.data = \"Skin reset was successfull. You'll be logged out in 3, 2, 1 ...\";\n\t\t\treply.code = 200;\n\t\t\t// do logout\n\t\t\tsetTimeout(function() {\n\t\t\t\tself.doLogout();\n\t\t\t}, 3000);\n\t\t} catch (e) {\n\t\t\treply.error = \"Something went wrong.\";\n\t\t\treply.message = e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetSkinTokens: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\ttokenObj = loadObject('skinTokens.json');\n\n\t\tif (tokenObj === null) {\n\n\t\t\ttokenObj = {\n\t\t\t\tskinTokens: []\n\t\t\t};\n\n\t\t\tsaveObject('skinTokens.json', tokenObj, true);\n\t\t}\n\n\t\tif (!!tokenObj) {\n\t\t\treply.data = tokenObj;\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_skin_tokens';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tstoreSkinToken: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\ttokenObj = loadObject('skinTokens.json');\n\n\t\tif (reqObj && reqObj.token) {\n\n\t\t\tif (tokenObj === null) {\n\n\t\t\t\ttokenObj = {\n\t\t\t\t\tskinTokens: [reqObj.token]\n\t\t\t\t}\n\n\t\t\t\t// save tokens\n\t\t\t\tsaveObject('skinTokens.json', tokenObj, true);\n\n\t\t\t\treply.data = tokenObj;\n\t\t\t\treply.code = 201;\n\n\t\t\t} else if (!!tokenObj && tokenObj.skinTokens) {\n\n\t\t\t\tif (tokenObj.skinTokens.indexOf(reqObj.token) < 0) {\n\t\t\t\t\t// add new token id\n\t\t\t\t\ttokenObj.skinTokens.push(reqObj.token);\n\n\t\t\t\t\t// save tokens\n\t\t\t\t\tsaveObject('skinTokens.json', tokenObj, true);\n\n\t\t\t\t\treply.data = tokenObj;\n\t\t\t\t\treply.code = 201;\n\t\t\t\t} else {\n\t\t\t\t\treply.code = 409;\n\t\t\t\t\treply.error = 'skin_token_not_unique';\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_skin_tokens';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tdeleteSkinToken: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\ttokenObj = loadObject('skinTokens.json');\n\n\t\tif (reqObj && reqObj.token && !!tokenObj && tokenObj.skinTokens) {\n\t\t\tif (tokenObj.skinTokens.indexOf(reqObj.token) > -1) {\n\t\t\t\t// add new token id\n\t\t\t\ttokenObj.skinTokens = _.filter(tokenObj.skinTokens, function(token) {\n\t\t\t\t\treturn token !== reqObj.token;\n\t\t\t\t});\n\n\t\t\t\t// save tokens\n\t\t\t\tsaveObject('skinTokens.json', tokenObj, true);\n\n\t\t\t\treply.data = tokenObj;\n\t\t\t\treply.code = 200;\n\t\t\t} else {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'not_existing_skin_token';\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_skin_tokens';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetIcons: function() {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tif (this.controller.icons) {\n\t\t\treply.data = this.controller.icons;\n\t\t\treply.code = 200;\n\t\t} else {\n\t\t\treply.error = 'failed_to_load_icons';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tuploadIcon: function() {\n\t\tvar reply = {\n\t\t\terror: 'icon_failed_to_install',\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tfor (prop in this.req.body) {\n\t\t\tif (this.req.body[prop]['content']) {\n\n\t\t\t\tfile = this.req.body[prop];\n\t\t\t}\n\t\t}\n\n\t\tfunction utf8Decode(bytes) {\n\t\t\tvar chars = [];\n\n\t\t\tfor (var i = 0; i < bytes.length; i++) {\n\t\t\t\tchars[i] = bytes.charCodeAt(i);\n\t\t\t}\n\n\t\t\treturn chars;\n\t\t}\n\n\t\tfunction Uint8ToBase64(uint8) {\n\t\t\tvar i,\n\t\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\t\toutput = \"\",\n\t\t\t\ttemp, length;\n\n\t\t\tvar lookup = [\n\t\t\t\t'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',\n\t\t\t\t'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',\n\t\t\t\t'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',\n\t\t\t\t'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',\n\t\t\t\t'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',\n\t\t\t\t'o', 'p', 'q', 'r', 's', 't', 'u', 'v',\n\t\t\t\t'w', 'x', 'y', 'z', '0', '1', '2', '3',\n\t\t\t\t'4', '5', '6', '7', '8', '9', '+', '/'\n\t\t\t];\n\n\t\t\tfunction tripletToBase64(num) {\n\t\t\t\treturn lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F];\n\t\t\t};\n\n\t\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]);\n\t\t\t\toutput += tripletToBase64(temp);\n\t\t\t}\n\n\t\t\t// this prevents an ERR_INVALID_URL in Chrome (Firefox okay)\n\t\t\tswitch (output.length % 4) {\n\t\t\t\tcase 1:\n\t\t\t\t\toutput += '=';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\toutput += '==';\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn output;\n\t\t}\n\t\tvar data,\n\t\t\tbytes = new Uint8Array(utf8Decode(file.content)),\n\t\t\tre = /(?:\\.([^.]+))?$/;\n\t\text = re.exec(file.name)[1];\n\n\t\tif (ext === 'gz') {\n\t\t\tvar gunzip = new Zlib.Gunzip(bytes);\n\t\t\tdata = gunzip.decompress();\n\t\t} else {\n\t\t\tdata = bytes;\n\t\t}\n\n\t\tfile.content = Uint8ToBase64(data);\n\n\t\tresult = this.controller.installIcon('local', file, 'custom', 'icon');\n\n\t\tif (result.message === \"done\") {\n\n\t\t\treply.code = 200;\n\t\t\treply.data = result.files;\n\t\t\treply.error = null;\n\t\t}\n\n\t\treturn reply\n\t},\n\taddOrUpdateIcons: function(iconName) {\n\t\tvar reply = {\n\t\t\t\terror: 'icon_failed_to_install',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\treqObj = parseToObject(this.req.body),\n\t\t\tresult = \"\",\n\t\t\ticName = iconName || reqObj.name,\n\t\t\tid = reqObj.id;\n\n\t\tindex = _.findIndex(this.controller.icons, function(icon) {\n\t\t\treturn icon.source === icName + \"_\" + id;\n\t\t});\n\n\t\tif (index === -1) {\n\n\t\t\t// download and install the icon\n\t\t\tresult = this.controller.installIcon('remote', reqObj, icName, reqObj.id);\n\n\t\t\tif (result.message === \"done\") {\n\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = result.files;\n\t\t\t\treply.error = null;\n\t\t\t}\n\t\t} else {\n\t\t\treply.code = 409;\n\t\t\treply.error = 'icon_from_url_already_exists';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tdeleteIcons: function(iconName) {\n\t\tvar reply = {\n\t\t\t\terror: 'icon_failed_to_delete',\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tuninstall = false;\n\n\t\tvar reqObj = typeof this.req.body === 'string' ? JSON.parse(this.req.body) : this.req.body;\n\n\t\tthis.controller.deleteCustomicon(iconName);\n\n\t\tuninstall = this.controller.uninstallIcon(iconName);\n\n\t\tif (uninstall) {\n\t\t\treply.code = 200;\n\t\t\treply.data = \"icon_delete_successful\";\n\t\t\treply.error = null;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetTime: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\ttz = \"\",\n\t\t\tnow = new Date();\n\n\t\ttry {\n\t\t\tvar sys = system(\"sh automation/lib/timezone.sh getTZ\");\n\t\t\tsys.forEach(function(i) {\n\t\t\t\tif (typeof i === 'string') {\n\t\t\t\t\ttz = i.replace(/\\n/g, '');\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (e) {}\n\n\t\tif (now) {\n\t\t\treply.code = 200;\n\t\t\treply.data = {\n\t\t\t\tlocalTimeUT: Math.round((now.getTime() + (now.getTimezoneOffset() * -60000)) / 1000), // generate timestamp with correct timezone offset\n\t\t\t\tlocalTimeString: now.toLocaleString(),\n\t\t\t\tlocalTimeZoneOffset: now.getTimezoneOffset() / 60,\n\t\t\t\tlocalTimeZone: tz,\n\t\t\t\tlocalGMT: now.toString().match(/([-\\+][0-9]+)\\s/)[1]\n\t\t\t};\n\t\t} else {\n\t\t\treply.error = 'Cannot get current date and time.';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tsetTimezone: function() {\n\t\tvar self = this,\n\t\t\tlangfile = this.controller.loadMainLang();\n\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tdata = {\n\t\t\t\t\"act\": \"set\",\n\t\t\t\t\"tz\": \"\"\n\t\t\t};\n\n\t\treqObj = parseToObject(this.req.body);\n\n\t\tdata.tz = reqObj.timeZone;\n\n\t\ttry {\n\t\t\tif (system(\"sh automation/lib/timezone.sh setTZ \" + reqObj.timeZone)[0] !== 0) {\n\t\t\t\tthrow \"Failed to set timezone\";\n\t\t\t} else {\n\t\t\t\treply.code = 200;\n\n\t\t\t\t// reboot after 5 seconds\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconsole.log(\"Rebooting system ...\");\n\t\t\t\t\t\tsystem(\"reboot\"); // reboot the box\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_reboot, \"core\", \"SetTimezone\");\n\t\t\t\t\t}\n\t\t\t\t}, 5000);\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.error = res.statusText + \"; \" + e.toString();\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetRemoteId: function() {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t};\n\n\t\ttry {\n\t\t\treply.code = 200;\n\t\t\treply.data = {\n\t\t\t\tremote_id: self.controller.getRemoteId()\n\t\t\t};\n\n\t\t} catch (e) {\n\t\t\tif (e.name === \"service-not-available\") {\n\t\t\t\treply.code = 503;\n\t\t\t\treply.error = e.message;\n\t\t\t} else {\n\t\t\t\treply.code = 500;\n\t\t\t\treply.error = e.message;\n\t\t\t}\n\t\t}\n\t\treturn reply;\n\t},\n\tgetIPAddress: function() {\n\t\tvar self = this,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tip = self.controller.getIPAddress();\n\n\t\tif (ip) {\n\t\t\treply.code = 200;\n\t\t\treply.data = {\n\t\t\t\tip_address: ip\n\t\t\t};\n\t\t} else {\n\t\t\treply.code = 500;\n\t\t\treply.error = \"syscommad-not-set\";\n\t\t}\n\t\treturn reply;\n\t},\n\t// set a timout for accessing firmware update tab of 8084\n\tsetWebifAccessTimout: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tallowAcc = 0,\n\t\t\ttimeout = 900; // in s ~ 15 min\n\n\t\tallowAcc = this.req.query.hasOwnProperty(\"allow_access\") ? parseInt(this.req.query.allow_access, 10) : 0;\n\t\ttimeout = this.req.query.hasOwnProperty(\"timeout\") ? parseInt(this.req.query.timeout, 10) : timeout;\n\n\t\tif (allowAcc === 1 && timeout > 0 && timeout <= 1200) {\n\t\t\tsaveObject('8084AccessTimeout', timeout, true);\n\t\t\treply.code = 200;\n\t\t\treply.data = {\n\t\t\t\ttimeout: timeout\n\t\t\t};\n\t\t} else if (allowAcc === 0) {\n\t\t\tsaveObject('8084AccessTimeout', null, true);\n\t\t\treply.code = 200;\n\t\t\treply.data = {\n\t\t\t\ttimeout: null\n\t\t\t};\n\t\t} else {\n\t\t\treply.code = 400;\n\t\t\treply.error = 'Invalid Request';\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetFirstLoginInfo: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: {},\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tdefaultProfile = [],\n\t\t\tsetLogin = {};\n\t\ttry {\n\t\t\tdefaultProfile = _.filter(this.controller.profiles, function(profile) {\n\t\t\t\treturn profile.login === 'admin' && profile.password === 'admin';\n\t\t\t});\n\n\t\t\tif ((!this.controller.config.first_start_up && defaultProfile.length > 0) || (defaultProfile.length > 0 && (typeof this.controller.config.firstaccess === 'undefined' || this.controller.config.firstaccess)) || (defaultProfile.length > 0 && !this.controller.config.firstaccess)) {\n\t\t\t\tsetLogin = this.setLogin(defaultProfile[0], this.req);\n\t\t\t\treply.headers = setLogin.headers; // set '/' Z-Way-Session root cookie\n\t\t\t\treply.data.defaultProfile = setLogin.data; // set login data of default profile\n\t\t\t\treply.data.firstaccess = true;\n\t\t\t\treply.data.defaultProfile.showWelcome = true;\n\t\t\t} else {\n\t\t\t\treply.data.firstaccess = false;\n\t\t\t}\n\t\t\treply.data.uuid = this.controller.getUUID();\n\t\t\treply.data.serial = this.controller.getSerial();\n\t\t\treply.data.mac = this.controller.getMACAddress();\n\t\t\treply.data.remote_id = this.controller.getRemoteId();\n\t\t\treply.data.ip_address = this.controller.getIPAddress();\n\t\t\treply.code = 200;\n\t\t} catch (e) {\n\t\t\treply.data = null;\n\t\t\treply.error = e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetSystemInfo: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tdata: {},\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tversionArr = [];\n\n\t\ttry {\n\t\t\tversionArr = zway.controller.data.softwareRevisionVersion.value.substring(1).split('-');\n\t\t\tversion = versionArr[0] ? versionArr[0] : null;\n\t\t\tmajurity = versionArr[1] ? versionArr[1] : null;\n\n\t\t\treply.data = {\n\t\t\t\tfirst_start_up: this.controller.config.first_start_up,\n\t\t\t\tcount_of_reconnects: this.controller.config.count_of_reconnects,\n\t\t\t\tcurrent_firmware: version,\n\t\t\t\tcurrent_firmware_majurity: majurity,\n\t\t\t\tremote_id: this.controller.getRemoteId(),\n\t\t\t\tuuid: this.controller.getUUID(),\n\t\t\t\tserial: this.controller.getSerial(),\n\t\t\t\tmac: this.controller.getMACAddress(),\n\t\t\t\tfirstaccess: this.controller.config.hasOwnProperty('firstaccess') ? this.controller.config.firstaccess : true\n\t\t\t};\n\n\t\t\treply.code = 200;\n\t\t} catch (e) {\n\t\t\treply.data = null;\n\t\t\treply.error = e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\trebootBox: function() {\n\t\tvar self = this,\n\t\t\tlangfile = this.controller.loadMainLang();\n\t\treply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\t// if reboot has flag firstaccess=true add showWelcome to controller config\n\t\tif (this.req.query.hasOwnProperty('firstaccess') && this.req.query.firstaccess) {\n\t\t\tthis.controller.config.showWelcome = true;\n\t\t\tthis.controller.saveConfig(true);\n\t\t}\n\n\t\t// reboot after 5 seconds\n\t\tsetTimeout(function() {\n\t\t\ttry {\n\t\t\t\tconsole.log(\"Rebooting system ...\");\n\t\t\t\tsystem(\"reboot\"); // reboot the box\n\t\t\t} catch (e) {\n\t\t\t\tself.controller.addNotification(\"error\", langfile.zaap_err_reboot, \"core\", \"RebootBox\");\n\t\t\t}\n\t\t}, 5000);\n\n\t\treply.code = 200;\n\t\treply.data = \"System is rebooting ...\";\n\n\t\treturn reply;\n\t},\n\tgetWiFiCliSettings: function() {\n\t\t// for Z-Wave.Me Hub\n\t\ttry {\n\t\t\tvar list = system(\"/lib/wifi-helper.sh LIST\")[1].split(\"\\n\");\n\t\t\tlist.pop(); list.pop(); list.shift(); list.shift(); // remove header and footer\n\n\t\t\tvar saved = system(\"/lib/wifi-helper.sh GETSAVEDCONNECTION\")[1].split(\"\\n\"),\n\t\t\t    savedEssid = saved[0].trim(), // LIST returns with spaces, so we trim in current too for uniform comparison\n\t\t\t    savedSecurity = saved[1],\n\t\t\t    savedEncryption = saved[2],\n\t\t\t    savedChannel = parseInt(saved[3]),\n\t\t\t    current = system(\"/lib/wifi-helper.sh GETCURRENTCONNECTION\")[1].split(\"\\n\"),\n\t\t\t    currentEssid = current[0].trim(), // LIST returns with spaces, so we trim in current too for uniform comparison\n\t\t\t    currentChannel = parseInt(current[1]);\n\t\t\t\n\t\t\t// sprintf(msg+strlen(msg),\"%-4s%-33s%-20s%-23s%-9s%-7s%-7s%-3s\\n\",\n\t\t\t//  \"Ch\", \"SSID\", \"BSSID\", \"Security\", \"Siganl(%)\", \"W-Mode\", \" ExtCH\",\" NT\");\n\t\t\t// sprintf(msg+strlen(msg)-1,\"%-4s%-5s\\n\", \" WPS\", \" DPID\");\n\t\t\t\n\t\t\tvar ret = list.map(function(l) {\n\t\t\t\tvar m = l.match(/(.{4})(.{33})(.{20})(.{23})(.{9})(.{7})/);\n\t\t\t\tvar sec = m[4].trim().split(\"/\");\n\t\t\t\treturn {\n\t\t\t\t\tsaved: savedEssid === m[2].trim() && savedSecurity === sec[0] && savedEncryption === sec[1] && savedChannel === parseInt(m[1]),\n\t\t\t\t\tcurrent: false, // to be filled later\n\t\t\t\t\tchannel: parseInt(m[1]),\n\t\t\t\t\tessid: m[2].trim(),\n\t\t\t\t\tsecurity: sec[0],\n\t\t\t\t\tencryption: sec[1],\n\t\t\t\t\tsignal: parseInt(m[5])\n\t\t\t\t};\n\t\t\t\t// TODO!!! Parse WPA1PSKWPA2PSK and TKIPAES\n\t\t\t}).filter(function(entry) {\n\t\t\t\treturn entry.essid; // skip entries with empty ESSID (can be as a result of error on weak signal)\n\t\t\t});\n\t\t\t\n\t\t\tvar savedEntry = ret.filter(function(entry) {\n\t\t\t\treturn entry.saved;\n\t\t\t})[0];\n\n\t\t\tif (savedEntry) {\n\t\t\t\tsavedEntry.current = savedEntry.saved && currentEssid === savedEntry.essid && currentChannel === savedEntry.channel;\n\t\t\t} else {\n\t\t\t\tif (savedEssid && savedSecurity && savedEncryption && savedChannel) {\n\t\t\t\t\tret.push({\n\t\t\t\t\t\tsaved: true,\n\t\t\t\t\t\tcurrent: false,\n\t\t\t\t\t\tchannel: savedChannel,\n\t\t\t\t\t\tessid: savedEssid,\n\t\t\t\t\t\tsecurity: savedSecurity,\n\t\t\t\t\t\tencryption: savedEncryption,\n\t\t\t\t\t\tsignal: 0\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tdata: ret,\n\t\t\t\tcode: 200\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconsole.log(e.toString());\n\t\t\treturn {\n\t\t\t\terror: 'Internal Server Error. Can not get the list of WiFi networks: ' + e.toString(),\n\t\t\t\tcode: 500\n\t\t\t}\n\t\t}\n\t},\n\tsetWiFiCliSettings: function() {\n\t\t// for Z-Wave.Me Hub\n\t\ttry {\n\t\t\tvar reqObj = parseToObject(this.req.body),\n\t\t\t    essid = reqObj.essid,\n\t\t\t    security = reqObj.security,\n\t\t\t    encryption = reqObj.encryption,\n\t\t\t    password = reqObj.password;\n\t\t\t\n\t\t\tif (essid && (!security || !encryption || !password)) throw \"Missing mandatory options: essid, security, encryption, password\";\n\t\t\t\n\t\t\tif (essid) {\n\t\t\t\tsystem('/lib/wifi-helper.sh \"' + essid + '\" \"' + security + '\" \"' + encryption + '\" \"' + password + '\"');\n\t\t\t} else {\n\t\t\t\tsystem('/lib/wifi-helper.sh DISCONNECT');\n\t\t\t}\n\t\t\t\n\t\t\treturn {\n\t\t\t\tdata: {\n\t\t\t\t},\n\t\t\t\tcode: 200\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconsole.log(e.toString());\n\t\t\treturn {\n\t\t\t\terror: 'Internal Server Error. Can not set WiFi network: ' + e.toString(),\n\t\t\t\tcode: 500\n\t\t\t}\n\t\t}\n\t},\n\tgetConnectionType: function() {\n\t\t// for Z-Wave.Me Hub\n\t\ttry {\n                    var currentConnection = system(\"route | grep default | awk '$5 == 0 { if ($8 == \\\"eth0.1\\\") print \\\"ethernet\\\"; else if ($8 == \\\"apcli0\\\") print \\\"wifi\\\"; else if ($8 == \\\"eth1\\\") print \\\"mobile\\\"; else print $8 }'\")[1].trim();\n                    var availableConnections = system(\"route | grep default | awk '$5 != 0 { if ($8 == \\\"eth0.1\\\") print \\\"ethernet\\\"; else if ($8 == \\\"apcli0\\\") print \\\"wifi\\\"; else if ($8 == \\\"eth1\\\") print \\\"mobile\\\"; else print $8 }'\")[1].split(\"\\n\").filter(function(x) { return x != \"\" });\n                    var possibleConnections = [ \"ethernet\", \"wifi\", \"mobile\" ]; // possible values\n                    return {\n                            data: {\n                                    currentConnection: currentConnection,\n                                    availableConnections: availableConnections,\n                                    possibleConnections: possibleConnections\n                            },\n                            code: 200\n                    };\n\t\t} catch (e) {\n\t\t\tconsole.log(e.toString());\n\t\t\treturn {\n\t\t\t\terror: 'Internal Server Error. Can not check current connection type: ' + e.toString(),\n\t\t\t\tcode: 500\n\t\t\t}\n\t\t}\n\t},\n\tsetWifiSettings: function() {\n\t\tvar reply = {\n\t\t\t\terror: \"Wifi setup failed!\",\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tretPp = [],\n\t\t\tretSsid = [],\n\t\t\tretR = [];\n\n\t\tif (fs.stat('lib/configAP.sh')) {\n\t\t\ttry {\n\t\t\t\treqObj = parseToObject(this.req.body);\n\n\t\t\t\tif (reqObj.password !== '') {\n\t\t\t\t\tif (reqObj.password.length >= 8 && reqObj.password.length <= 63) {\n\t\t\t\t\t\tretPp = system(\"sh automation/lib/configAP.sh setPp \" + reqObj.password);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.error = \"Password must between 8 and 63 characters long.\";\n\t\t\t\t\t\treturn reply;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tretPp[1] = \"\";\n\t\t\t\t}\n\n\t\t\t\tif (reqObj.ssid !== '') {\n\t\t\t\t\tretSsid = system(\"sh automation/lib/configAP.sh setSsid \" + reqObj.ssid);\n\t\t\t\t} else {\n\t\t\t\t\tretSsid[1] = \"\";\n\t\t\t\t}\n\n\t\t\t\tif ((retSsid[1].indexOf(\"successfull\") !== -1 || retPp[1].indexOf(\"successfull\") !== -1) || (retSsid[1].indexOf(\"successfull\") !== -1 && retPp[1].indexOf(\"successfull\") !== -1)) {\n\t\t\t\t\tretR = system(\"sh automation/lib/configAP.sh reload\");\n\t\t\t\t\tif (retR[1].indexOf(\"Done\") !== -1) {\n\t\t\t\t\t\treply.error = null;\n\t\t\t\t\t\treply.data = \"OK\";\n\t\t\t\t\t\treply.code = 200;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(e.toString());\n\t\t\t\treply.error = 'Internal Server Error. ' + e.toString();\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'Not Implemented';\n\t\t\treply.code = 501;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tgetWifiSettings: function() {\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\t\tif (fs.stat('lib/configAP.sh')) {\n\t\t\ttry {\n\n\t\t\t\tvar retSsid = system(\"sh automation/lib/configAP.sh getSsid\");\n\n\t\t\t\tvar ssid = retSsid[1].replace(' 0', '').replace(/\\n/g, '');\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = {\n\t\t\t\t\t\"ssid\": ssid\n\t\t\t\t};\n\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(e.toString());\n\t\t\t\treply.error = 'Internal Server Error. ' + e.toString();\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'Not Implemented';\n\t\t\treply.code = 501;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tconfigNtp: function(action) {\n\t\tvar reply = {\n\t\t\t\terror: \"Internal Server Error\",\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500\n\t\t\t},\n\t\t\tactions = [\"status\", \"stop\", \"start\", \"restart\", \"disable\", \"enable\", \"reconfigure\", \"setDateTime\"],\n\t\t\tdt_regex = /[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]/;\n\n\t\tif (fs.stat('lib/ntp.sh')) {\n\t\t\ttry {\n\t\t\t\treqObj = parseToObject(this.req.query);\n\n\t\t\t\tif (actions.indexOf(action) > -1 || (action == 'setDateTime' && reqObj.dateTime && dt_regex.exec(reqObj.dateTime))) {\n\n\t\t\t\t\tres = system(\"./automation/lib/ntp.sh \" + action + (action == 'setDateTime' ? \" '\" + reqObj.dateTime + \"'\" : \"\"));\n\n\t\t\t\t\tif (action === 'status' && res[1]) {\n\t\t\t\t\t\treply.data = JSON.parse(res[1]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\treply.data = res[1] ? res[1] : res;\n\t\t\t\t\t}\n\n\t\t\t\t\treply.code = 200;\n\t\t\t\t\treply.error = null;\n\n\t\t\t\t} else {\n\t\t\t\t\treply.error = 'Bad Request. Allowed are: ' + actions.toString() + '?dateTime=yyyy-mm-dd hh:mm';\n\t\t\t\t\treply.code = 400;\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(e.toString());\n\t\t\t\treply.error = 'Internal Server Error. ' + e.toString();\n\t\t\t}\n\t\t} else {\n\t\t\treply.error = 'Not Implemented';\n\t\t\treply.code = 501;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tzwaveDeviceInfoGet: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tcode: 500,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\tl = ['en', 'de'], //this.controller.availableLang\n\t\t\tdevInfo = {},\n\t\t\treqObj = !this.req.query ? undefined : parseToObject(this.req.query);\n\n\t\ttry {\n\n\t\t\tdevID = reqObj && reqObj.id ? reqObj.id : null;\n\t\t\tlanguage = reqObj && reqObj.lang && l.indexOf(reqObj.lang) > -1 ? reqObj.lang : 'en';\n\n\t\t\tif (reqObj && reqObj.lang && l.indexOf(reqObj.lang) === -1) {\n\t\t\t\treply.message = 'Language not found. English is used instead.';\n\t\t\t}\n\n\t\t\tdevInfo = loadObject(language + '.devices.json'); //this.controller.defaultLang\n\n\n\t\t\tif (devInfo === null) {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'No list of Z-Wave devices found. Please try to download them first.';\n\t\t\t} else {\n\t\t\t\treply.data = devInfo;\n\t\t\t\treply.code = 200;\n\n\t\t\t\tif (!!devID) {\n\t\t\t\t\treply.data = _.find(devInfo.zwave_devices, function(dev) {\n\t\t\t\t\t\treturn dev['Product_Code'] === devID;\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!reply.data) {\n\t\t\t\t\t\treply.code = 404;\n\t\t\t\t\t\treply.error = 'No Z-Wave device with ' + devID + ' found.';\n\t\t\t\t\t\treply.data = null;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.error = 'Something went wrong:' + e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tzwaveDeviceInfoUpdate: function() {\n\t\tvar self = this,\n\t\t\tresult = [],\n\t\t\tl = ['en', 'de'], //this.controller.availableLang,\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tcode: 500,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\tdelay = Date.now() + 10000; // wait not more than 10 seconds\n\n\t\ttry {\n\t\t\t// update postfix JSON\n\t\t\tl.forEach(function(lang) {\n\t\t\t\tvar obj = {},\n\t\t\t\t\tlist = {\n\t\t\t\t\t\tupdateTime: '',\n\t\t\t\t\t\tzwave_devices: []\n\t\t\t\t\t};\n\n\t\t\t\tobj[lang] = false;\n\n\t\t\t\thttp.request({\n\t\t\t\t\turl: \"http://manuals-backend.z-wave.info/make.php?lang=\" + lang + \"&mode=ui_devices\",\n\t\t\t\t\tasync: true,\n\t\t\t\t\tsuccess: function(res) {\n\t\t\t\t\t\tif (res.data) {\n\t\t\t\t\t\t\tdata = parseToObject(res.data);\n\t\t\t\t\t\t\tlist.updateTime = Date.now();\n\n\t\t\t\t\t\t\tfor (index in data) {\n\t\t\t\t\t\t\t\tlist.zwave_devices.push(data[index]);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tsaveObject(lang + '.devices.json', list, true);\n\t\t\t\t\t\t\tobj[lang] = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tresult.push(obj);\n\t\t\t\t\t},\n\t\t\t\t\terror: function() {\n\t\t\t\t\t\tself.controller.addNotification('error', 'Z-Wave device list for lang:' + lang + ' not found.', 'core', 'ZAutomationAPI');\n\t\t\t\t\t\tresult.push(obj);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\n\t\t\twhile (result.length < l.length && Date.now() < delay) {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result) {\n\t\t\t\treply.code = 200;\n\t\t\t\treply.data = result;\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\tthis.controller.addNotification('error', 'Error has occured during updating the Z-Wave devices list', 'core', 'ZAutomationAPI');\n\t\t\treply.error = 'Something went wrong:' + e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tzwaveVendorsInfoGet: function() {\n\t\tvar reply = {\n\t\t\t\terror: null,\n\t\t\t\tcode: 500,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\tdevInfo = {},\n\t\t\treqObj = !this.req.query ? undefined : parseToObject(this.req.query);\n\n\t\ttry {\n\n\t\t\tvendorID = reqObj && reqObj.id ? reqObj.id : null;\n\n\t\t\tdevInfo = loadObject('zwave_vendors.json');\n\n\t\t\tif (devInfo === null) {\n\t\t\t\treply.code = 404;\n\t\t\t\treply.error = 'No list of Z-Wave vendors found. Please try to download them first.';\n\t\t\t} else {\n\t\t\t\treply.data = devInfo;\n\t\t\t\treply.code = 200;\n\n\t\t\t\tif (devInfo.zwave_vendors[vendorID]) {\n\t\t\t\t\treply.data = devInfo.zwave_vendors[vendorID];\n\t\t\t\t} else if (reqObj.id) {\n\t\t\t\t\treply.code = 404;\n\t\t\t\t\treply.error = 'No Z-Wave vendor with id \"' + vendorID + '\" found.';\n\t\t\t\t\treply.data = null;\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.error = 'Something went wrong:' + e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tzwaveVendorsInfoUpdate: function() {\n\t\tvar self = this,\n\t\t\tresult = 'in progress',\n\t\t\treply = {\n\t\t\t\terror: null,\n\t\t\t\tcode: 500,\n\t\t\t\tdata: null\n\t\t\t},\n\t\t\tdelay = Date.now() + 10000; // wait not more than 10 seconds\n\n\t\ttry {\n\t\t\t// update postfix JSON\n\t\t\tvar list = {\n\t\t\t\tupdateTime: '',\n\t\t\t\tzwave_vendors: {}\n\t\t\t};\n\n\t\t\thttp.request({\n\t\t\t\turl: \"http://manuals-backend.z-wave.info/make.php?mode=brand\",\n\t\t\t\tasync: true,\n\t\t\t\tsuccess: function(res) {\n\t\t\t\t\tif (res.data) {\n\t\t\t\t\t\tlist.updateTime = Date.now();\n\t\t\t\t\t\tlist.zwave_vendors = parseToObject(res.data);\n\n\t\t\t\t\t\tsaveObject('zwave_vendors.json', list, true);\n\n\t\t\t\t\t\tresult = 'done';\n\n\t\t\t\t\t\treply.code = 200;\n\t\t\t\t\t\treply.data = list;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\terror: function(e) {\n\t\t\t\t\tvar msg = 'Z-Wave vendors list could not be updated. Error: ' + e.toString();\n\t\t\t\t\tself.controller.addNotification('error', msg, 'core', 'ZAutomationAPI');\n\n\t\t\t\t\tresult = 'failed';\n\n\t\t\t\t\treply.code = e.status;\n\t\t\t\t\treply.error = msg;\n\t\t\t\t\treply.data = e.data;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\twhile (result === 'in progress' && Date.now() < delay) {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === 'in progress') {\n\t\t\t\tresult = 'failed';\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\tthis.controller.addNotification('error', 'Error has occured during updating the Z-Wave devices list', 'core', 'ZAutomationAPI');\n\t\t\treply.error = 'Something went wrong:' + e.message;\n\t\t}\n\n\t\treturn reply;\n\t},\n\tredirectURL: function() {\n\t\tvar self = this;\n\t\tvar params = Object.keys(this.req.query).filter(function(k) { return k != \"to\"; }).map(function(k) { return k + \"=\" + self.req.query[k]; }).join(\"&\");\n\t\treturn {\n\t\t\terror: null,\n\t\t\tcode: 302,\n\t\t\theaders: {\n\t\t\t\t\"Location\": this.req.query[\"to\"] + (params ? \"?\" + params : \"\")\n\t\t\t}\n\t\t};\n\t},\n\tdemultiplex: function(_path) {\n\t\tvar self = this;\n\t\tvar reply = {\n\t\t\terror: null,\n\t\t\tdata: [],\n\t\t\tcode: 200\n\t\t};\n\n\t\tvar fullUrl = this.req.fullUrl,\n\t\t    prefix = \"/demultiplex/\",\n\t\t    ind;\n\t\t\n\t\t// A bit urgly logic to remove API prefix\n\t\tif (!fullUrl || (ind = fullUrl.indexOf(prefix + _path)) === -1) return { code: 500 };\n\t\tfullUrlPrefix = fullUrl.slice(0, fullUrl.indexOf(this.req.url));\n\t\tfullUrl = fullUrl.slice(ind + prefix.length);\n\t\tvar prefix = _.first(self.req.url.split(\"/\"), 2).join(\"/\") + \"/\";\n\t\t\n\t\tfullUrl.split(\";\").forEach(function(url) {\n\t\t\tvar path = url,\n\t\t\t    query = {},\n\t\t\t    qind = url.indexOf(\"?\");\n\t\t\tif (qind > -1) {\n\t\t\t\tvar q = url.slice(qind + 1);\n\t\t\t\tpath = url.slice(0, qind);\n\t\t\t\tq.split(\"&\").forEach(function(kv) {\n\t\t\t\t\tvar kv_arr = kv.split(\"=\");\n\t\t\t\t\tquery[kv_arr[0]] = kv_arr[1];\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tself.req.fullUrl = fullUrlPrefix + prefix + url;\n\t\t\tself.req.url =  prefix + path;\n\t\t\tself.req.query = query;\n\t\t\t\n\t\t\tvar ret = self.handleRequest(self.req.url, self.req);\n\n\t\t\tvar body;\n\t\t\ttry {\n\t\t\t\tbody = JSON.parse(ret.body);\n\t\t\t} catch(ex) {\n\t\t\t\tbody = ret.body;\n\t\t\t}\n\t\t\treply.data.push({\n\t\t\t\tstatus: ret.status,\n\t\t\t\tbody: body\n\t\t\t});\n\t\t});\n\t\t\n\t\treturn reply;\n\t}\n});\n\n\nZAutomationAPIWebRequest.prototype.Unauthorized = function() {\n\treturn {\n\t\terror: 'Not logged in',\n\t\tdata: null,\n\t\tcode: 401\n\t};\n}\n\nZAutomationAPIWebRequest.prototype.Forbidden = function() {\n\treturn {\n\t\terror: 'Permission denied',\n\t\tdata: null,\n\t\tcode: 403\n\t};\n}\n\nZAutomationAPIWebRequest.prototype.dispatchRequest = function(method, url) {\n\tvar self = this,\n\t\thandlerFunc = this.NotFound, // Default handler is NotFound\n\t\tvalidParams;\n\n\tvar matched = this.router.dispatch(method, url);\n\tif (matched) {\n\t\tvar auth = this.controller.auth.resolve(this.req, matched.role);\n\t\tif (!auth) {\n\t\t\treturn this.Unauthorized;\n\t\t} else if (this.controller.auth.isAuthorized(auth.role, matched.role)) {\n\t\t\tif (matched.params.length) {\n\t\t\t\tvalidParams = _.every(matched.params),\n\t\t\t\t\tfunction(p) {\n\t\t\t\t\t\treturn !!p;\n\t\t\t\t\t};\n\t\t\t\tif (validParams) {\n\t\t\t\t\thandlerFunc = function() {\n\t\t\t\t\t\treturn matched.handler.apply(this, matched.params);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\thandlerFunc = matched.handler ? matched.handler : handlerFunc;\n\t\t\t}\n\n\t\t\t// --- Proceed to checkout =)\n\t\t\treturn handlerFunc;\n\t\t} else {\n\t\t\treturn this.Forbidden;\n\t\t}\n\t} else {\n\t\treturn handlerFunc;\n\t}\n};\n\nZAutomationAPIWebRequest.prototype.reorderDevices = function() {\n\tvar self = this,\n\t\treply = {\n\t\t\terror: \"Internal Server Error\",\n\t\t\tdata: null,\n\t\t\tcode: 500\n\t\t};\n\n\tvar reqObj = typeof this.req.body !== 'object' ? JSON.parse(this.req.body) : this.req.body;\n\n\tvar data = reqObj.data, // ordered list of devices\n\t\taction = reqObj.action; // Dashboard, Elements, Room(location)\n\n\tif (self.controller.reoderDevices(data, action)) {\n\t\treply.error = \"\";\n\t\treply.data = \"OK\";\n\t\treply.code = 200;\n\t}\n\n\t//\t a = self.controller.order.elements.indexOf(reqObj[0].id);\n\t//\t b = self.controller.order.elements.indexOf(reqObj[1].id);\n\t//\n\t// Array.prototype.swapItems = function(a, b){\n\t//\t this[a] = this.splice(b, 1, this[a])[0];\n\t//\t return this;\n\t// }\n\t//\n\t//\n\t// self.controller.order.elements = self.controller.order.elements.swapItems(a,b);\n\t//\n\n\treturn reply;\n\n}\n"
  },
  {
    "path": "apiary.apib",
    "content": "emFORMAT: 1A\nHOST: http://r3bfish.ddns.net:8083/ZAutomation/api\n\n# Z-Way API\n\n+ Allowed HTTPs requests:\n\t+ POST\t  To create resource\n\t+ PUT\t   To update resource\n\t+ GET\t   Get a resource or list of resources\n\t+ DELETE\tTo delete resource\n\n+ Allow get parameters\n\t+ suppress_response_codes (optional, boolean) ... If this parameter is present, all responses will be returned with a 200 OK status code - even errors. This parameter exists to accommodate Flash and JavaScript applications running in browsers that intercept all non-200 responses. If used, it’s then the job of the client to determine error states by parsing the response body. Use with caution, as those error messages may change.\n\t+ pagination (optional, boolean) ... If this parameter is present, all response of the lists (Devices, Notifications) will be included pagination  \n\t+ limit (optional, number) ... If this parameter is present, then set limit models per page, else set default 10 models per page\n\t+ offset (options, number) ... If this parameter is present, then set start point models in page, else set default offset 0.\n\t+ fields (options, string) ... example: nameField1,nameField2,...\n\n+ Status codes,\n\t+ 200:  \"200 OK\",\n\t+ 201:  \"201 Created\",\n\t+ 204:  \"204 No Content\",\n\t+ 304:  \"304 Not Modified\",\n\t+ 400:  \"400 Bad Request\",\n\t+ 401:  \"401 Unauthorized\",\n\t+ 403:  \"403 Forbidden\",\n\t+ 404:  \"404 Not Found\",\n\t+ 405:  \"405 Method Not Allowed\",\n\t+ 500:  \"500 Internal server error\",\n\t+ 501:  \"501 Not Implemented\"\n\t+ 503:  \"503 Service Unavailable\"\n\t\n\n# Group Platform Availability \n<a id=\"available\" ></a>\n\nIt will return 503 with Error message (see the details below). You can also use **/v1/status** resource to check the Platform availability.\n\n## /v1/status\n### GET\nResource for checking the Platform availability.\n\n+ Request\n\n\t+ Headers\n\n\t\t\tAccept: application/json\n\n\n+ Response 200\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: \"OK\",\n\t\t\t\tcode: 200\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\n+ Response 503\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\terror: \"Internal server error. Please fill in bug report with request_id='\" + this.error + \"'\",\n\t\t\t\tdata: null,\n\t\t\t\tcode: 503,\n\t\t\t\tmessage: \"Service Unavailable\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n# Group Platform Restart\n<a id=\"available\" ></a>\n\nYou can use **/v1/restart** to restart the controller. This will reload all notifications, ZAutomation API and reinitialize (not reload) all apps.\n\n## /v1/restart\n### GET\nPlatform Restart\n\n+ Request\n\n\t+ Headers\n\n\t\t\tAccept: application/json\n\n\n+ Response 200\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: \"OK\",\n\t\t\t\tcode: 200\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\n# Group Namespaces\n<a id=\"available\" ></a>\n\nNamespaces is a collection of internal registered names and ids - e.g. for zway or virtual devices. \nThis API is mostly used in apps to create custom filters for virtual device selection. The data is build during z-way controller start up. Virtual device namespaces are influenced by the following listener emits:\n* **created** ... added to devices collection\n* **removed** ... removed from devices collection\n* **change:metrics:title** ... change name of virtual dev\n* **change:permanently_hide** ... deactivate virtual device - not hidden and usable\n\nThe namespace structure of virtual devices depends on their device types an probe types. Please check chapter **[Devices](anchor-devices)** for more information.\n\n###Methods\n- **/v1/namespaces** - read all namespaces.\n- **/v1/namespaces/zways** - zway namespaces.\n- **/v1/namespaces/devices_all** - array of all registered virtual devices that includes deviceId and deviceName.\n- **/v1/namespaces/{devices_DEVICETYPE}** - read namespaces of specific **device type** and show their **probe type** children.\n- **/v1/namespaces/{devices_DEVICETYPE}.{PATH}** - use path to read namespaces of child probe types  from a specific device type.\n- **/v1/namespaces/{devices_DEVICETYPE}.{PATH}.deviceId** - get an array of all deviceId's that lies under path endpoint.\n- **/v1/namespaces/{devices_DEVICETYPE}.{PATH}.deviceName** - get an array of all deviceNames's lies under path endpoint.\n\n\n## Namespaces Collection [/v1/namespaces]\n### List all Namespaces [GET]\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"zways\",\n\t\t\t\t\t\tparams: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tzwayName: \"zway\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"devices_battery\",\n\t\t\t\t\t\tparams: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-128\",\n\t\t\t\t\t\t\t\tdeviceName: \"Fibar Group Battery (7.0)\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"devices_all\",\n\t\t\t\t\t\tparams: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"DummyDevice_12\",\n\t\t\t\t\t\t\t\tdeviceName: \"Switch All On\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"DummyDevice_13\",\n\t\t\t\t\t\t\t\tdeviceName: \"Tischlampe\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"DummyDevice_18\",\n\t\t\t\t\t\t\t\tdeviceName: \"Deckenlampe\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-37\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Sirene Switch\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-48-2\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Sensor\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-48-8\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Tamper Sensor\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-1-2-A\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Alarm\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-7-3-A\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Burglar Alarm\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-9-1-A\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke System Alarm\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-128\",\n\t\t\t\t\t\t\t\tdeviceName: \"Fibar Group Battery (7.0)\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"Sonos_Device_Play_192.168.10.205_21\",\n\t\t\t\t\t\t\t\tdeviceName: \"Sonos Play Wohnzimmer\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"Sonos_Device_Volume_192.168.10.205_21\",\n\t\t\t\t\t\t\t\tdeviceName: \"Sonos Volume Wohnzimmer\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"devices_switchBinary\",\n\t\t\t\t\t\tparams: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"DummyDevice_12\",\n\t\t\t\t\t\t\t\tdeviceName: \"Switch All On\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-37\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Sirene Switch\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"Sonos_Device_Play_192.168.10.205_21\",\n\t\t\t\t\t\t\t\tdeviceName: \"Sonos Play Wohnzimmer\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"devices_switchMultilevel\",\n\t\t\t\t\t\tparams: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"DummyDevice_13\",\n\t\t\t\t\t\t\t\tdeviceName: \"Tischlampe\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"DummyDevice_18\",\n\t\t\t\t\t\t\t\tdeviceName: \"Deckenlampe\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"Sonos_Device_Volume_192.168.10.205_21\",\n\t\t\t\t\t\t\t\tdeviceName: \"Sonos Volume Wohnzimmer\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"devices_sensorBinary\",\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tsmoke: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-48-2\",\n\t\t\t\t\t\t\t\t\tdeviceName: \"Smoke Sensor\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\ttamper: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-48-8\",\n\t\t\t\t\t\t\t\t\tdeviceName: \"Smoke Tamper Sensor\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\talarm: {\n\t\t\t\t\t\t\t\tsmoke: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-1-2-A\",\n\t\t\t\t\t\t\t\t\t\tdeviceName: \"Smoke Alarm\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tburglar: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-7-3-A\",\n\t\t\t\t\t\t\t\t\t\tdeviceName: \"Smoke Burglar Alarm\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\tsystem: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-9-1-A\",\n\t\t\t\t\t\t\t\t\t\tdeviceName: \"Smoke System Alarm\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: \"200 OK\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror: \"Namespaces array is null\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n## Z-Way Namespaces Collection [/v1/namespaces/zways]\n### List all Z-Way Namespaces [GET]\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"zwayName\": \"zway\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"zwayName\": \"zway_remote_1\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"zwayName\": \"zway_remote_2\"\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: \"200 OK\",\n\t\t\t\terror: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n## Virtual Device Namespace Model  [/v1/namespaces/{devices_DEVICETYPE}.{PATH}.{deviceId,deviceName}]\n### List specific namespaces [GET]\n\t\t\t\n+ Parameters\n\t+ `devices_DEVICETYPE` (optional, string, `devices_sensorBinary`) ... get namespaces of all devices `devices_all` or by device type - e.g. `devices_switchBinary`, `devices_sensorBinary`, `devices_switchControl` ...\n\t+ PATH (optional, string, `alarm.smoke`) ... get namespaces of devices depending on their probe type - e.g. `smoke`, `alarm`, `alarm.smoke`\n\t+ deviceId (optional, string, `deviceId`) ... get an array with device ID's of all virtual child devices.\n\t+ deviceName (optional, string, `deviceName`) ... get an array with device names's of all virtual child devices.\n\t\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\tdata: {\n\t\t\t\t\tsmoke: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-48-2\",\n\t\t\t\t\t\t\tdeviceName: \"Smoke Sensor\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\ttamper: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-48-8\",\n\t\t\t\t\t\t\tdeviceName: \"Smoke Tamper Sensor\"\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\talarm: {\n\t\t\t\t\t\tsmoke: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-1-2-A\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Alarm\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t],\n\t\t\t\t\t\tburglar: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-7-3-A\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke Burglar Alarm\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t],\n\t\t\t\t\t\tsystem: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdeviceId: \"ZWayVDev_zway_7-0-113-9-1-A\",\n\t\t\t\t\t\t\t\tdeviceName: \"Smoke System Alarm\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: \"200 OK\",\n\t\t\t\terror: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"smoke\": {\n\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"tamper\"\n\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"alarm\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"smoke\": {\n\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"burglar\"\n\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"system\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror: \"No namespaces found with this path: foobar\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n# Group Modules\n<a id=\"available\" ></a>\n\nThis API prepares the whole meta data of all registered modules and their instances. \n\n###Methods for:\n#### Module Meta Data\n- **/v1/modules** - read all module meta data.\n- **/v1/modules/{module-id}** - get meta data of specific module\n\n#### Module Handling\n- **/v1/modules/install** - download and install module (.tar.gz/ .zip) from the given address.\n- **/v1/modules/update** - download and overwrite module (.tar.gz/ .zip) from the given address. Reload JS and meta data of updated module.\n- **/v1/modules/reset/{module-id}** - resets an updated module back to its preinstalled version. Module needs to be preinstalled by on current firmware.\n- **/v1/modules/delete/{module-id}** - deletes a **non preinstalled** module and removes all its instances. Cannot be undone without doing backup before.\n- **/v1/modules/reinitialize/{module-id}** - stops all instances of module, reloads JS and meta data and starts instances again - useful for module development.\n\n#### Module Categories\n- **/v1/modules/categories** - show all module categories\n- **/v1/modules/categories/{category-id}** - list modules by category\n\n#### Access to Online Store Groups \n- **/v1/modules/tokens** - create/read/update/delete tokens for online store group access.\n\n## Module attributes\n\nThis is a list of all module attributes hand out by the api. Some of them are predefined by module.json and the rest is added by the controller after initialisation.\n\n| Module Attributes| Type\t\t\t\t\t | Comment\t\t\t\t\t\t\t\t\t\t\t|\n|---------------|-----------------------------|----------------------------------------------------|\n| `id`\t\t  | _immutable_ (string, uniq)  | class name as unique identifier |\n| `location`\t| _immutable_ (string)\t\t| path to file directory: /modules or /userModules |\n| `className`   | _immutable_ (string)\t\t| reference to class name from index.js |\n| `hasReset`\t| (boolean, false)\t\t\t| indicator if module could be reseted |\n| `created`\t | (boolean, false)\t\t\t| indicator if an instance of a singleton module already exists |\n| `dependencies`| (array, [])\t\t\t\t | id's of modules that are necessary to initiate this module |\n| `singleton`   | (boolean, false)\t\t\t| indicates if a module could have only one (singleton) or more running instances  |\n| `category`\t| (string)\t\t\t\t\t| assign module to special category |\n| `author`\t  | (string)\t\t\t\t\t| name of author |\n| `homepage`\t| (string, uri)\t\t\t   | homepage (of author) |\n| `icon`\t\t| (string, uri)\t\t\t   | custom icon field: looks in folder _/LOCATION/MODULENAME/htdocs/ICON-NAME.png_ |\n| `version`\t | (string or number)\t\t  | current version of module, format MAJOR.FEATURES.PATCHES ``0.0.0`` |\n| `maturity`\t| (string)\t\t\t\t\t| shows maturity of a modules: _alpha, beta, gamma, ... or stable_ |\n| `repository`  | (object)\t\t\t\t\t| information about the repository where to find the module e.g. ``{\"type\": \"git\",\"source\": \"https://github.com/Z-Wave-Me/home-automation\"}`` |\n| `defaults`\t| (object)\t\t\t\t\t| defines default attributes (basic skeleton) of the module, also includes module title and description e.g. ``{\"title\": \"AutoLock\",\"description\": \"Electronic Doors typically move the dead bold of the door. [...]\"``\n} |\n| `schema`\t  | (object)\t\t\t\t\t| defines formatting schema for UI transformation with Alpaca Forms |\n| `options`\t | (object)\t\t\t\t\t| defines view attributes of objects for UI transformation with Alpaca Forms |\n\nMore information about 'How to build a module?' you will find [here in this tutorial on developer.z-wave.me](http://developer.z-wave.me/?uri=help). Please check out [http://www.alpacajs.org/](http://www.alpacajs.org/) to learn more about Alpaca Forms and how you could use it to make your own modules for home automation.\n\n## Modules Collection [/v1/modules]\n### List all Modules [GET]\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 'module-id',\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"array\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Module Model [/v1/modules/{module-id}]\n### List Module Meta Data [GET]\n\n+ Parameters\n\t+ module-id (required, string, `BatteryPolling`) ... class name of module from which meta data should be requested\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\t\"singleton\": true,\n\t\t\t\t\t\"dependencies\": [\n\t\t\t\t\t\t\"Cron\"\n\t\t\t\t\t],\n\t\t\t\t\t\"category\": \"basic_gateway_modules\",\n\t\t\t\t\t\"author\": \"Z-Wave.Me\",\n\t\t\t\t\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\t\t\t\t\"icon\": \"icon.png\",\n\t\t\t\t\t\"moduleName\": \"BatteryPolling\",\n\t\t\t\t\t\"version\": \"2.0.1\",\n\t\t\t\t\t\"maturity\": \"stable\",\n\t\t\t\t\t\"repository\": {\n\t\t\t\t\t\t\"type\": \"git\",\n\t\t\t\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t\t\t\t\t},\n\t\t\t\t\t\"defaults\": {\n\t\t\t\t\t\t\"title\": \"Battery Polling\",\n\t\t\t\t\t\t\"description\": \"The battery polling will update the battery status by asking all battery-operated device once a week for a battery status update.. You can pick the day of the week and a warning level, when this module will send you a warning note.\",\n\t\t\t\t\t\t\"launchWeekDay\": 0,\n\t\t\t\t\t\t\"warningLevel\": 20\n\t\t\t\t\t},\n\t\t\t\t\t\"schema\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"launchWeekDay\": {\n\t\t\t\t\t\t\t\t\"type\": \"number\",\n\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t-1,\n\t\t\t\t\t\t\t\t\t1,\n\t\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t\t\t3,\n\t\t\t\t\t\t\t\t\t4,\n\t\t\t\t\t\t\t\t\t5,\n\t\t\t\t\t\t\t\t\t6,\n\t\t\t\t\t\t\t\t\t0\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"warningLevel\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t5,\n\t\t\t\t\t\t\t\t\t10,\n\t\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\t\t20\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t},\n\t\t\t\t\t\"options\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"launchWeekDay\": {\n\t\t\t\t\t\t\t\t\"label\": \"Do battery polling on\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"Every Day\",\n\t\t\t\t\t\t\t\t\t\"Monday\",\n\t\t\t\t\t\t\t\t\t\"Tuesday\",\n\t\t\t\t\t\t\t\t\t\"Wednesday\",\n\t\t\t\t\t\t\t\t\t\"Thursday\",\n\t\t\t\t\t\t\t\t\t\"Friday\",\n\t\t\t\t\t\t\t\t\t\"Saturday\",\n\t\t\t\t\t\t\t\t\t\"Sunday\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"warningLevel\": {\n\t\t\t\t\t\t\t\t\"label\": \"Warning Level\",\n\t\t\t\t\t\t\t\t\"helper\": \"Warn if device's battery is below this level\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"5%\",\n\t\t\t\t\t\t\t\t\t\"10%\",\n\t\t\t\t\t\t\t\t\t\"15%\",\n\t\t\t\t\t\t\t\t\t\"20%\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"id\": \"BatteryPolling\",\n\t\t\t\t\t\"location\": \"modules/BatteryPolling\",\n\t\t\t\t\t\"hasReset\": false\n\t\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"array\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror: \"Instance 'module-id' not found\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Install Module [/v1/modules/install{?moduleUrl}]\n### INSTALL [POST]\n\n+ Parameters\n\t+ moduleUrl (required, string, `http://developer.z-wave.me/modules/ScheduledScene.tar.gz`) ... target download url\n\n+ Request (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\t\tmoduleUrl: \"http://developer.z-wave.me/modules/ScheduledScene.tar.gz\"\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"moduleUrl\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\n+ Response 201 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tkey: \"The app was successfully installed.\",\n\t\t\t\t\tappendix: null\n\t\t\t\t},\n\t\t\t\tcode: 201,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"; {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"appendix\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 409\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 409,\n\t\t\t\tmessage: \"409 conflict\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"The app is already installed.\",\n\t\t\t\t\terrorMsg: null\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"Failed to install the app.\",\n\t\t\t\t\terrorMsg: null\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n## Update Module [/v1/modules/update{?moduleUrl}]\n### UPDATE [POST]\n\n+ Parameters\n\t+ moduleUrl (required, string, `http://developer.z-wave.me/modules/ScheduledScene.tar.gz`) ... target download url\n\t\n+ Request (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\t\tmoduleUrl: \"http://developer.z-wave.me/modules/ScheduledScene.tar.gz\"\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"moduleUrl\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tkey: \"The app was successfully updated.\",\n\t\t\t\t\tappendix: null\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"array\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror: \"Cannot find the app.\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"Failed to update the app.\",\n\t\t\t\t\terrorMsg: null\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Reset Module [/v1/modules/reset/{module-id}]\n### RESET - works only if module was preinstalled by default [POST]\n\n+ Parameters\n\t+ module-id (required, string, `ScheduledScene`) ... class name of module that should be reseted\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tkey: \"The app was successfully reseted.\",\n\t\t\t\t\tappendix: \"current_version\"\n\t\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"appendix\"\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"App not found.\",\n\t\t\t\t\terrorMsg: null\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 412\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 412,\n\t\t\t\tmessage: \"412 Precondition Failed\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"App is already reset.\",\n\t\t\t\t\terrorMsg: null\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"There was an error during resetting the app 'module-id'. Maybe a server restart could solve this problem.\",\n\t\t\t\t\terrorMsg: null\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Delete Module [/v1/delete/{module-id}]\n### DELETE - works only with non preinstalled modules [DELETE]\n\n+ Parameters\n\t+ module-id (required, string, `MultiButton`) ... class name of module that should deleted\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tkey: \"The app was successfully deleted\",\n\t\t\t\t\tappendix: null\n\t\t\t\t\t\t\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"appendix\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"App not found.\"\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: {\n\t\t\t\t\tkey: \"Failed to delete the app.\"\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"key\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"errorMsg\"\n\t\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Reinitialize Module [/v1/reinitialize/{module-id}]   \n### REINITIALIZE [GET]\n\n+ Parameters\n\t+ module-id (required, string, `BatteryPolling`) ... class name of module that should be reinitialized\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: \"Reinitialization of app 'module-id' successfull.\",\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not Found\",\n\t\t\t\terror:  \"App not found.\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Module Categories [/v1/modules/categories]\n- **/v1/modules/categories** - show all module categories\n\n## Module Categories [/v1/modules/categories/{category-id}]\n- **/v1/modules/categories/{category-id}** - list modules by category\n\n## Access to Online Store Groups [/v1/modules/tokens]\n- **/v1/modules/tokens** - create/read/update/delete tokens for online store group access.\n\t\t\t\n# Group Instances\n\nAn instance is an object that is derived from a modules class. The module itself is a predefined mask and allows to create custom or different instances of it. For example using the module **If > Then**:\n\n1. If ``Switch A`` is ``ON`` > Set ``Dimmer A`` to level ``99``, ``Radio`` to level ``12``, switch ``Plug Media````ON``\n2. If ``Switch A`` is ``OFF`` > Set ``Dimmer A`` to level ``0``, switch ``Radio````OFF``, switch ``Plug Media````ON``\n\nBoth instances are derived objects from the _IfThen()_ class of **If > Then** module. They have the same origin but different attributes and usage. This also means that one module could usually have one or more registered instances.\n\n#### Singleton Instances:\n\nIf a module has the the attribute ``\"singleton\": true`` then it could only have one registered instance - called singleton. Singletons are useful to avoid unnecessary instantiations of one class, so for example the module **Z-Wave Network Access** is configured as singleton. This module is the interface between the z-way controller and the Smart Home UI. It makes no sence to add another instance of that module because the interface already exists. Also another instance could interfere with the existing one because their class isn't concipated to handle more than one.\n\n#### Instances\n- **/v1/instances** - get all instances or create new instance (POST).\n- **/v1/instances/{module-name}** - get an array of all instances of one module.\n- **/v1/instances/{instance-id}** - read/update/delete instances.\n\n## Instances Collection [/v1/instances]   \n### List all Instances [GET]\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 2,\n\t\t\t\t\t\tmoduleId: \"Cron\",\n\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\tactive: true,\n\t\t\t\t\t\ttitle: \"System Clock (CRON)\",\n\t\t\t\t\t\tdescription: \"Scheduler used by other modules.\",\n\t\t\t\t\t\tcreationTime: 1459769281,\n\t\t\t\t\t\tstate: null,\n\t\t\t\t\t\tmodule: \"System Clock (CRON)\"\n\t\t\t\t\t}, {\n\t\t\t\t\t\tid: 3,\n\t\t\t\t\t\tmoduleId: \"InbandNotifications\",\n\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\tactive: true,\n\t\t\t\t\t\ttitle: \"Inband Notifier\",\n\t\t\t\t\t\tdescription: \"Creates and records the presentation of events in the event list (Eventlog).\",\n\t\t\t\t\t\tcreationTime: 1459769281,\n\t\t\t\t\t\tstate: null,\n\t\t\t\t\t\tmodule: \"Inband Notifier\"\n\t\t\t\t\t}, {\n\t\t\t\t\t\tid: 7,\n\t\t\t\t\t\tmoduleId: \"BatteryPolling\",\n\t\t\t\t\t\tactive: \"true\",\n\t\t\t\t\t\ttitle: \"Battery Polling\",\n\t\t\t\t\t\tdescription: \"Set up an interval that regularly polls the battery status of a battery devices.\",\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tlaunchWeekDay: 0,\n\t\t\t\t\t\t\twarningLevel: \"20\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcreationTime: 1459769281\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: \"200 OK\",\n\t\t\t\terror: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: \"Could not list Instances.\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n### CREATE [POST]\n\n+ Request (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tmoduleId: \"BatteryPolling\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tlaunchWeekDay: 0,\n\t\t\t\t\t\twarningLevel: \"20\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"moduleId\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n+ Response 201 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\tmoduleId: 'moduleId',\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"moduleId\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not found\",\n\t\t\t\terror: \"Module 'module-id' doesn't exist.\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: \"Cannot instantiate module 'module-id'\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n## Instance Collection by module id [/v1/instances/{module-id}]\n\nList all instances that has the same module as origin.\n\n+ Parameters\n\t+ module-id (required, string, `IfThen`) ... module id (class name) of parent module\n\n### READ [GET]\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t{\n\t\t\t\"data\": [\n\t\t\t\t{\n\t\t\t\t\t\"instanceId\": \"0\",\n\t\t\t\t\t\"moduleId\": \"IfThen\",\n\t\t\t\t\t\"active\": \"true\",\n\t\t\t\t\t\"title\": \"All On\",\n\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\"sourceDevice\": {\n\t\t\t\t\t\t\t\"filterIf\": \"scene\",\n\t\t\t\t\t\t\t\"scene\": {\n\t\t\t\t\t\t\t\t\"device\": \"ZWayVDev_zway_Remote_39-0-0-1-S\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"targets\": [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"filterThen\": \"switchBinary\",\n\t\t\t\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\t\t\t\"target\": \"ZWayVDev_zway_13-0-37\",\n\t\t\t\t\t\t\t\t\t\"status\": \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"filterThen\": \"switchBinary\",\n\t\t\t\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\t\t\t\"target\": \"Sonos_Device_Play_192.168.10.205_21\",\n\t\t\t\t\t\t\t\t\t\"status\": \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t\"id\": 24,\n\t\t\t\t\t\"creationTime\": 1461152581\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"instanceId\": \"0\",\n\t\t\t\t\t\"moduleId\": \"IfThen\",\n\t\t\t\t\t\"active\": true,\n\t\t\t\t\t\"title\": \"All Off\",\n\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\"sourceDevice\": {\n\t\t\t\t\t\t\t\"filterIf\": \"scene\",\n\t\t\t\t\t\t\t\"scene\": {\n\t\t\t\t\t\t\t\t\"device\": \"ZWayVDev_zway_Remote_39-0-0-2-S\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"targets\": [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"filterThen\": \"switchBinary\",\n\t\t\t\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\t\t\t\"target\": \"Sonos_Device_Play_192.168.10.205_21\",\n\t\t\t\t\t\t\t\t\t\"status\": \"off\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\t\t\"filterThen\": \"switchBinary\",\n\t\t\t\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\t\t\t\"target\": \"DummyDevice_12\",\n\t\t\t\t\t\t\t\t\t\"status\": \"off\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t\"id\": 25,\n\t\t\t\t\t\"creationTime\": 1461152774\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"code\": 200,\n\t\t\t\"message\": \"200 OK\",\n\t\t\t\"error\": null\n\t\t}\n\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\n\t+ Body\n\t\n\t\t{\n\t\t\t\"data\": null,\n\t\t\t\"code\": 404,\n\t\t\t\"message\": \"404 Not Found\",\n\t\t\t\"error\": \"Instance foobar is not found\"\n\t\t}\n\n## Instance Model [/v1/instances/{instance-id}]\n\n| Instance Attributes| Type\t\t\t\t\t | Comment\t\t\t\t\t\t\t\t\t\t\t|\n|---------------|-----------------------------|----------------------------------------------------|\n| `id`\t\t  | _immutable_ (string, uniq)  | id of instance |\n| `moduleId`\t| _immutable_ (string)\t\t| id of referenced module (classname) |\n| `active`\t  | (boolean, true)\t\t\t | marks instance as in-/active |\n| `title`\t   | (string)\t\t\t\t\t| title of instance |\n| `params`\t  | (object, {})\t\t\t\t| depends on module, includes all last configured parameters that could be entered through the module form |\n| `creationTime`| (integer)\t\t\t\t   | timestamp of creation time |\n\n+ Parameters\n\t+ instance-id (required, string, `7`) ... id (number) of target instance\n\n### READ [GET]\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 7,\n\t\t\t\t\t\tmoduleId: \"BatteryPolling\",\n\t\t\t\t\t\tactive: \"true\",\n\t\t\t\t\t\ttitle: \"Battery Polling\",\n\t\t\t\t\t\tdescription: \"Set up an interval that regularly polls the battery status of a battery devices.\",\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tlaunchWeekDay: 0,\n\t\t\t\t\t\t\twarningLevel: \"20\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcreationTime: 1459769281\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: \"200 OK\",\n\t\t\t\terror: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not found\",\n\t\t\t\terror: \"Instance 'instance-id' is not found\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t\n### UPDATE [PUT]\n\n+ Request (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: {\n\t\t\t\t\tmoduleId: \"BatteryPolling\",\n\t\t\t\t\ttitle: \"New name for BatteryPolling\",\n\t\t\t\t\tparams: {\n\t\t\t\t\t\tlaunchWeekDay: 5,\n\t\t\t\t\t\twarningLevel: \"15\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"moduleId\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n+ Response 200 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: 7,\n\t\t\t\t\t\tmoduleId: \"BatteryPolling\",\n\t\t\t\t\t\tactive: \"true\",\n\t\t\t\t\t\ttitle: \"New name for BatteryPolling\",\n\t\t\t\t\t\tdescription: \"Set up an interval that regularly polls the battery status of a battery devices.\",\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tlaunchWeekDay: 5,\n\t\t\t\t\t\t\twarningLevel: \"15\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcreationTime: 1459769281\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tcode: 200,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\" :{\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not found\",\n\t\t\t\terror: \"Instance 'instance-id' is not found\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 500\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Internal server error\",\n\t\t\t\terror: \"Cannot reconfigure module 'instance-id' config.\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n### DELETE [DELETE]\n\n+ Response 204 (application/json)\n\t\n\t+ Body \n\n\t\t\t{\n\t\t\t\terror: null,\n\t\t\t\tdata: null,\n\t\t\t\tcode: 204,\n\t\t\t\tmessage: null\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\" :{\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n+ Response 404\n\n\t+ Headers\n\t\n\t\t\tContent-Type: application/json\n\t\t\n\t+ Body \n\t\n\t\t\t{\n\t\t\t\tdata: null,\n\t\t\t\tcode: 404,\n\t\t\t\tmessage: \"404 Not found\",\n\t\t\t\terror: \"Instance 'instance-id' is not found\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n# Group Devices\nThe **Devices API** handles all actions of virtual devices in the gateway related to their origin or node (included device). To recognize all this API could be fetched immediately. Also sending commands to change levels etc. is is done by this API.\n\n## Devices Collection [/v1/devices{?since}]\n\n| Devices Data Attribute | Type\t | Comment\t\t\t\t  |\n|-------------------|---------------|--------------------------|\n| `structureChanged`| (boolean)\t | indicates of structure of list has changed (virtual devices has been added or removed) |\n| `updateTime`\t  | (integer)\t | timestamp of last change |\n\n### List all Devices  [GET]\n\n+ Parameters\n\t+ since (optional, integer, `1459939093`) ... `updateTime` of the devices list.\n\n+ Response 200 (application/json)\n\n\t+ Body\n\t\t{\n\t\t\tdata: {\n\t\t\t\tstructureChanged: true,\n\t\t\t\tupdateTime: 1464761666,\n\t\t\t\tdevices: [{\n\t\t\t\t\tcreationTime: 1459939093,\n\t\t\t\t\tcreatorId: 7,\n\t\t\t\t\tdeviceType: \"battery\",\n\t\t\t\t\th: -592588978,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"BatteryPolling_7\",\n\t\t\t\t\tlocation: 0,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: \"Battery\",\n\t\t\t\t\t\tscaleTitle: \"%\",\n\t\t\t\t\t\ttitle: \"Battery digest 7\",\n\t\t\t\t\t\tlevel: 47,\n\t\t\t\t\t\tmodificationTime: 1464684791,\n\t\t\t\t\t\tlastLevel: 47\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684791\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1459947936,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"sensorBinary\",\n\t\t\t\t\th: 1303282175,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_2-0-48-1\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: \"General purpose\",\n\t\t\t\t\t\tscaleTitle: \"\",\n\t\t\t\t\t\ticon: \"motion\",\n\t\t\t\t\t\tlevel: \"on\",\n\t\t\t\t\t\ttitle: \"Motion - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1463116944,\n\t\t\t\t\t\tlastLevel: \"on\"\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"general_purpose\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684789\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1461244852,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\t\th: 1303283136,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_2-0-49-1\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: \"Temperature\",\n\t\t\t\t\t\tscaleTitle: \"°C\",\n\t\t\t\t\t\tlevel: 24,\n\t\t\t\t\t\ticon: \"temperature\",\n\t\t\t\t\t\ttitle: \"Temperature Door - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1463128674,\n\t\t\t\t\t\tlastLevel: 24\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"temperature\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684789\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1461244853,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\t\th: 1303283138,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_2-0-49-3\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: \"Luminiscence\",\n\t\t\t\t\t\tscaleTitle: \"Lux\",\n\t\t\t\t\t\tlevel: 130,\n\t\t\t\t\t\ticon: \"luminosity\",\n\t\t\t\t\t\ttitle: \"Luminiscence - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1463128674,\n\t\t\t\t\t\tlastLevel: 130\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"luminosity\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684790\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1459947935,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"battery\",\n\t\t\t\t\th: -927793024,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_2-0-128\",\n\t\t\t\t\tlocation: 0,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: \"Battery\",\n\t\t\t\t\t\tscaleTitle: \"%\",\n\t\t\t\t\t\tlevel: 100,\n\t\t\t\t\t\ticon: \"battery\",\n\t\t\t\t\t\ttitle: \"Multisensor Battery - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1463128674,\n\t\t\t\t\t\tlastLevel: 100\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684790\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1461244852,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"sensorBinary\",\n\t\t\t\t\th: 1129728498,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_2-0-156-0-A\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: \"alarm\",\n\t\t\t\t\t\tlevel: \"on\",\n\t\t\t\t\t\ttitle: \"Motion Alarm - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1462367037,\n\t\t\t\t\t\tlastLevel: \"on\"\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"alarmSensor_general_purpose\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684790\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1463037018,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\t\th: -1332622515,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_18-0-49-1\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: \"Temperature\",\n\t\t\t\t\t\tscaleTitle: \"°C\",\n\t\t\t\t\t\tlevel: 25,\n\t\t\t\t\t\ticon: \"temperature\",\n\t\t\t\t\t\ttitle: \"Temperature - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1463116879,\n\t\t\t\t\t\tlastLevel: 25\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"temperature\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684791\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1463037018,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\th: -1503060958,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_18-0-64\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: \"thermostat\",\n\t\t\t\t\t\ttitle: \"Thermostat operation - Living Room\",\n\t\t\t\t\t\tlevel: \"on\",\n\t\t\t\t\t\tmodificationTime: 1463037070,\n\t\t\t\t\t\tlastLevel: \"on\"\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"thermostat_mode\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684791\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1463037019,\n\t\t\t\t\tcreatorId: 29,\n\t\t\t\t\tdeviceType: \"thermostat\",\n\t\t\t\t\th: -1332564855,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"ZWayVDev_zway_18-0-67-1\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tscaleTitle: \"°C\",\n\t\t\t\t\t\tlevel: 23.5,\n\t\t\t\t\t\tmin: 5,\n\t\t\t\t\t\tmax: 40,\n\t\t\t\t\t\ticon: \"thermostat\",\n\t\t\t\t\t\ttitle: \"Thermostat - Living Room\",\n\t\t\t\t\t\tmodificationTime: 1463037973,\n\t\t\t\t\t\tlastLevel: 23.5\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"thermostat_set_point\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464684791\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1460715630,\n\t\t\t\t\tcreatorId: 21,\n\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\th: 1606285100,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"Sonos_Device_Play_192.168.10.205_21\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ttitle: \"Sonos Play - Living Room\",\n\t\t\t\t\t\ticon: \"\",\n\t\t\t\t\t\tlevel: \"off\",\n\t\t\t\t\t\tmodificationTime: 1464619055,\n\t\t\t\t\t\tlastLevel: \"off\"\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464760397\n\t\t\t\t}, {\n\t\t\t\t\tcreationTime: 1460715630,\n\t\t\t\t\tcreatorId: 21,\n\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\th: 1810681234,\n\t\t\t\t\thasHistory: false,\n\t\t\t\t\tid: \"Sonos_Device_Volume_192.168.10.205_21\",\n\t\t\t\t\tlocation: 2,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ttitle: \"Sonos Volume - Living Room\",\n\t\t\t\t\t\ticon: \"\",\n\t\t\t\t\t\tlevel: 9,\n\t\t\t\t\t\tmodificationTime: 1463640278,\n\t\t\t\t\t\tlastLevel: 9\n\t\t\t\t\t},\n\t\t\t\t\tpermanently_hidden: false,\n\t\t\t\t\tprobeType: \"\",\n\t\t\t\t\ttags: [],\n\t\t\t\t\tvisibility: true,\n\t\t\t\t\tupdateTime: 1464760397\n\t\t\t\t}]\n\t\t\t},\n\t\t\tcode: 200,\n\t\t\tmessage: \"200 OK\",\n\t\t\terror: null\n\t\t}\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"updateTime\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"structureChanged\": {\n\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"devices\": {\n\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\n## Virtual Device [/v1/devices/{id}]\nA single virtual device object with all its details.\n\n## Virtual Device Attributes\n\n| Virtual Device Attribute\t  | Type\t\t\t\t\t\t| Comment\t\t\t\t\t\t\t\t\t  |\t  \n|-----------------------|-----------------------------|----------------------------------------------|\n| `id`\t\t\t\t  | _immutable_ (string, uniq)  | unique identifier |\n| `deviceType`\t\t  | _immutable_ (string)\t\t| major categorization of virtual device types, example _switchBinary_, _thermostat_, _sensorMultilevel_ etc.|\n| `updateTime`\t\t  | _immutable_ (integer)\t   | timestamp of last update|\n| `metrics`\t\t\t | (object)\t\t\t\t\t| device parameters |\n| `metrics.probeTitle`  | (string)\t\t\t\t\t| title of probe, example: _Temperature_ |\n| `metrics.scaleTitle`  | (string)\t\t\t\t\t| title of scale, example: _%_, _LUX_, _°C_ etc. |\n| `metrics.level`\t   | (string or integer)\t\t | level, example: _5_, _21.4_, _on/off_, _ALARM_ etc. |\n| `metrics.icon`\t\t| (string)\t\t\t\t\t| custom icon field, example: _uri, icon type_ |\n| `metrics.title`\t   | (string)\t\t\t\t\t| current title, example: _Temperature Door - Living Room_ |\n| `creationTime`\t\t| (integer)\t\t\t\t   | creation time timestamp |\n| `creatorId`\t\t   | (integer)\t\t\t\t   | id of instance that has created the virtual device (Z-Way devices usually will be created from ZWave instance) |\n| `hasHistory`\t\t  | (boolean)\t\t\t\t   | virtual device has a history |\n| `permanently_hidden`  | (boolean)\t\t\t\t   | virtual device is pemanently hidden (inactive) - not usable in apps etc. |\n| `probeType`\t\t   | _immutable_ (string)\t\t| type of probe for deeper categorization, example: _temperature_ |\n| `visibility`\t\t  | (boolean)\t\t\t\t   | hide virtual device in view (e.g. elements view) |\n| `tags`\t\t\t\t| (array)\t\t\t\t\t | list of tags assigned to virtual device |\n\n## Virtual Device Types\n\n| deviceType\t\t\t\t\t\t|Metrics\t\t\t\t   | Commands\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  | Examples\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t|\n|-----------------------------------|----------------------|-----------------------------------------------------------------------------------------------|-----------------------------------------------|\n| battery\t\t\t\t\t\t   | probeTitle,scaleTitle, level, icon, title | -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |-\t\t\t\t\t\t\t\t\t\t\t  |\n| doorlock\t\t\t\t\t\t  | level, icon, title |**_open_** or **_close_**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |apiURL/devices/:deviceId/command/open\t\t  |\n| thermostat\t\t\t\t\t\t| scaleTitle, min, max, level, icon, title |**_exact_** with get-param **_level_**\t\t\t\t\t\t\t\t\t\t  |apiURL/devices/:deviceId/command/exact?level=22.5|\n| switchBinary (Thermostat)\t\t | level, icon, title | **_on_**, **_off_** or **_update_**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  |apiURL/devices/:deviceId/command/on\t\t\t|\n| switchBinary\t\t\t\t\t  | level, icon, title | **_on_**, **_off_** or **_update_**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  |apiURL/devices/:deviceId/command/on\t\t\t|\n| switchMultilevel\t\t\t\t  | level, icon, title | **_on_** Set(255), **_off_** Set(0), **_min_** Set(10), **_max_** Set(99), **_increase_** Set(l+10), **_decrease_** Set(l-10), **_update_**, **_exact_** + get params **_level_**\t\t|apiURL/devices/:deviceId/command/exact?level=40|\n| switchMultilevel (Blinds)\t\t | level, icon, title | **_up_** Set(255), **_down_** Set(0), **_upMax_** Set(99), **_increase_** Set(l+10), **_decrease_** Set(l-10), **_startUp_** StartLevelChange(0), **_startDown_** StartLevelChange(1), **_stop_** StopLevelChange(), **_update_**, **_excactSmooth_** + get params **_level_**   |apiURL/devices/:deviceId/command/stop|\n| sensorBinary\t\t\t\t\t  | probeTitle, level, icon, title | **_update_**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |apiURL/devices/:deviceId/command/update\t\t|\n| sensorMultilevel\t\t\t\t  | probeTitle, scaleTitle, level, icon, title | **_update_**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |apiURL/devices/:deviceId/command/update\t\t|\n| toggleButton\t\t\t\t\t  | level, icon, title | **_on_**\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t |apiURL/devices/:deviceId/command/on\t\t\t|\n| camera\t\t\t\t\t\t\t| icon, title\t\t| depends on installed camera - could be: **_zoomIn_**, **_zoomOut_**, **_up_**, **_down_**, **_left_**, **_right_**, **_close_**, **_open_** | apiURL/devices/:deviceId/zoomIn |\n| switchControl\t\t\t\t\t | level, icon, title, change | **_on_**, **_off_**, **_upstart_**, **_upstop_**, **_downstart_**, **_downstop_**, **_exact_** with get-param **_level_**\t| apiURL/devices/:deviceId/command/on |\n| text\t\t\t\t\t\t\t  | title, text, icon | - | - |\n| sensorMultiline\t\t\t\t   | multilineType, title, icon, level, (scaleTitle, ...) | depends on apps | apiURL/devices/:deviceId/command/:cmd |\n| switchRGB\t\t\t\t\t\t | icon, title, color: {r:255,g:255,b:255}, level  | **_on_**, **_off_**, **_exact_** with get-params: **_red_**, **_green_** and **_blue_** | apiURL/devices/:deviceId/command/exact?red=20&green=240&blue=0 | \n\n## Probe Types (Z-Way)\n\n| Command Class\t\t\t\t\t |Probe Types\t\t\t\t| Sensor ID | Parent deviceType\t\t |\n|-----------------------------------|---------------------------|-----------|---------------------------|\n| ThermostatSetPoint\t\t\t\t| `thermostat_set_point`\t| -\t\t | thermostat\t\t\t\t|\n| ThermostatMode\t\t\t\t\t| `thermostat_mode`\t\t | -\t\t | switchBinary\t\t\t  |\n| SwitchMultilevel\t\t\t\t  | `multiLevel` <br> `motor` | default <br> 3,5,6,7 | switchMultilevel |\n| SwitchColor (virtual device with RGB panel) | `switchColor_rgb` | - | switchRGB |\n| SwitchColor\t\t\t\t\t   | `switchColor_soft_white` <br> `switchColor_cold_white` <br> `switchColor_red` <br> `switchColor_green` <br> `switchColor_blue` | 0 <br> 1 <br> 2 <br> 3 <br> 4 | switchMultilevel |\n| SensorBinary\t\t\t\t\t  | `general_purpose` <br> `smoke` <br> `co` <br> `flood` <br> `cooling` <br> `tamper` <br> `door-window` <br> `motion` | default <br> 2 <br> 3,4 <br> 6 <br> 7 <br> 8 <br> 10 <br> 12 | sensorBinary |\n| SensorMultilevel\t\t\t\t  | `temperature` <br> `luminosity` <br> `energy` <br> `humidity` <br> `barometer` <br> `ultraviolet`| 1 <br> 3  <br> 4,15,16 <br> 5 <br> 9 <br> 27 | sensorMultilevel |\n| Meter\t\t\t\t\t\t\t | `meterElectric_kilowatt_per_hour` <br> `meterElectric_watt` <br> `meterElectric_pulse_count` <br> `meterElectric_voltage` <br> `meterElectric_ampere` <br> `meterElectric_power_factor` | 0 <br> 2 <br> 3 <br> 4 <br> 5 <br> 6 | sensorMultilevel |\n| Alarm\t\t\t\t\t\t\t | `alarm_general_purpose` <br> `alarm_smoke` <br> `alarm_co` <br> `alarm_coo` <br> `alarm_heat` <br> `alarm_flood` <br> `alarm_door` <br> `alarm_burglar` <br> `alarm_power` <br> `alarm_system` <br> `alarm_emergency` <br> `alarm_clock` | 0 <br> 1 <br> 2 <br> 3 <br> 4 <br> 5 <br> 6 <br> 7 <br> 8 <br> 9 <br> 10 <br> 11 | sensorBinary |\n| AlarmSensor\t\t\t\t\t   | `alarmSensor_general_purpose` <br> `alarmSensor_smoke` <br> `alarmSensor_co` <br> `alarmSensor_coo` <br> `alarmSensor_heat` <br> `alarmSensor_flood` <br> `alarmSensor_door` <br> `alarmSensor_burglar` <br> `alarmSensor_power` <br> `alarmSensor_system` <br> `alarmSensor_emergency` <br> `alarmSensor_clock` | 0 <br> 1 <br> 2 <br> 3 <br> 4 <br> 5 <br> 6 <br> 7 <br> 8 <br> 9 <br> 10 <br> 11 | sensorBinary |\n\nProbe Types are used to allow deeper categorizations in the Namespaces API. If a virtual device has no probeType then the parameter will be empty `''`. You can also use probeType in your apps to differentiate between your virtual devices generated by them.\t \n\n## Icon Types\n\n**icon** attribute of **metrics** object may be:\n\n| Icon Attribute\t\t\t\t\t\t\t\t   |Comment\n|--------------------------------------------------|--------------------------------------------|\n| `''`\t\t\t\t\t\t\t\t\t\t\t | none|\n| `url(uri)`\t\t\t\t\t\t\t\t\t   | URL, example: http://image.com/image.png .|\n| `relative url string`\t\t\t\t\t\t\t| use home automation api to show pictures from app htdocs folder, example: `apiURL/modulemedia/:module_name/:file_name`|\n| `switch`\t\t\t\t\t\t\t\t\t\t | for **switchBinary** deviceType.|\n| `multilevel`, `blinds`\t\t\t\t\t\t   | for **switchMultilevel** deviceType.|\n| `smoke`, `co`, `cooling`, `door`, `motion`, `flood`, `alarm`, `window`\t | for **sensorBinary** deviceType.|\n| `temperature`, `luminosity`, `energy`, `humidity`, `ultraviolet`, `barometer`   | for **sensorMultilevel** deviceType.|\n| `battery`\t\t\t\t\t\t\t\t\t\t| for **battery** deviceType.|\n| `thermostat`\t\t\t\t\t\t\t\t\t | for **thermostat** deviceType.|\n| `meter`\t\t\t\t\t\t\t\t\t\t  | for **meter** deviceType.|\n| `door`\t\t\t\t\t\t\t\t\t\t   | for **doorlock** deviceType.|\n| `doorlockcontrol`\t\t\t\t\t\t\t\t| for **doorlock** deviceType.|\n| `camera`\t\t\t\t\t\t\t\t\t\t | for **camera** deviceType.|\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the Device to perform action with.\n\n### READ [GET]\n\nRetrieve a virtual device\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t{\n\t\t\t\"data\": {\n\t\t\t\t\"creationTime\": 1464779507,\n\t\t\t\t\"creatorId\": 34,\n\t\t\t\t\"deviceType\": \"sensorMultilevel\",\n\t\t\t\t\"h\": 1303283138,\n\t\t\t\t\"hasHistory\": false,\n\t\t\t\t\"id\": \"ZWayVDev_zway_2-0-49-3\",\n\t\t\t\t\"location\": 0,\n\t\t\t\t\"metrics\": {\n\t\t\t\t\t\"probeTitle\": \"Luminiscence\",\n\t\t\t\t\t\"scaleTitle\": \"Lux\",\n\t\t\t\t\t\"level\": 130,\n\t\t\t\t\t\"icon\": \"luminosity\",\n\t\t\t\t\t\"title\": \"Luminiscence - Living Room\",\n\t\t\t\t\t\"modificationTime\": 1464779507,\n\t\t\t\t\t\"lastLevel\": 130\n\t\t\t\t},\n\t\t\t\t\"permanently_hidden\": false,\n\t\t\t\t\"probeType\": \"luminosity\",\n\t\t\t\t\"tags\": [],\n\t\t\t\t\"visibility\": true,\n\t\t\t\t\"updateTime\": 1464779507\n\t\t\t},\n\t\t\t\"code\": 200,\n\t\t\t\"message\": \"200 OK\",\n\t\t\t\"error\": null\n\t\t}\n\n   + Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"creationTime\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"creatorId\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"deviceType\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"hasHistory\": {\n\t\t\t\t\t\t\t\t\"type\": \"bolean\"\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"location\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"metrics\": {\n\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"permanently_hidden\": {\n\t\t\t\t\t\t\t\t\"type\": \"boolean\"\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"probeType\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"tags\": {\n\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"visibility\": {\n\t\t\t\t\t\t\t\t\"type\": \"boolean\"\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"updateTime\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\"\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n### UPDATE [PUT]\n\nUpdate a virtual device\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the Device to perform action with.\n\n+ Request (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\t\"creationTime\": 1464779507,\n\t\t\t\t\"creatorId\": 34,\n\t\t\t\t\"deviceType\": \"sensorMultilevel\",\n\t\t\t\t\"h\": 1303283138,\n\t\t\t\t\"hasHistory\": false,\n\t\t\t\t\"id\": \"ZWayVDev_zway_2-0-49-3\",\n\t\t\t\t\"location\": 0,\n\t\t\t\t\"metrics\": {\n\t\t\t\t\t\"probeTitle\": \"Luminiscence\",\n\t\t\t\t\t\"scaleTitle\": \"Lux\",\n\t\t\t\t\t\"level\": 130,\n\t\t\t\t\t\"icon\": \"luminosity\",\n\t\t\t\t\t\"title\": \"Luminiscence - Living Room\",\n\t\t\t\t\t\"modificationTime\": 1464779507,\n\t\t\t\t\t\"lastLevel\": 130\n\t\t\t\t},\n\t\t\t\t\"permanently_hidden\": false,\n\t\t\t\t\"probeType\": \"luminosity\",\n\t\t\t\t\"tags\": [],\n\t\t\t\t\"visibility\": true,\n\t\t\t\t\"updateTime\": 1464779507\n\t\t\t}\n\t\t\t\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\"data\": {\n\t\t\t\t\"creationTime\": 1464779507,\n\t\t\t\t\"creatorId\": 34,\n\t\t\t\t\"deviceType\": \"sensorMultilevel\",\n\t\t\t\t\"h\": 1303283138,\n\t\t\t\t\"hasHistory\": false,\n\t\t\t\t\"id\": \"ZWayVDev_zway_2-0-49-3\",\n\t\t\t\t\"location\": 0,\n\t\t\t\t\"metrics\": {\n\t\t\t\t\t\"probeTitle\": \"Luminiscence\",\n\t\t\t\t\t\"scaleTitle\": \"Lux\",\n\t\t\t\t\t\"level\": 130,\n\t\t\t\t\t\"icon\": \"luminosity\",\n\t\t\t\t\t\"title\": \"Luminiscence - Living Room\",\n\t\t\t\t\t\"modificationTime\": 1464779507,\n\t\t\t\t\t\"lastLevel\": 130\n\t\t\t\t},\n\t\t\t\t\"permanently_hidden\": false,\n\t\t\t\t\"probeType\": \"luminosity\",\n\t\t\t\t\"tags\": [],\n\t\t\t\t\"visibility\": true,\n\t\t\t\t\"updateTime\": 1464779507\n\t\t\t},\n\t\t\t\"code\": 200,\n\t\t\t\"message\": \"200 OK\",\n\t\t\t\"error\": null\n\t\t}\n\t\t\n+ Response 404 (application/json)\n\n\t+ Body\n\t\n\t\t{\n\t\t\tdata: null,\n\t\t\tcode: 404,\n\t\t\tmessage: \"404 Not found\",\n\t\t\terror: \"Device :id doesn't exist\"\n\t\t}\n\n## Devices Commands [/v1/devices/{id}/command/{command}{?params}]\n### Send Command to Device [GET]\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\t\"data\": null,\n\t\t\t\t\"code\": 200,\n\t\t\t\t\"message\": \"200 OK\",\n\t\t\t\t\"error\": null\n\t\t\t}\n\n# Group Locations\nLocations related resources of the **Locations API**\n\n## Locations Collection [/v1/locations]\n### List all Locations [GET]\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\t\"data\":[\n\t\t\t\t\t{\"id\":6,\"title\":\"Garage\"},\n\t\t\t\t\t{\"id\":7,\"title\":\"Hall\"},\n\t\t\t\t\t{\"id\":8,\"title\":\"Kids\"},\n\t\t\t\t\t{\"id\":9,\"title\":\"Kitchen\"},\n\t\t\t\t\t{\"id\":10,\"title\":\"Bedroom\"},\n\t\t\t\t\t{\"id\":11,\"title\":\"name123\"},\n\t\t\t\t\t{\"id\":12,\"title\":\"test\"}\n\t\t\t\t],\n\t\t\t\t\"error\": null,\n\t\t\t\t\"code\": \"200 OK\",\n\t\t\t\t\"message\" null,\n\t\t\t}\n\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\n### CREATE [POST]\n\nCreate a Location\n\n+ Request (application/json)\n\t\n\t+ Body\n\t\n\t\t\t{ \"title\": \"Garage\", \"icon\": \"http://example.com/garage.png\" }\n\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"icon\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n+ Parameters\n\t+ title (required, string, `Garage`) ... `title` of the location.\n\t+ icon (optional, string, `http://example.com/garage.png`) ... `icon` of the location.\n\n+ Response 201 (application/json)\n\n\t+ Body \n\t\t\n\t\t\t{ \"id\": 1, \"title\": \"Garage\", \"icon\": \"http://example.com/garage.png\" }\n\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"icon\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n## Location [/v1/locations/{id}]\nA single Location object with all its details\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the Location to perform action with.\n\n### READ [GET]\n\nRetrieve a Location\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{ \"id\": 2, \"title\": \"Pick-up posters from post-office\" }\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"icon\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n### UPDATE [PUT]\n\nUpdate a Location\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{ \"id\": 2, \"title\": \"Pick-up posters from post-office\" }\n\t\t\t\n\t+ Schema\n\n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"icon\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n### DELETE [DELETE]\n\nRemove a Location\n\n+ Response 204\n\n# Group Profiles\nProfiles related resources of the **Profiles API**\n\n## Profiles Collection [/v1/profiles]\n### List all Profiles [GET]\n\n+ Response 200 (application/json)\n\n\t\t[{\n\t\t\t\"data\":[\n\t\t\t\t\"{\"id\":1,\"name\":\"Default\",\"description\":\"This is default profile. Default profile created automatically.\",\"widgets\":[],\"active\":true}\",\n\t\t\t],\n\t\t\t\"error\": null,\n\t\t\t\"message\": null,\n\t\t\t\"code\": \"200 OK\"\n\t\t}]\n\t\t\n### CREATE [POST]\n\nCreate a Profile\n\n+ Request (application/json)\n   \n\t\t+ Body\n\t\t\n\t\t\t\t{ \"name\": \"Default\", \"description\": \"descriptions\", \"active\": false, \"positions\": []}\n\t\t\n\t\t+ Schema \n\t\t\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"description\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"positions\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"active\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\n+ Response 201 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\t\"data\":[\n\t\t\t\t\t\"{\"id\":1,\"name\":\"Default\",\"description\":\"This is default profile. Default profile created automatically.\",\"widgets\":[],\"active\":true}\",\n\t\t\t\t],\n\t\t\t\t\"error\": null,\n\t\t\t\t\"message\": null,\n\t\t\t\t\"code\": \"200 OK\"\n\t\t\t}\n\n## Profile [/v1/profiles/{id}]\nA single Profile object with all its details\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the Profile to perform action with.\n\t+ name (required, string, `Default`) ... `name` of the profile.\n\t+ description (optional, string, `description`) ... `description` of the profile.\n\t+ active (optional, boolean, `false`) ... `profile is activated`.\n\t+ positions (required, array, `[deviceId1, deviceId2]`) ... `show and sortable on dashboard`.\n\n### READ [GET]\n\nRetrieve a Profile\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\t\"data\":[\n\t\t\t\t\t{\"id\":1,\"name\":\"Default\",\"description\":\"This is default profile. Default profile created automatically.\",\"positions\":[],\"active\":true},\n\t\t\t\t],\n\t\t\t\t\"error\": null,\n\t\t\t\t\"message\": null,\n\t\t\t\t\"code\": \"200 OK\"\n\t\t\t}\n\t\t\t\n\t+ Schema\n\t \n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"id\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"positions\": {\n\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"active\": {\n\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n### Update a Profile [PUT]\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the Profile to perform action with.\n\t+ name (required, string, `Default`) ... `name` of the profile.\n\t+ description (optional, string, `description`) ... `description` of the profile.\n\t+ active (optional, boolean, `false`) ... `profile is activated`.\n\t+ positions (required, array, `[deviceId1, deviceId2]`) ... `show and sortable on dashboard`.\n\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\t\"data\":[\n\t\t\t\t\t\"{\"id\":1,\"name\":\"Default\",\"description\":\"This is default profile. Default profile created automatically.\",\"widgets\":[],\"active\":true}\",\n\t\t\t\t],\n\t\t\t\t\"error\": null,\n\t\t\t\t\"message\": null,\n\t\t\t\t\"code\": \"200 OK\"\n\t\t\t}\n\n\t+ Schema\n\t \n\t\t\t{\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"error\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"data\"\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"title\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"description\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"positions\": {\n\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"active\": {\n\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"code\": {\n\t\t\t\t\t\t\"type\": [\"integer\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": [\"string\", \"null\"],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t}\n\n### Remove a Profile [DELETE]\n+ Response 204\n\n# Group Notifications\nLocations related resources of the **Notifications API**\n\n## Notifications Collection [/v1/notifications{?since}]\n\n### List all Notification  [GET]\n\n+ Parameters\n\t+ redeemed = `false` (optional, boolean, `?redeemed=true`) ... if `redeemed` eq true - include redeemed notifications\n\t+ since (optional, integer, `?since=1387881635`) ... `updateTime` of the Notifications.\n\n+ Response 200 (application/json)\n\n\t+ Body\n\t\n\t\t\t{\"error\":null,\n\t\t\t  \"data\":{\n\t\t\t\t\"updateTime\":1387884437,\n\t\t\t\t\"notifications\":[\n\t\t\t\t  {\"id\":\"1387199352223\",\"timestamp\":\"2013-12-16T13:09:12.223Z\",\"level\":\"error\",\"message\":\"Cannot remove location 54545 - doesn't exist\",\"redeemed\":true},\n\t\t\t\t  {\"id\":\"1387200419730\",\"timestamp\":\"2013-12-16T13:26:59.730Z\",\"level\":\"error\",\"message\":\"Cannot remove location 54545 - doesn't exist\",\"redeemed\":true}\n\t\t\t\t]\n\t\t\t  }\n\t\t\t}\t\t\n\t\t\n## Notification [/v1/notifications/{id}]\nA single Notice object with all its details\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the notifications to perform action with.\n\n### Retrieve a Notification [GET]\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\"error\":null,\"data\":{\"id\":1387202340396,\"timestamp\":\"2013-12-16T13:59:00.396Z\",\"level\":\"error\",\"message\":\"Cannot remove location 54545 - doesn't exist\",\"redeemed\":true}}\n\n### Update a Notification [PUT]\n\n+ Parameters\n\t+ id (required, integer, `1`) ... Numeric `id` of the Notification to perform action with.\n\n+ Request (application/json)\n\n\t+ Body\n\n\t\t\t{\"id\":1387202340396,\"timestamp\":\"2013-12-16T13:59:00.396Z\",\"level\":\"error\",\"message\":\"Cannot remove location 54545 - doesn't exist\",\"redeemed\":true}\n\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\"error\":null,\"data\":{\"id\":1387202340396,\"timestamp\":\"2013-12-16T13:59:00.396Z\",\"level\":\"error\",\"message\":\"Cannot remove location 54545 - doesn't exist\",\"redeemed\":true}}\n\n# Group Device Histories\nDevice related resources of the **History API**\n\n## Histories Collection [/v1/history]\n\n### List all Device Histories  [GET]\n\n+ Response 200 (application/json)\n\n\t+ Body\n\t\n\t\t\t{\"error\":null,\n\t\t\t  \"data\":{\n\t\t\t\t\"updateTime\":1387884437,\n\t\t\t\t\"history\":[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"ZWayVDev_zway_3-0-48-1\",\n\t\t\t\t\t\t\t\"dT\": \"sensorBinary\",\n\t\t\t\t\t\t\t\"mH\": [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"id\": 1424185598,\n\t\t\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T15:06:38.404Z\",\n\t\t\t\t\t\t\t\t\t\t\"l\": \"on\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"id\": 1424185662,\n\t\t\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T15:07:42.382Z\",\n\t\t\t\t\t\t\t\t\t\t\"l\": \"off\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t},{\n\t\t\t\t\t\t\t\"id\": \"ZWayVDev_zway_3-0-49-3\",\n\t\t\t\t\t\t\t\"dT\": \"sensorMultilevel\",\n\t\t\t\t\t\t\t\"mH\": [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"id\": 1424172352,\n\t\t\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T11:25:52.723Z\",\n\t\t\t\t\t\t\t\t\t\t\"l\": \"21\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"id\": 1424172382,\n\t\t\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T11:26:22.743Z\",\n\t\t\t\t\t\t\t\t\t\t\"l\": \"22\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t  }\n\t\t\t}\t\t\n\t\t\n## Device History [/v1/history/{id}{?since}]\nA single device history object with all its details\n\n+ Parameters\n\t+ id (optional, string, `/ZWayVDev_zway_3-0-48-1`) ... Device `id` of the device to perform action with.\n\t+ since (optional, integer, `?since=1424186368`) ... `updateTime` of the metrics change.\n\n### Retrieve a single Device History [GET]\n+ Response 200 (application/json)\n\n\t+ Body\n\n\t\t\t{\n\t\t\t\"data\": {\n\t\t\t\t\"id\": \"ZWayVDev_zway_3-0-48-1\",\n\t\t\t\t\"since\": 1424186368,\n\t\t\t\t\"deviceHistory\": [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"id\": 1424186368,\n\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T15:19:28.698Z\",\n\t\t\t\t\t\t\t\t\"l\": \"off\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"id\": 1424186396,\n\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T15:19:56.806Z\",\n\t\t\t\t\t\t\t\t\"l\": \"on\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"id\": 1424186427,\n\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T15:20:27.238Z\",\n\t\t\t\t\t\t\t\t\"l\": \"off\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"id\": 1424187453,\n\t\t\t\t\t\t\t\t\"t\": \"2015-02-17T15:37:33.410Z\",\n\t\t\t\t\t\t\t\t\"l\": \"on\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\"code\": 200,\n\t\t\t\"message\": \"200 OK\",\n\t\t\t\"error\": null\n\t\t\t}\n"
  },
  {
    "path": "classes/AuthController.js",
    "content": "/*** Automation Webserver Auth Controller *************************************\n\nVersion:\n-------------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nCopyright: (c) ZWave.Me, 2015\n\n******************************************************************************/\n'use strict';\n\nfunction AuthController (controller) {\n\t// available roles\n\tthis.ROLE = {\n\t\tADMIN: 1,\n\t\tUSER: 2,\n\t\tLOCAL: 3,\n\t\tANONYMOUS: 4\n\t};\n\n\tthis.forgottenPwdCollector = {};\n\t\n\t// link to controller to get profiles\n\tthis.controller = controller;\n}\n\nAuthController.prototype.isAuthorized = function(myRole, requiredRole) {\n\tif (!requiredRole) {\n\t\t// no role required, allow access\n\t\treturn true;\n\t}\n\n\treturn myRole <= requiredRole;\n}\n\nAuthController.prototype.getSessionId = function(request) {\n\t// check if session id is specified in cookie or header\n\tvar profileSID;\n\t\n\t// first try Authorization Bearer\n\tvar authHeader = request.headers['Authorization'];\n\tif (authHeader && authHeader.indexOf('Bearer ') === 0) {\n\t\tprofileSID = authHeader.substr('Bearer '.length).split('/')[1];\n\t\tif (profileSID) {\n\t\t\trequest.__authMethod = 'Authorization Bearer';\n\t\t\treturn profileSID;\n\t\t}\n\t}\n\t\n\t// second try ZWAYSession\n\tprofileSID = request.headers['ZWAYSession'];\n\tif (profileSID) {\n\t\trequest.__authMethod = 'ZWAYSession';\n\t\treturn profileSID;\n\t}\n\t\n\t// third try cookie\n\tvar cookiesHeader = request.headers['Cookie'];\n\tvar cookiesIgnore = !!request.headers['ZWAYSessionCookieIgnore'];\n\tif (cookiesHeader && !cookiesIgnore) {\n\t\tvar cookie = cookiesHeader.split(\";\").map(function(el) { return el.trim().split(\"=\"); }).filter(function(el) { return el[0] === \"ZWAYSession\" });\n\t\tif (!!cookie && !!cookie[0]) {\n\t\t\trequest.__authMethod = 'Cookie';\n\t\t\treturn cookie[0][1];\n\t\t}\n\t}\n\t\n\treturn '';\n}\n\nAuthController.prototype.resolve = function(request, requestedRole) {\n\tvar user, role, token, session,\n\t\tself = this;\n\n\tif (request.user && request.role && request.authToken) {\n\t\tuser = request.user;\n\t\trole = request.role;\n\t\ttoken = request.authToken;\n\t\t\n\t\tif ((role === this.ROLE.LOCAL || role === this.ROLE.ANONYMOUS) && requestedRole === this.ROLE.USER) {\n\t\t\trole = this.ROLE.USER;\n\t\t}\n\t} else {\n\t\tvar defaultProfile = _.filter(this.controller.profiles, function (profile) {\n\t\t\treturn profile.login === 'admin' && profile.password === 'admin';\n\t\t});\n\t\t\n\t\tvar noAnonymous = false;\n\t\t\n\t\tvar reqSession = self.getSessionId(request);\n\t\tif (reqSession) {\n\t\t\tnoAnonymous = true;\n\t\t\t\n\t\t\tvar removedExpired = false;\n\t\t\tsession = _.find(this.controller.profiles, function(profile) {\n\t\t\t\tvar _profile, toRemove = [];\n\t\t\t\t\n\t\t\t\t_profile = _.find(profile.authTokens, function(authToken) {\n\t\t\t\t\t// remove expired tokens\n\t\t\t\t\tif (authToken.expire > 0 && authToken.expire < Date.now()) {\n\t\t\t\t\t\ttoRemove.push(authToken.sid);\n\t\t\t\t\t\tremovedExpired = true;\n\t\t\t\t\t}\n\t\t\t\t\tif (authToken.sid == reqSession) {\n\t\t\t\t\t\t// make the Authorization Bearer always permanent\n\t\t\t\t\t\tif (authToken.expire != 0 && request.__authMethod == 'Authorization Bearer') {\n\t\t\t\t\t\t\tself.controller.permanentToken(profile, authToken.sid);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\t// Update last seen and IP\n\t\t\t\t\t\tauthToken.lastSeen = Date.now();\n\t\t\t\t\t\tauthToken.ip = self.getClientIP(request);\n\t\t\t\t\t\t\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\ttoRemove.forEach(function(token) {\n\t\t\t\t\tself.controller.removeToken(profile, token, true); // skip save\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\treturn _profile;\n\t\t\t});\n\t\t\tif (removedExpired) this.controller.saveConfig(false);\n\t\t}\n\n\t\tif (!session) {\n\t\t\t// no session found or session expired\n\n\t\t\t// try Basic auth\n\t\t\tvar authHeader = request.headers['Authorization'];\n\t\t\tif (authHeader && authHeader.substring(0, 6) === \"Basic \") {\n\t\t\t\tauthHeader = Base64.decode(authHeader.substring(6));\n\t\t\t\tif (authHeader) {\n\t\t\t\t\tnoAnonymous = true;\n\t\t\t\t\t\n\t\t\t\t\tvar authInfo = authHeader.split(':');\n\t\t\t\t\tif (authInfo.length === 2 && authInfo[0].length > 0) {\n\t\t\t\t\t\tvar profile = _.find(this.controller.profiles, function (profile) {\n\t\t\t\t\t\t\treturn profile.login === authInfo[0];\n\t\t\t\t\t\t});\n\t\t\t\t\t\n\t\t\t\t\t\tif (profile && (!profile.salt && profile.password === authInfo[1] || profile.salt && profile.password === hashPassword(authInfo[1], profile.salt))) {\n\t\t\t\t\t\t\t// auth successful, use selected profile\n\t\t\t\t\t\t\tsession = profile;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!session && requestedRole === this.ROLE.USER) {\n\t\t\t\t// try to find Local user account\n\t\t\t\tif (request.peer.address === \"127.0.0.1\" && defaultProfile.length < 1 && !this.controller.config.firstaccess) {\n\t\t\t\t\t// don't treat find.z-wave.me as local user (connection comes from local ssh server)\n\t\t\t\t\tif (!(request.headers['Cookie'] && request.headers['Cookie'].split(\";\").map(function(el) { return el.trim().split(\"=\"); }).filter(function(el) { return el[0] === \"ZBW_SESSID\" }))) {\n\t\t\t\t\t\t// TODO: cache this in future\n\t\t\t\t\t\tsession = _.find(this.controller.profiles, function (profile) {\n\t\t\t\t\t\t\treturn profile.role === self.ROLE.LOCAL;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// try to find Anonymous user account\n\t\t\t\tif (!session) {\n\t\t\t\t\t// TODO: cache this in future\n\t\t\t\t\tsession = _.find(this.controller.profiles, function (profile) {\n\t\t\t\t\t\treturn profile.role === self.ROLE.ANONYMOUS;\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!session) {\n\t\t\t\t// no session found, but requested role is anonymous - use dummy session.\n\t\t\t\tif (requestedRole === this.ROLE.ANONYMOUS && !noAnonymous) {\n\t\t\t\t\tsession = {\n\t\t\t\t\t\tid: -1, // non-existant ID\n\t\t\t\t\t\trole: this.ROLE.ANONYMOUS\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// change role type, if we found matching local/anonymous user (real user, not dummy with -1)\n\t\tif (session.id !== -1 && (session.role === this.ROLE.LOCAL || session.role === this.ROLE.ANONYMOUS)) {\n\t\t\trole = this.ROLE.USER;\n\t\t}\n\n\t\tuser = session.id;\n\t\t\n\t\tif (!role) {\n\t\t\trole = session.role;\n\t\t}\n\t\t\n\t\ttoken = reqSession.substr(0, 6);\n\t}\n\t\n\t// save in request fields for handling in API and to allow subsequent call of this function\n\trequest.user = user;\n\trequest.role = role;\n\trequest.authToken = token;\n\t\n\treturn {user: user, role: role, token: token};\n};\n\nAuthController.prototype.checkIn = function(profile, req, permanent) {\n\tvar sid;\n\t\n\t// generate a new sid\n\tdo {\n\t\tsid = crypto.guid();\n\t\t\n\t\t// and make sure it is unique (first 6 letters can be used to show to the user and to delete sid)\n\t\tvar found = _.find(this.controller.profiles, function(profile) {\n\t\t\t_.find(profile.authTokens, function(authToken) {\n\t\t\t\tauthToken.sid.substr(0, 6) == sid.substr(0, 6);\n\t\t\t});\n\t\t});\n\t\tif (!found) break;\n\t} while(true);\n\t\n\t// save user agent\n\tvar userAgent;\n\tif (req && req.headers && req.headers['User-Agent']) {\n\t\tuserAgent = req.headers['User-Agent'];\n\t}\n\t\n\t// save auth token in the profile\n\tif (!profile.authTokens) {\n\t\tprofile.authTokens = [];\n\t}\n\t\n\tvar TTL = 7 * 24 * 60 * 60 * 1000; // 1 week in ms\n\tvar d = Date.now();\n\t\n\tprofile.authTokens.push({\n\t\tsid: sid,\n\t\tagent: userAgent,\n\t\tdate: d,\n\t\tlastSeen: d,\n\t\tip: this.getClientIP(req),\n\t\texpire: permanent ? 0 : (d + TTL)\n\t});\n\t\n\tthis.controller.saveConfig(false);\n\t\n\treturn sid\n};\n\nAuthController.prototype.forgottenPwd = function(email, token) {\n\tvar self = this,\n\t\tsuccess = true,\n\t\tsetToken = function(){\n\t\t\tself.forgottenPwdCollector[token] = {\n\t\t\t\temail: email,\n\t\t\t\texpTime: Math.floor(Date.now() / 1000) + 600 // 10 min\n\t\t\t};\n\t\t};\n\n\tif (Object.keys(this.forgottenPwdCollector).length > 0) {\n\t\tObject.keys(this.forgottenPwdCollector).forEach(function(t){\n\t\t\tif (self.forgottenPwdCollector[t].email === email) {\n\t\t\t\tsuccess = false;\n\t\t\t}\n\t\t});\n\t\tif (success) {\n\t\t\tsetToken();\n\t\t}\n\t} else {\n\t\tsetToken();\n\t}\n\n\tif (!this.expireTokens) {\n\t\tthis.expireTokens = setInterval(function() {\n\t\t\tvar expirationTime = Math.floor(Date.now() / 1000);\n\t\t\t\n\t\t\tObject.keys(self.forgottenPwdCollector).forEach(function(tkn) {\n\t\t\t\tif (self.forgottenPwdCollector[tkn].expTime < expirationTime) {\n\t\t\t\t\tself.removeForgottenPwdEntry(tkn);\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\tif (Object.keys(self.forgottenPwdCollector).length < 1 && self.expireTokens) {\n\t\t\t\tclearInterval(self.expireTokens);\n\t\t\t\tself.expireTokens = null;\n\t\t\t}\n\t\t}, 60 * 1000); // check each minute\n\t}\n\n\treturn success;\n};\n\nAuthController.prototype.removeForgottenPwdEntry = function(token) {\n\tif (this.forgottenPwdCollector[token]){\n\t\tdelete this.forgottenPwdCollector[token];\n\t}\n};\n\nAuthController.prototype.getForgottenPwdToken = function(token) {\n\tvar result = null;\n\n\tif (this.forgottenPwdCollector[token]){\n\t\tresult = this.forgottenPwdCollector[token];\n\t}\n\n\treturn result;\n};\n\nAuthController.prototype.getClientIP = function(request) {\n\tvar ip = request.peer.address;\n\t\n\tif (request.peer.address === \"127.0.0.1\") {\n\t\t// don't treat find.z-wave.me as local user (connection comes from local ssh server)\n\t\tif (request.headers['Cookie'] && request.headers['Cookie'].split(\";\").map(function(el) { return el.trim().split(\"=\"); }).filter(function(el) { return el[0] === \"ZBW_SESSID\" }) && request.headers['X-Forwarded-For']) {\n\t\t\tip = request.headers['X-Forwarded-For'].split(\",\")[0].trim();\n\t\t}\n\t}\n\t\n\treturn ip;\n};\n"
  },
  {
    "path": "classes/AutomationController.js",
    "content": "/*** Z-Way HA Controller class module *****************************************\n\n Version: 1.0.0\n -------------------------------------------------------------------------------\n Author: Gregory Sitnin <sitnin@z-wave.me>\n Copyright: (c) ZWave.Me, 2013\n\n ******************************************************************************/\n\nfunction AutomationController() {\n\tAutomationController.super_.call(this);\n\n\n\tthis.savePeriod = 60; // save objects and notifications period (in seconds): increase for slow SD cards\n\t\n\tthis.config = config.controller || {};\n\tthis.debug = false;\n\tthis.availableLang = ['en', 'ru', 'de', 'sk', 'cz', 'se', 'fr', 'es']; // will be updated by correct ISO language codes in future\n\tthis.defaultLang = 'en';\n\tthis.profiles = config.profiles;\n\tthis.instances = config.instances;\n\tthis.locations = config.locations || [];\n\tthis.vdevInfo = config.vdevInfo || {};\n\tthis.modules_categories = fs.loadJSON('modulesCategories.json') || [];\n\tthis.namespaces = namespaces || [];\n\tthis.registerInstances = {};\n\tthis.files = files || {};\n\n\tthis.modules = {};\n\tthis.devices = new DevicesCollection(this);\n\n\tthis.notifications = [];\n\tthis.lastStructureChangeTime = 0;\n\t\n\tthis.notificationChannels = {};\n\n\tthis._loadedSingletons = [];\n\n\tthis.auth = new AuthController(this);\n\tthis.skins = loadObject('userSkins.json') || [{\n\t\tname: \"default\",\n\t\ttitle: \"Default\",\n\t\tdescription: \"Default skin\",\n\t\tversion: \"1.0.0\",\n\t\ticon: true,\n\t\tauthor: \"Z-Wave.Me\",\n\t\thomepage: \"https://www.z-wave.me\",\n\t\tactive: true\n\t}];\n\n\tthis.icons = loadObject('userIcons.json') || [];\n}\n\ninherits(AutomationController, EventEmitter2);\n\nfunction wrap(self, func) {\n\treturn function() {\n\t\tfunc.apply(self, arguments);\n\t};\n}\n\nAutomationController.prototype.init = function() {\n\tvar self = this;\n\n\n\tfunction pushNamespaces(device, locationNspcOnly) {\n\t\tself.generateNamespaces(function(namespaces) {\n\t\t\tws.push('me.z-wave.namespaces.update', namespaces, self.profilesByRole(self.auth.ROLE.ADMIN));\n\t\t}, device, locationNspcOnly);\n\t}\n\n\tself.loadModules(function() {\n\t\tself.emit(\"core.init\");\n\n\t\t// update device state\n\t\tself.devices.on('change:metrics:level', function(device) {\n\t\t\tws.push(\"me.z-wave.devices.level\", device.toJSON(), self.profilesByDevice(device.id));\n\t\t});\n\n\t\t// update namespaces if device title has changed\n\t\tself.devices.on('change:metrics:title', function(device) {\n\t\t\tws.push(\"me.z-wave.devices.title_update\", device.toJSON(), self.profilesByDevice(device.id));\n\t\t\tpushNamespaces(device, false);\n\t\t});\n\n\t\t// update only location namespaces if device location has changed\n\t\tself.devices.on('change:location', function(device) {\n\t\t\tws.push(\"me.z-wave.devices.location_update\", device.toJSON(), self.profilesByRole(self.auth.ROLE.ADMIN));\n\t\t\tpushNamespaces(device, true);\n\t\t\tvar id = device.get('id');\n\t\t\tlocationId = device.get('location'),\n\t\t\t\torder = device.get('order'),\n\t\t\t\tcount = 0;\n\n\t\t\tself.devices.forEach(function(dev) {\n\t\t\t\tif (dev.get('location') == locationId) {\n\t\t\t\t\tcount++;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\torder.room = (count - 1);\n\t\t\tdevice.set('order', order);\n\n\t\t\tvar location = _.find(self.locations, function(loc) {\n\t\t\t\tif (loc.id !== 0) {\n\t\t\t\t\tvar index = loc.main_sensors.indexOf(id);\n\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\treturn loc;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (location !== undefined && device.get('location') !== location.id) {\n\t\t\t\tlocation.main_sensors.splice(index, 1);\n\t\t\t\tself.updateLocation(location.id, location.title, location.user_img, location.default_img, location.img_type, location.show_background, location.main_sensors, function(data) {\n\t\t\t\t\tif (!data) {\n\t\t\t\t\t\tconsole.log(\"Error location not exists\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tdevice.set(\"locationName\", self.locationName(locationId));\n\t\t});\n\n\t\t// update namespaces if device permanently_hidden status has changed\n\t\tself.devices.on('change:permanently_hidden', function(device) {\n\t\t\tws.push(\"me.z-wave.devices.visibility_update\", device.toJSON(), self.profilesByDevice(device.id));\n\t\t\tpushNamespaces(device, false);\n\t\t});\n\n\t\t// update namespaces if device removed status has changed\n\t\tself.devices.on('change:metrics:removed', function(device) {\n\t\t\tws.push(\"me.z-wave.devices.visibility_update\", device.toJSON(), self.profilesByDevice(device.id));\n\t\t\tpushNamespaces(device, false);\n\t\t});\n\n\t\t// update namespaces if structure of devices collection changed\n\t\tself.devices.on('created', function(device) {\n\t\t\tws.push(\"me.z-wave.devices.add\", device.toJSON(), self.profilesByDevice(device.id));\n\t\t\tpushNamespaces(device);\n\t\t});\n\t\t\n\t\t// update namespaces if structure of devices collection changed\n\t\tself.devices.on('wipedOut', function(device_id) {\n\t\t\tws.push(\"me.z-wave.devices.wipe\", device_id, self.profilesByDevice(device_id));\n\t\t});\n\n\t\tself.devices.on('removed', function(device) {\n\t\t\tpushNamespaces(device);\n\n\t\t\tvar id = device.get('id');\n\t\t\tvar locationId = device.get('location');\n\n\t\t\tif (locationId !== 0) {\n\t\t\t\tvar location = _.find(self.locations, function(location) {\n\t\t\t\t\treturn location.id === locationId;\n\t\t\t\t});\n\n\t\t\t\tif (typeof location !== 'undefined') {\n\t\t\t\t\tif (location.hasOwnProperty(\"main_sensors\")) {\n\t\t\t\t\t\tvar index = location.main_sensors.indexOf(id);\n\t\t\t\t\t\tif (index > -1) {\n\t\t\t\t\t\t\tlocation.main_sensors.splice(index, 1);\n\t\t\t\t\t\t\tself.updateLocation(location.id, location.title, location.user_img, location.default_img, location.img_type, location.show_background, location.main_sensors, function(data) {\n\t\t\t\t\t\t\t\tif (!data) {\n\t\t\t\t\t\t\t\t\tconsole.log(\"Error location not exists\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tws.push(\"me.z-wave.devices.remove\", id, self.profilesByDevice(id));\n\t\t});\n\n\t\tself.on('location.added', function(location) {\n\t\t\tws.push(\"me.z-wave.locations.add\", location, self.profilesByLocation(location));\n\t\t});\n\t\t\n\t\tself.on('location.removed', function(location) {\n\t\t\tws.push(\"me.z-wave.locations.remove\", location, self.profilesByLocation(location));\n\t\t});\n\t\t\n\t\tself.on('location.updated', function(location) {\n\t\t\tws.push(\"me.z-wave.locations.updated\", location, self.profilesByLocation(location));\n\t\t});\n\t\t\n\t\tself.on('profile.updated', function(profile) {\n\t\t\tws.push(\"me.z-wave.profile.updated\", self.safeProfile(profile), self.profilesByRole(self.auth.ROLE.ADMIN).concat([profile.id]));\n\t\t});\n\t\t\n\t\tself.on(\"notifications.push\", function(notice) {\n\t\t\tws.push(\"me.z-wave.notifications.add\", notice, self.profilesByRole(self.auth.ROLE.ADMIN));\n\t\t});\n\t});\n};\n\nAutomationController.prototype.setDefaultLang = function(lang) {\n\tvar self = this,\n\t\toldLang = self.defaultLang;\n\n\tself.defaultLang = self.availableLang.indexOf(lang) === -1 ? 'en' : lang;\n\n\tif (self.defaultLang !== oldLang) {\n\t\tthis.emit('language.changed', self.defaultLang);\n\t}\n};\n\nAutomationController.prototype.saveConfig = function(immediate) {\n\n\t// do clean up of location namespaces\n\tcleanupLocations = function(locations) {\n\t\tvar newLoc = [];\n\n\t\tlocations.forEach(function(loc) {\n\t\t\tnewLoc.push(_.omit(loc, 'namespaces'));\n\t\t});\n\n\t\treturn newLoc;\n\t};\n\n\tvar cfgObject = {\n\t\t\"controller\": this.config,\n\t\t\"vdevInfo\": this.vdevInfo,\n\t\t\"locations\": cleanupLocations(this.locations),\n\t\t\"profiles\": this.profiles,\n\t\t\"instances\": this.instances\n\t};\n\n\ttry {\n\t\tsaveObject(\"config.json\", cfgObject, immediate);\n\t} catch (e) {\n\t\tconsole.log(\"Error: can not write back config to storage: \", e);\n\t}\n};\n\nAutomationController.prototype.saveFiles = function() {\n\tsaveObject(\"files.json\", this.files, true);\n};\n\nAutomationController.prototype.start = function(reload) {\n\tvar restore = restore || false;\n\n\t// if reload flag is true, overwrite config values first\n\tif (reload) {\n\t\tconsole.log(\"Reload config...\");\n\t\t// Reload config\n\t\tthis.reloadConfig();\n\t\tthis.skins = loadObject('userSkins.json') || [{\n\t\t\tname: \"default\",\n\t\t\ttitle: \"Default\",\n\t\t\tdescription: \"Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.\",\n\t\t\tversion: \"1.0.3\",\n\t\t\ticon: true,\n\t\t\tauthor: \"Martin Vach\",\n\t\t\thomepage: \"http://www.zwave.eu\",\n\t\t\tactive: true\n\t\t}];\n\t\tthis.icons = loadObject('userIcons.json') || [];\n\t}\n\n\t// Restore persistent data\n\tthis.loadNotifications();\n\n\t// Run all modules\n\tconsole.log(\"Loading modules...\");\n\tthis.instantiateModules();\n\n\tZAutomation = function() {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid ZAutomation request\"\n\t\t};\n\t};\n\tws.allowExternalAccess(\"ZAutomation\", this.auth.ROLE.ANONYMOUS);\n\n\t// Run webserver\n\tconsole.log(\"Starting automation...\");\n\tZAutomation.api = new ZAutomationAPIWebRequest(this).handlerFunc();\n\tws.allowExternalAccess(\"ZAutomation.api\", this.auth.ROLE.ANONYMOUS); // there would be additional auth check for each request\n\n\t// Run storage\n\tconsole.log(\"Starting storage...\");\n\tZAutomation.storage = new ZAutomationStorageWebRequest(this).handlerFunc();\n\tws.allowExternalAccess(\"ZAutomation.storage\", this.auth.ROLE.ANONYMOUS); // there would be additional auth check for each request\n\n\t// Notify core\n\tthis.emit(\"core.start\");\n};\n\nAutomationController.prototype.reloadConfig = function() {\n\tvar reloadedConfig = loadObject(\"config.json\");\n\n\t// overwrite variables with restored data\n\tthis.config = reloadedConfig.controller || config.controller;\n\tthis.profiles = reloadedConfig.profiles || config.profiles;\n\tthis.instances = reloadedConfig.instances || config.instances;\n\tthis.locations = reloadedConfig.locations || config.locations;\n\tthis.vdevInfo = reloadedConfig.vdevInfo || config.vdevInfo;\n};\n\nAutomationController.prototype.stop = function() {\n\tvar self = this,\n\t\tmodWithoutDep = [];\n\n\t// Remove API webserver\n\tconsole.log(\"Stopping automation...\");\n\tZAutomation = null;\n\n\tws.revokeExternalAccess(\"ZAutomation\");\n\tws.revokeExternalAccess(\"ZAutomation.api\");\n\tws.revokeExternalAccess(\"ZAutomation.storage\");\n\n\t// Clean instances\n\tconsole.log(\"Stopping instances with dependencies ...\");\n\tself.instances.forEach(function(instance) {\n\n\t\t// first stop instances with dependencies\n\t\tif (self.modules[instance.moduleId]) {\n\t\t\tif ((instance.active === true || instance.active === 'true') &&\n\t\t\t\t_.isArray(self.modules[instance.moduleId].meta.dependencies) &&\n\t\t\t\tself.modules[instance.moduleId].meta.dependencies.length > 0) {\n\t\t\t\tself.removeInstance(instance.id);\n\t\t\t} else if ((instance.active === true || instance.active === 'true')) {\n\t\t\t\tmodWithoutDep.push(instance.id)\n\t\t\t}\n\t\t}\n\t});\n\n\t// stop instances without dependencies at least\n\tif (modWithoutDep.length > 0) {\n\t\tconsole.log(\"Stopping all remaining instances ...\");\n\t\tmodWithoutDep.forEach(function(instanceId) {\n\t\t\tself.removeInstance(instanceId);\n\t\t})\n\t}\n\n\tthis._loadedSingletons = [];\n\n\t// save notifications on automation shut down\n\tthis.notifications.finalize();\n\tthis.notifications = null;\n\n\t// Notify core\n\tthis.emit(\"core.stop\");\n};\n\nAutomationController.prototype.restart = function() {\n\tthis.stop();\n\tthis.start();\n\n\tvar langFile = this.loadMainLang();\n\n\tthis.addNotification(\"warning\", langFile.ac_warn_restart, \"core\", \"AutomationController\");\n};\n\nAutomationController.prototype.loadModules = function(callback) {\n\tconsole.log(\"--- Loading ZAutomation classes\");\n\tvar self = this;\n\n\tfs.list(\"modules/\").forEach(function(moduleClassName) {\n\t\tself.loadModuleFromFolder(moduleClassName, \"modules/\");\n\t});\n\n\t(fs.list(\"userModules/\") || []).forEach(function(moduleClassName) {\n\t\tself.loadModuleFromFolder(moduleClassName, \"userModules/\");\n\t});\n\n\tif (typeof callback === 'function') {\n\t\tcallback();\n\t}\n};\n\nAutomationController.prototype.loadModuleFromFolder = function(moduleClassName, folder, ignoreVersion) {\n\tvar self = this,\n\t\tlangFile = self.loadMainLang(),\n\t\tvalues,\n\t\taddModule = false,\n\t\tignoreVersion = ignoreVersion ? ignoreVersion : false;\n\n\tvar moduleMetaFilename = folder + moduleClassName + \"/module.json\",\n\t\t_st;\n\n\t_st = fs.stat(folder + moduleClassName);\n\tif (_st && \"file\" === _st.type) {\n\t\treturn; // skip files in modules folders\n\t}\n\n\t_st = fs.stat(moduleMetaFilename);\n\n\tif (!_st || \"file\" !== _st.type || 2 > _st.size) {\n\t\tconsole.log(\"ERROR: Cannot read module metadata from\", moduleMetaFilename);\n\t\treturn;\n\t}\n\n\ttry {\n\t\tvar moduleMeta = fs.loadJSON(moduleMetaFilename);\n\t} catch (e) {\n\t\tvalues = moduleMetaFilename + \": \" + e.toString();\n\n\t\tself.addNotification(\"error\", langFile.ac_err_load_mod_json + values, \"core\", \"AutomationController\");\n\t\tconsole.log(e.stack);\n\t\treturn; // skip this modules\n\t}\n\tif (moduleMeta.hasOwnProperty(\"skip\"), !!moduleMeta[\"skip\"]) return;\n\n\tvar moduleFilename = folder + moduleClassName + \"/index.js\";\n\t_st = fs.stat(moduleFilename);\n\tif (\"file\" !== _st.type || 2 > _st.size) {\n\t\tconsole.log(\"ERROR: Cannot stat module\", moduleFilename);\n\t\treturn;\n\t}\n\n\tmoduleMeta.id = moduleClassName;\n\tmoduleMeta.location = folder + moduleClassName;\n\n\t// check version before overwriting the already existing module\n\tif (self.modules[moduleClassName] &&\n\t\tself.modules[moduleClassName].meta &&\n\t\tself.modules[moduleClassName].meta.version &&\n\t\tmoduleMeta.version) {\n\n\t\tvar existingVersion = self.modules[moduleClassName].meta.version.toString(),\n\t\t\tcurrentVersion = moduleMeta.version.toString();\n\n\t\tif (existingVersion.localeCompare(currentVersion) === 0 || ignoreVersion) {\n\t\t\taddModule = true;\n\t\t} else {\n\t\t\taddModule = has_higher_version(currentVersion, existingVersion);\n\t\t}\n\n\t} else {\n\t\taddModule = true;\n\t}\n\n\tif (addModule) {\n\t\t// Grab _module and clear it out\n\t\tself.modules[moduleClassName] = {\n\t\t\tmeta: moduleMeta,\n\t\t\tlocation: folder + moduleClassName\n\t\t};\n\t} else {\n\t\tconsole.log('Lower version detected, ignoring ...');\n\t}\n\n\treturn addModule;\n};\n\n\nAutomationController.prototype.instantiateModule = function(instanceModel) {\n\tvar self = this,\n\t\tmodule = _.find(self.modules, function(module) {\n\t\t\treturn instanceModel.moduleId === module.meta.id;\n\t\t}),\n\t\tinstance = null,\n\t\tlangFile = self.loadMainLang(),\n\t\tvalues,\n\t\tcntExistInst = [];\n\n\tif (!module) {\n\t\tself.addNotification(\"error\", langFile.ac_err_init_module_not_found, \"core\", \"AutomationController\");\n\t\treturn null; // not loaded\n\t}\n\n\tif (module.failed) {\n\t\tself.addNotification(\"error\", langFile.ac_err_load_failure + (module.meta && module.meta.id ? ': ' + module.meta.id : ''), \"core\", \"AutomationController\");\n\t\treturn null; // not loaded\n\t}\n\n\t// add creation time\n\tif (!instanceModel.creationTime) {\n\t\tinstanceModel.creationTime = Math.floor(Date.now() / 1000);\n\t}\n\n\ttry {\n\t\tinstance = new global[module.meta.id](instanceModel.id, self);\n\t} catch (e) {\n\t\tvalues = ((module && module.meta) ? module.meta.id : instanceModel.moduleId) + \": \" + e.toString();\n\n\t\tself.addNotification(\"error\", langFile.ac_err_init_module + values, \"core\", \"AutomationController\");\n\t\tconsole.log(e.stack);\n\t\treturn null; // not loaded\n\t}\n\n\tconsole.log(\"Instantiating module\", instanceModel.id, \"from class\", module.meta.id);\n\n\tcntExistInst = _.filter(self.instances, function(inst) {\n\t\treturn module.meta.id === inst.moduleId;\n\t});\n\n\tif (module.meta.singleton) {\n\t\tif (in_array(self._loadedSingletons, module.meta.id) && cntExistInst.length > 1) {\n\t\t\tconsole.log(\"WARNING: Module\", instanceModel.id, \"is a singleton and already has been instantiated. Skipping.\");\n\t\t\treturn null; // not loaded\n\t\t}\n\n\t\tself._loadedSingletons.push(module.meta.id);\n\t}\n\n\tinstanceModel.active = instanceModel.active === 'true' || (typeof instanceModel.active == 'boolean' && instanceModel.active) ? true : false;\n\n\tif (typeof instanceModel.instanceId != 'undefined')\n\t{\n\t\tdelete instanceModel.instanceId;\n\t}\n\n\tif (instanceModel.active) {\n\t\ttry {\n\t\t\tinstance.init(instanceModel.params);\n\t\t} catch (e) {\n\n\t\t\t// remove singleton entry of broken instance\n\t\t\tif (module.meta.singleton) {\n\t\t\t\tvar index = self._loadedSingletons.indexOf(module.meta.id);\n\n\t\t\t\tif (index > -1) {\n\t\t\t\t\tself._loadedSingletons.splice(index, 1);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvalues = ((module && module.meta) ? module.meta.id : instanceModel.moduleId) + \": \" + e.toString();\n\n\t\t\tself.addNotification(\"error\", langFile.ac_err_init_module + values, \"core\", \"AutomationController\");\n\t\t\tconsole.log(e.stack);\n\t\t\treturn null; // not loaded\n\t\t}\n\t\tself.registerInstance(instance);\n\t}\n\n\t// add module to loaded modules if at least one instance exists\n\tif (this.loadedModules.indexOf(module) < 0) {\n\t\tthis.loadedModules.push(module);\n\t}\n\n\treturn instance;\n};\n\nAutomationController.prototype.loadModule = function(module, rootModule, instancesCount) {\n\tvar langFile = this.loadMainLang(),\n\t\tvalues;\n\n\tif (rootModule && rootModule === module) {\n\t\tconsole.log('Circular dependencies detected!');\n\t\treturn false;\n\t}\n\n\tif (module.failed) return false; // already tried to load, and failed\n\tif (this.loadedModules.indexOf(module) >= 0) return true; // already loaded\n\n\trootModule = rootModule || module;\n\n\tif (module.meta.dependencies instanceof Array) {\n\t\tfor (var i in module.meta.dependencies) {\n\t\t\tvar dep = module.meta.dependencies[i];\n\t\t\tvalues = dep + \" :: \" + module.meta.id;\n\n\t\t\tvar depModule = this.modules[dep];\n\t\t\tif (!depModule) {\n\t\t\t\tthis.addNotification(\"error\", langFile.ac_err_dep_not_found + values, \"dependency\", module.meta.id);\n\t\t\t\tmodule.failed = true;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!this.loadModule(depModule, rootModule)) {\n\t\t\t\tthis.addNotification(\"error\", langFile.ac_err_dep_not_loaded + values, \"dependency\", module.meta.id);\n\t\t\t\tmodule.failed = true;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (!this.loadedModules.some(function(x) {\n\t\t\t\t\treturn x.meta.id === dep;\n\t\t\t\t})) {\n\n\t\t\t\tthis.addNotification(\"error\", langFile.ac_err_dep_not_init + values, \"dependency\", module.meta.id);\n\t\t\t\tmodule.failed = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t}\n\n\tconsole.log(\"Loading module \" + module.meta.id + \" from \" + module.location);\n\ttry {\n\t\texecuteFile(module.location + \"/index.js\");\n\t} catch (e) {\n\t\tvalues = module.meta.id + \": \" + e.toString();\n\n\t\tthis.addNotification(\"error\", langFile.ac_err_file_load + values, \"core\", \"AutomationController\");\n\t\tconsole.log(e.stack);\n\t\tmodule.failed = true;\n\t\treturn false; // skip this modules\n\t}\n\n\tif (!_module) {\n\t\tvalues = module.meta.id;\n\n\t\tthis.addNotification(\"error\", langFile.ac_err_invalid_module + values, \"core\", \"AutomationController\");\n\t\tmodule.failed = true;\n\t\treturn false; // skip this modules\n\t}\n\n\t// Monkey-patch module with basePath method\n\t_module.prototype.moduleBasePath = function() {\n\t\treturn module.location;\n\t};\n\n\tmodule.classRef = _module;\n\n\t_module = undefined;\n\n\t// Loading instances\n\n\tvar count = 0;\n\tthis.instances.filter(function(x) {\n\t\treturn x.moduleId === module.meta.id;\n\t}).forEach(function(x) {\n\t\tif (this.instantiateModule(x) !== null) {\n\t\t\tcount++;\n\t\t}\n\t}, this);\n\n\tif (count || instancesCount) {\n\t\tthis.loadedModules.push(module);\n\t}\n\treturn true;\n};\n\nAutomationController.prototype.unloadModule = function(moduleId) {\n\tvar self = this,\n\t\tactiveInstances = [],\n\t\tresult = 'failed';\n\n\ttry {\n\t\t// filter for instances of moduleId\n\t\tactiveInstances = self.instances.filter(function(instance) {\n\t\t\treturn instance.moduleId === moduleId;\n\t\t}).map(function(instance) {\n\t\t\treturn instance.id;\n\t\t});\n\n\t\t// remove all instances of moduleId\n\t\tif (activeInstances.length > 0) {\n\t\t\tactiveInstances.forEach(function(instanceId) {\n\t\t\t\tself.deleteInstance(instanceId);\n\t\t\t});\n\t\t}\n\n\t\t//remove from loaded Modules\n\t\tself.loadedModules = self.loadedModules.filter(function(module) {\n\t\t\treturn module.meta.id !== moduleId;\n\t\t});\n\n\t\t// remove from modules list\n\t\tif (self.modules[moduleId]) {\n\t\t\tdelete self.modules[moduleId];\n\n\t\t\tresult = 'success';\n\t\t}\n\t} catch (e) {\n\t\tresult = e;\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.installModule = function(moduleUrl, moduleName) {\n\tvar result = \"in progress\";\n\n\tconsole.log('Installing app', moduleName, '...');\n\n\tif (moduleUrl) {\n\t\tinstaller.install(\n\t\t\tmoduleUrl,\n\t\t\tmoduleName,\n\t\t\tfunction() {\n\t\t\t\tresult = \"done\";\n\t\t\t},\n\t\t\tfunction(e) {\n\t\t\t\tconsole.log(\"Error installing app \" + moduleName + \": \" + e);\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t);\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tif (result === \"in progress\") {\n\t\t\tresult = \"failed\";\n\t\t}\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.uninstallModule = function(moduleId, reset) {\n\tvar langFile = this.loadMainLang(),\n\t\tuninstall = false,\n\t\treset = reset ? reset : false,\n\t\tunload = this.unloadModule(moduleId),\n\t\tresult = \"in progress\";\n\n\tif (unload === 'success') {\n\t\ttry {\n\t\t\tinstaller.remove(\n\t\t\t\tmoduleId,\n\t\t\t\tfunction() {\n\t\t\t\t\tresult = \"done\";\n\t\t\t\t},\n\t\t\t\tfunction(e) {\n\t\t\t\t\tconsole.log(\"Error removing app \" + moduleName + \": \" + e);\n\t\t\t\t\tresult = \"failed\";\n\t\t\t\t}\n\t\t\t);\n\n\t\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tif (result === \"done\") {\n\n\t\t\t\tif (reset) {\n\t\t\t\t\tloadSuccessfully = this.loadInstalledModule(moduleId, 'modules/', true);\n\n\t\t\t\t\tuninstall = loadSuccessfully;\n\t\t\t\t} else {\n\t\t\t\t\tuninstall = true;\n\t\t\t\t}\n\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log('Uninstalling or reseting of app \"' + moduleId + '\" has failed. ERROR:', e);\n\t\t\tthis.addNotification(\"error\", langFile.ac_err_uninstall_mod + ': ' + moduleId, \"core\", \"AutomationController\");\n\t\t}\n\t}\n\n\treturn uninstall;\n};\n\nAutomationController.prototype.loadInstalledModule = function(moduleId, rootDirectory, ignoreVersion) {\n\tvar self = this,\n\t\tsuccessful = false,\n\t\tignoreVersion = ignoreVersion ? ignoreVersion : false;\n\n\ttry {\n\t\tif (fs.list(rootDirectory + moduleId) && fs.list(rootDirectory + moduleId).indexOf('index.js') !== -1) {\n\t\t\tconsole.log('Load app \"' + moduleId + '\" from folder ...');\n\t\t\tsuccessful = self.loadModuleFromFolder(moduleId, rootDirectory, ignoreVersion);\n\n\t\t\tif (successful && self.modules[moduleId]) {\n\t\t\t\tself.loadModule(self.modules[moduleId]);\n\n\t\t\t\tsuccessful = true;\n\t\t\t}\n\t\t}\n\t} catch (e) {\n\t\tconsole.log('Load app \"' + moduleId + '\" has failed. ERROR:', e);\n\t}\n\n\treturn successful;\n};\n\nAutomationController.prototype.reinitializeModule = function(moduleId, rootDirectory, ignoreVersion) {\n\tvar self = this,\n\t\tsuccessful = false,\n\t\texistingInstances = [],\n\t\tignoreVersion = ignoreVersion ? ignoreVersion : false;\n\n\t// filter for active instances of moduleId\n\texistingInstances = self.instances.filter(function(instance) {\n\t\treturn instance.moduleId === moduleId;\n\t});\n\n\tthis.unloadModule(moduleId);\n\n\t// try to reinitialize app\n\ttry {\n\t\tif (fs.list(rootDirectory + moduleId) && fs.list(rootDirectory + moduleId).indexOf('index.js') !== -1) {\n\t\t\tconsole.log('Load app \"' + moduleId + '\" from folder ...');\n\t\t\tsuccessful = self.loadModuleFromFolder(moduleId, rootDirectory, ignoreVersion);\n\n\t\t\tif (successful && self.modules[moduleId]) {\n\n\t\t\t\tself.loadModule(self.modules[moduleId], undefined, existingInstances.length);\n\n\t\t\t\t// add and start instances of moduleId again\n\t\t\t\texistingInstances.forEach(function(instance) {\n\t\t\t\t\tself.createInstance(instance);\n\t\t\t\t});\n\n\t\t\t\tsuccessful = true;\n\t\t\t}\n\t\t}\n\t} catch (e) {\n\t\tconsole.log('Load app \"' + moduleId + '\" has failed. ERROR:', e);\n\t}\n\n\treturn successful;\n};\n\nAutomationController.prototype.instantiateModules = function() {\n\tvar self = this,\n\t\tlangFile = this.loadMainLang(),\n\t\tmodules = Object.getOwnPropertyNames(this.modules),\n\t\trequiredBaseModules = [\"Cron\", \"ZWave\"],\n\t\trequiredWithDep = [];\n\n\tthis.loadedModules = [];\n\n\tmodules.splice(modules.indexOf('Cron'), 1);\n\tmodules.splice(modules.indexOf('ZWave'), 1);\n\n\t// get all required modules from dependencies\n\tObject.getOwnPropertyNames(this.modules).forEach(function(m) {\n\t\tif (this.modules[m].meta &&\n\t\t\tthis.modules[m].meta.dependencies &&\n\t\t\t_.isArray(this.modules[m].meta.dependencies) &&\n\t\t\tthis.modules[m].meta.dependencies.length > 0) {\n\n\t\t\t// load if it exists in modules list\n\t\t\trequiredBaseModules = _.uniq(requiredBaseModules.concat(_.filter(this.modules[m].meta.dependencies, function(dep) {\n\t\t\t\treturn self.modules[dep];\n\t\t\t})));\n\n\t\t\t// remove all required base modules from modules list\n\t\t\tthis.modules[m].meta.dependencies.forEach(function(mod) {\n\t\t\t\tif (modules.indexOf(mod) > -1) {\n\t\t\t\t\tmodules.splice(modules.indexOf(mod), 1);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}, this);\n\n\t// first instantiate all required modules without dependencies\n\trequiredBaseModules.forEach(function(mod) {\n\n\t\t// prepare base modules with dependencies\n\t\tif (this.modules[mod].meta &&\n\t\t\tthis.modules[mod].meta.dependencies &&\n\t\t\t_.isArray(this.modules[mod].meta.dependencies) &&\n\t\t\tthis.modules[mod].meta.dependencies.length > 0) {\n\n\t\t\t// cache required modules with dependencies\n\t\t\tif (requiredWithDep.indexOf(mod) < 0) {\n\t\t\t\trequiredWithDep.push(mod);\n\t\t\t}\n\t\t} else {\n\t\t\t// load base modules without dependencies first\n\t\t\tthis.loadModule(this.modules[mod]);\n\t\t}\n\t}, this);\n\n\t// instantiate all required with dependencies\n\trequiredWithDep.forEach(function(mod) {\n\t\tthis.loadModule(this.modules[mod]);\n\t}, this);\n\n\t// load all remaining modules\n\tmodules.forEach(function(mod) {\n\t\tthis.loadModule(this.modules[mod]);\n\t}, this);\n};\n\nAutomationController.prototype.moduleInstance = function(instanceId) {\n\treturn this.instances.hasOwnProperty(instanceId) ? this.instances[instanceId] : null;\n};\n\nAutomationController.prototype.registerInstance = function(instance) {\n\tvar self = this,\n\t\tlangFile = this.loadMainLang();\n\n\tif (!!instance) {\n\t\tvar instanceId = instance.id,\n\t\t\tisExistInstance = self.registerInstances.hasOwnProperty(instanceId);\n\n\t\tif (!isExistInstance) {\n\t\t\tself.registerInstances[instanceId] = instance;\n\t\t\tself.emit('core.instanceRegistered', instanceId);\n\t\t} else {\n\t\t\tself.emit('core.error', new Error(langFile.ac_err_instance_already_exists + instanceId));\n\t\t}\n\t} else {\n\t\tself.emit('core.error', new Error(langFile.ac_err_instance_empty + instance.id));\n\t}\n};\n\nAutomationController.prototype.listInstances = function() {\n\tvar self = this,\n\t\texpInstances = [];\n\n\tif (self.instances) {\n\t\tself.instances.forEach(function(instance) {\n\t\t\tvar moduleJSON = self.getModuleData(instance.moduleId);\n\n\t\t\texpInstances.push(_.extend(instance, {\n\t\t\t\t// use category from module and use it's title as fallback ...\n\t\t\t\tcategory: moduleJSON && moduleJSON.category || null,\n\t\t\t\ttitle: (!instance.title || instance.title === '') ? ((moduleJSON.defaults && moduleJSON.defaults.title) ? moduleJSON.defaults.title : \"?\") : instance.title\n\t\t\t}));\n\t\t});\n\t} else {\n\t\texpInstances = null;\n\t}\n\n\treturn expInstances;\n}\n\nAutomationController.prototype.createInstance = function(reqObj) {\n\n\t//var instance = this.instantiateModule(id, className, config),\n\tvar self = this,\n\t\tlangFile = this.loadMainLang(),\n\t\tid = findSmallestNotAssignedIntegerValue(self.instances, 'id'),\n\t\tinstance = null,\n\t\tmodule = _.find(self.modules, function(module) {\n\t\t\treturn module.meta.id === reqObj.moduleId;\n\t\t}),\n\t\tresult,\n\t\talreadyExisting = [];\n\n\tif (!!module) {\n\n\t\tif (reqObj.id) {\n\t\t\talreadyExisting = _.filter(this.instances, function(inst) {\n\t\t\t\treturn inst.id === reqObj.id\n\t\t\t});\n\t\t}\n\n\t\tinstance = _.extend(reqObj, {\n\t\t\tid: alreadyExisting[0] ? reqObj.id : id,\n\t\t\tactive: reqObj.active === 'true' || (typeof reqObj.active == 'boolean' && reqObj.active) ? true : false\n\t\t});\n\n\t\tif (typeof instance.instanceId != 'undefined')\n\t\t{\n\t\t\tdelete instance.instanceId;\n\t\t}\n\n\t\tself.instances.push(instance);\n\t\tself.saveConfig(true);\n\t\tself.emit('core.instanceCreated', instance.id);\n\t\tresult = self.instantiateModule(instance);\n\n\t\t// remove instance from list if broken\n\t\tif (result === null) {\n\t\t\tvar currIndex = self.instances.length ? self.instances.length - 1 : 0;\n\n\t\t\tself.instances.splice(currIndex, 1);\n\t\t\tself.saveConfig(true);\n\t\t\tself.emit('core.instanceDeleted', id);\n\t\t}\n\t} else {\n\t\tself.emit('core.error', new Error(langFile.ac_err_create_instance + reqObj.moduleId + \" :: \" + id));\n\t\tresult = false;\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.stopInstance = function(instance) {\n\tvar self = this,\n\t\tlangFile = this.loadMainLang(),\n\t\tinstId = instance.id,\n\t\tvalues;\n\n\ttry {\n\t\tinstance.stop();\n\t\tdelete this.registerInstances[instId];\n\n\t\t// get all devices created by instance\n\t\tinstDevices = _.map(this.devices.filter(function(dev) {\n\t\t\treturn dev.get('creatorId') === instId;\n\t\t}), function(dev) {\n\t\t\treturn dev.id;\n\t\t});\n\n\t\t// remove devices\n\t\tif (instDevices.length > 0) {\n\t\t\tinstDevices.forEach(function(id) {\n\t\t\t\t// check for device entry again\n\t\t\t\tif (!!self.devices.get(id)) {\n\t\t\t\t\tself.devices.remove(id);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t} catch (e) {\n\t\tvalues = ((instance && instId) ? instId : \"<unknow id>\") + \": \" + e.toString();\n\n\t\tthis.addNotification(\"error\", langFile.ac_err_stop_mod + values, \"core\", \"AutomationController\");\n\t\tconsole.log(e.stack);\n\t\treturn;\n\t}\n};\n\nAutomationController.prototype.reconfigureInstance = function(id, instanceObject) {\n\tvar langFile = this.loadMainLang(),\n\t\tregister_instance = this.registerInstances[id],\n\t\tinstance = _.find(this.instances, function(model) {\n\t\t\treturn model.id === id;\n\t\t}),\n\t\tindex = this.instances.indexOf(instance),\n\t\tconfig = {},\n\t\tresult;\n\n\tif (instance) {\n\t\tif (register_instance && instance.active) {\n\t\t\tthis.stopInstance(register_instance);\n\t\t}\n\n\t\tif (instanceObject.hasOwnProperty('params')) {\n\t\t\tif (Object.keys(instanceObject.params).length === 0) {\n\t\t\t\tconfig = instanceObject.params;\n\t\t\t} else {\n\t\t\t\tfor (var property in instance.params) {\n\t\t\t\t\tconfig[property] = instanceObject.params.hasOwnProperty(property) && instanceObject.params[property] !== instance.params[property] ? instanceObject.params[property] : instance.params[property];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t_.extend(this.instances[index], {\n\t\t\ttitle: instanceObject.hasOwnProperty('title') ? instanceObject.title : instance.title,\n\t\t\tdescription: instanceObject.hasOwnProperty('description') ? instanceObject.description : instance.description,\n\t\t\tactive: instanceObject.hasOwnProperty('active') ? !!instanceObject.active : instance.active,\n\t\t\tparams: config !== {} ? config : instance.params\n\t\t});\n\n\t\tif (typeof this.instances[index].instanceId != 'undefined')\n\t\t{\n\t\t\tdelete this.instances[index].instanceId;\n\t\t}\n\n\t\tif (!!register_instance) {\n\t\t\tif (this.instances[index].active) { // here we read new config instead of existing\n\t\t\t\tregister_instance.init(config);\n\t\t\t\tthis.registerInstance(register_instance);\n\t\t\t} else {\n\t\t\t\tregister_instance.saveNewConfig(config);\n\t\t\t}\n\t\t} else {\n\t\t\tif (this.instances[index].active) {\n\t\t\t\tthis.instantiateModule(this.instances[index]);\n\t\t\t}\n\t\t}\n\n\t\tresult = this.instances[index];\n\t\tthis.emit('core.instanceReconfigured', id)\n\t} else {\n\t\tresult = null;\n\t\tthis.emit('core.error', new Error(langFile.ac_err_refonfigure_instance + id));\n\t}\n\n\tthis.saveConfig(true);\n\treturn result;\n};\n\nAutomationController.prototype.removeInstance = function(id) {\n\tvar instance = this.registerInstances[id],\n\t\tgetInstFromList = [];\n\n\tgetInstFromList = this.instances.filter(function(model) {\n\t\treturn id === model.id;\n\t});\n\n\tif (!!instance) {\n\t\tthis.stopInstance(instance);\n\n\t\tthis.emit('core.instanceStopped', id);\n\t\tthis.saveConfig(true);\n\t}\n\n\t// remove from loaded singleton list if singleton\n\tif (getInstFromList.length > 0 && getInstFromList[0]) {\n\t\tvar moduleId = getInstFromList[0].moduleId;\n\t\tvar index = this._loadedSingletons.indexOf(moduleId);\n\t\tif (index > -1) {\n\t\t\tthis._loadedSingletons.splice(index, 1);\n\t\t}\n\t}\n};\n\nAutomationController.prototype.deleteInstance = function(id) {\n\tvar instDevices = [],\n\t\tself = this;\n\n\t// get all devices created by instance\n\tinstDevices = this.devices.filterByCreatorId(id).concat(\n        \tObject.keys(self.vdevInfo).filter(function(__id, __vdev) {\n        \t\treturn __vdev.creatorId === id;\n\t\t})\n\t);\n\n\tthis.removeInstance(id);\n\n\tthis.instances = this.instances.filter(function(model) {\n\t\treturn id !== model.id;\n\t});\n\n\t// remove and cleanup\n\tif (instDevices.length > 0) {\n\t\tinstDevices.forEach(function(vDev) {\n\t\t\t// check for vDevInfo entry\n\t\t\tself.devices.remove(vDev.id);\n\t\t\tself.devices.cleanup(vDev.id);\n\t\t});\n\t}\n\n\tthis.saveConfig(true);\n\tthis.emit('core.instanceDeleted', id);\n};\n\nAutomationController.prototype.installSkin = function(reqObj, skinName, index) {\n\tvar result = \"in progress\";\n\n\tif (reqObj.file_path) {\n\n\t\tconsole.log('Installing skin', skinName, '...');\n\n\t\tskininstaller.install(\n\t\t\treqObj.file_path,\n\t\t\tskinName,\n\t\t\tfunction() {\n\t\t\t\tresult = \"done\";\n\t\t\t},\n\t\t\tfunction(e) {\n\t\t\t\tconsole.log(\"Error installing skin \" + skinName + \": \" + e);\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t);\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tif (result === \"in progress\") {\n\t\t\tresult = \"failed\";\n\t\t}\n\n\t\tif (result === 'done') {\n\t\t\tif (index < 0) {\n\t\t\t\t// add new skin\n\t\t\t\tnewSkin = {\n\t\t\t\t\tname: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tdescription: '',\n\t\t\t\t\tversion: '',\n\t\t\t\t\ticon: false,\n\t\t\t\t\tauthor: '',\n\t\t\t\t\thomepage: '',\n\t\t\t\t\tactive: false\n\t\t\t\t};\n\n\t\t\t\tfor (var property in reqObj) {\n\t\t\t\t\tif (reqObj.hasOwnProperty(property) && newSkin.hasOwnProperty(property)) {\n\t\t\t\t\t\tnewSkin[property] = reqObj[property];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.skins.push(newSkin);\n\t\t\t} else {\n\t\t\t\t// update entries\n\t\t\t\tfor (var property in reqObj) {\n\t\t\t\t\tif (reqObj.hasOwnProperty(property) && this.skins[index].hasOwnProperty(property)) {\n\t\t\t\t\t\tthis.skins[index][property] = reqObj[property];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.skins[index].active = false;\n\t\t\t}\n\n\t\t\tsaveObject(\"userSkins.json\", this.skins, true);\n\t\t}\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.uninstallSkin = function(skinName) {\n\tvar langFile = this.loadMainLang(),\n\t\tresult = \"in progress\";\n\n\ttry {\n\t\tskininstaller.remove(\n\t\t\tskinName,\n\t\t\tfunction() {\n\t\t\t\tresult = \"done\";\n\t\t\t},\n\t\t\tfunction(e) {\n\t\t\t\tconsole.log(\"Error installing skin \" + skinName + \": \" + e);\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t);\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tif (result === \"in progress\") {\n\t\t\tresult = \"failed\";\n\t\t}\n\n\t\t//if (result === \"done\") {\n\n\t\tthis.skins = _.filter(this.skins, function(skin) {\n\t\t\treturn skin.name !== skinName;\n\t\t});\n\n\t\tthis.profiles.forEach(function(prof) {\n\t\t\tif (prof.skin === skinName) {\n\t\t\t\tprof.skin = 'default';\n\t\t\t}\n\t\t});\n\n\t\tsaveObject(\"userSkins.json\", this.skins, true);\n\t\t//}\n\n\t} catch (e) {\n\t\tconsole.log('Uninstalling or reseting of skin \"' + skinName + '\" has failed. ERROR:', e);\n\t\tthis.addNotification(\"error\", langFile.ac_err_uninstall_skin + ': ' + skinName, \"core\", \"AutomationController\");\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.setSkinState = function(skinName, reqObj) {\n\n\tvar res = null;\n\n\tif (reqObj.hasOwnProperty('active')) {\n\n\t\t_.forEach(this.skins, function(skin) {\n\t\t\tif (reqObj.active === true || reqObj.active === 'true') {\n\t\t\t\t// activate target skin and deactivate all others\n\t\t\t\tskin.active = skin.name === skinName ? true : false;\n\t\t\t\tres = skin.name === skinName ? skin : res;\n\t\t\t} else {\n\t\t\t\t// deactivate all skins and set default skin to active: true\n\t\t\t\tskin.active = skin.name === 'default' ? true : false;\n\t\t\t\tres = skin.name === 'default' ? skin : res;\n\t\t\t}\n\t\t})\n\n\t\tsaveObject(\"userSkins.json\", this.skins, true);\n\t}\n\n\treturn res;\n};\n\nAutomationController.prototype.installIcon = function(option, reqObj, iconName, id) {\n\tvar reply = {\n\t\t\tmessage: \"in progress\",\n\t\t\tfiles: []\n\t\t},\n\t\tfilelist = [],\n\t\tinput = \"\",\n\t\tname = \"\",\n\t\tupdate = false;\n\n\textensionToLower = function(name) {\n\t\tvar arr = name.split(\".\");\n\t\tarr[arr.length - 1] = arr[arr.length - 1].toLowerCase();\n\t\tif (arr[arr.length - 1] == \"gz\" && arr.length > 2 && arr[arr.length - 2].toLowerCase() == \"tar\") {\n\t\t\tarr[arr.length - 2] == arr[arr.length - 2].toLowerCase();\n\t\t}\n\t\treturn arr.join(\".\");\n\t};\n\n\tswitch (option) {\n\t\tcase 'remote':\n\t\t\tinput = reqObj.file_path;\n\t\t\tname = iconName\n\t\t\tbreak;\n\t\tcase 'local':\n\t\t\treqObj.name = extensionToLower(reqObj.name);\n\t\t\tinput = JSON.stringify(reqObj);\n\t\t\tname = reqObj.name;\n\t\t\tbreak;\n\t}\n\n\tif (input) {\n\t\tconsole.log('Installing icon', name, '...');\n\n\t\ticoninstaller.install(\n\t\t\tinput,\n\t\t\ticonName,\n\t\t\tid,\n\t\t\tfunction(success) {\n\t\t\t\tfilelist = parseToObject(success);\n\t\t\t\treply.message = \"done\";\n\t\t\t},\n\t\t\tfunction(e) {\n\t\t\t\tconsole.log(\"Error installing icons set \" + name + \": \" + e);\n\t\t\t\treply.message = \"failed\";\n\t\t\t}\n\t\t);\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d && reply.message === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tif (reply.message === \"in progress\") {\n\t\t\treply.message = \"failed\";\n\t\t}\n\n\t\tif (reply.message === 'done') {\n\t\t\tfor (var file in filelist) {\n\t\t\t\tif (filelist[file].filename && filelist[file].orgfilename) {\n\t\t\t\t\tvar icon = {\n\t\t\t\t\t\t'file': filelist[file].filename,\n\t\t\t\t\t\t'orgfile': filelist[file].orgfilename,\n\t\t\t\t\t\t'source': iconName + \"_\" + id,\n\t\t\t\t\t\t'name': iconName,\n\t\t\t\t\t\t'id': id,\n\t\t\t\t\t\t'timestamp': Math.floor(Date.now() / 1000),\n\t\t\t\t\t\t'source_title': option === \"local\" ? iconName + \" \" + id : reqObj.title\n\t\t\t\t\t};\n\n\t\t\t\t\treply.files.push(filelist[file].filename);\n\n\t\t\t\t\tthis.icons.push(icon);\n\t\t\t\t\tupdate = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (update) {\n\t\t\t\tsaveObject(\"userIcons.json\", this.icons, true);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (reply.files.length == 1) {\n\t\treply.files = reply.files[0];\n\t}\n\n\treturn reply;\n};\n\nAutomationController.prototype.listIcons = function() {\n\tvar result = \"in progress\",\n\t\ticons = {};\n\n\ttry {\n\t\ticoninstaller.list(\n\t\t\tfunction(success) {\n\t\t\t\ticons = success;\n\t\t\t\tresult = \"done\";\n\t\t\t},\n\t\t\tfunction(e) {\n\t\t\t\tconsole.log(\"Error installing icons set \" + name + \": \" + e);\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t);\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tif (result == \"in progress\") {\n\t\t\tresult = \"failed\";\n\t\t}\n\n\t} catch (e) {\n\t\tconsole.log(e)\n\t}\n\n\treturn icons;\n}\n\nAutomationController.prototype.uninstallIcon = function(iconName) {\n\tvar langFile = this.loadMainLang(),\n\t\tresult = \"in progress\";\n\n\ttry {\n\t\ticoninstaller.remove(\n\t\t\ticonName,\n\t\t\tfunction(success) {\n\t\t\t\tresult = \"done\";\n\t\t\t},\n\t\t\tfunction(error) {\n\t\t\t\tif (error == \"No such icon.\") {\n\t\t\t\t\tresult = \"done\";\n\t\t\t\t} else {\n\t\t\t\t\tresult = \"failed\";\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tif (result === \"in progress\") {\n\t\t\tresult = \"failed\";\n\t\t}\n\n\t\t//if (result === \"done\") {\n\t\tthis.icons = _.filter(this.icons, function(icon) {\n\t\t\treturn icon.file !== iconName;\n\t\t});\n\n\t\tsaveObject(\"userIcons.json\", this.icons, true);\n\t\t//}\n\n\t} catch (e) {\n\t\tconsole.log('Uninstalling or reseting of icon \"' + iconName + '\" has failed. ERROR:', e);\n\t\tthis.addNotification(\"error\", langFile.ac_err_uninstall_icon + ': ' + iconName, \"core\", \"AutomationController\");\n\t}\n\n\treturn result;\n}\n\nAutomationController.prototype.deleteCustomicon = function(iconName) {\n\tself = this;\n\tself.devices.each(function(dev) {\n\t\tif (!_.isEmpty(dev.get('customIcons'))) {\n\t\t\tvar customIcon = dev.get('customIcons');\n\t\t\t_.each(customIcon, function(value, key) {\n\t\t\t\tif (typeof value !== \"object\") {\n\t\t\t\t\tif (value === iconName) {\n\t\t\t\t\t\tcustomIcon = {};\n\t\t\t\t\t\tdev.set('customIcons', customIcon, {\n\t\t\t\t\t\t\tsilent: true\n\t\t\t\t\t\t});\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t_.each(value, function(icon, level) {\n\t\t\t\t\t\tif (icon === iconName) {\n\t\t\t\t\t\t\tdelete customIcon[key][level];\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (_.isEmpty(customIcon[key])) {\n\t\t\t\t\t\tcustomIcon = {};\n\t\t\t\t\t}\n\t\t\t\t\tdev.set('customIcons', customIcon, {\n\t\t\t\t\t\tsilent: true\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n}\n\nAutomationController.prototype.deleteAllCustomicons = function() {\n\tself = this;\n\tself.devices.each(function(dev) {\n\t\tdev.set('customIcons', {}, {\n\t\t\tsilent: true\n\t\t});\n\t});\n}\n\nAutomationController.prototype.deviceExists = function(vDevId) {\n\treturn Object.keys(this.devices).indexOf(vDevId) >= 0;\n};\n\nAutomationController.prototype.getVdevInfo = function(id) {\n\treturn this.vdevInfo[id] || {};\n};\n\nAutomationController.prototype.setVdevInfo = function(id, device) {\n\tthis.vdevInfo[id] = _.pick(device,\n\t\t\"deviceType\",\n\t\t\"probeType\",\n\t\t\"metrics\",\n\t\t\"location\",\n\t\t// do not save locationName - recalculate on the fly\n\t\t\"tags\",\n\t\t\"permanently_hidden\",\n\t\t\"creationTime\",\n\t\t\"creatorId\",\n\t\t\"customIcons\",\n\t\t\"order\",\n\t\t\"visibility\",\n\t\t\"hasHistory\");\n\tthis.saveConfig(this.savePeriod);\n\treturn this.vdevInfo[id];\n};\n\nAutomationController.prototype.clearVdevInfo = function(id) {\n\tdelete this.vdevInfo[id];\n\tthis.profiles.forEach(function(p) {\n\t\tp.hide_single_device_events = p.hide_single_device_events.filter(function(item) {\n\t\t\treturn item !== id;\n\t\t}); \n\t\tp.devices = p.devices.filter(function(item) {\n\t\t\treturn item !== id;\n\t\t});\n\t});\n\tthis.saveConfig(true);\n};\n\nAutomationController.prototype.loadNotifications = function() {\n\tvar self = this;\n\t\n\tthis.notifications = new LimitedArray(\n\t\tloadObject(\"notifications\") || [],\n\t\tfunction(arr) {\n\t\t\tsaveObject('notifications', arr, self.savePeriod);\n\t\t},\n\t\t25, // check it every 25 notifications\n\t\t2500, // save up to 2500 notifications\n\t\tfunction(notification) {\n\t\t\tvar now = new Date(),\n\t\t\t\tstartOfDay = now.setHours(0, 0, 0, 0),\n\t\t\t\ts_tsSevenDaysBefore = Math.floor(startOfDay / 1000) - 86400 * 6, // fallback for older versions\n\t\t\t\tms_tsSevenDaysBefore = Math.floor(startOfDay) - 86400000 * 6;\n\n\t\t\treturn (notification.id.toString().length <= 10 && notification.id >= s_tsSevenDaysBefore) ||\n\t\t\t\t(notification.id.toString().length > 10 && notification.id >= ms_tsSevenDaysBefore);\n\t\t}\n\t);\n};\n\nAutomationController.prototype.addNotification = function(severity, message, type, source) {\n\tvar self = this;\n\n\tvar now = new Date(),\n\t\tnotice = {\n\t\t\tid: Math.floor(now.getTime()),\n\t\t\ttimestamp: now.toISOString(),\n\t\t\tlevel: severity,\n\t\t\tmessage: message,\n\t\t\ttype: type || 'device',\n\t\t\tsource: source,\n\t\t\tredeemed: false\n\t\t};\n\n\tif (typeof message === 'object') {\n\t\tmsg = JSON.stringify(message);\n\t} else {\n\t\tmsg = message;\n\t}\n\n\tthis.notifications.push(notice);\n\t\n\tconsole.log(\"Notification:\", severity, \"(\" + type + \"):\", msg);\n\tthis.emit(\"notifications.push\", notice); // notify modules to allow SMS and E-Mail notifications\n};\n\nAutomationController.prototype.deleteNotifications = function(ts, before, callback) {\n\tvar before = Boolean(before) || false,\n\t\tnewNotificationList = [],\n\t\tts = parseInt(ts) || 0;\n\n\tif (ts !== 0) {\n\t\tif (before) {\n\t\t\tnewNotificationList = this.notifications.get().filter(function(notification) {\n\t\t\t\treturn notification.id >= ts;\n\t\t\t});\n\t\t\tconsole.log('---------- all notifications before ' + ts + ' deleted ----------');\n\t\t} else {\n\t\t\tnewNotificationList = this.notifications.get().filter(function(notification) {\n\t\t\t\treturn notification.id !== ts;\n\t\t\t});\n\t\t\tconsole.log('---------- notification with id ' + ts + ' deleted ----------');\n\t\t}\n\n\t\tthis.notifications.set(newNotificationList);\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(true);\n\t\t}\n\t}\n};\n\nAutomationController.prototype.deleteAllRedeemedNotifications = function(callback) {\n\ttry {\n\t\tthis.notifications.set(this.notifications.get().filter(function(notification) {\n\t\t\treturn !notification.redeemed;\n\t\t}));\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(true);\n\t\t}\n\t} catch (e) {\n\t\tconsole.log('deleteAllRedeemedNotifications - something went wrong:', e.message);\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(false);\n\t\t}\n\t}\n};\n\nAutomationController.prototype.redeemNotification = function(id, redeemed, callback) {\n\tvar r = redeemed !== undefined ? redeemed : true;\n\tid = id || 0;\n\n\tif (id > 0) {\n\t\tvar notifications = this.notifications.get(),\n\t\t\tindex = _.findIndex(notifications, {\n\t\t\t\tid: id\n\t\t\t});\n\n\t\tnotifications[index].redeemed = r;\n\n\t\tthis.notifications.set(notifications);\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(true);\n\t\t}\n\t} else {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(false);\n\t\t}\n\t}\n};\n\nAutomationController.prototype.redeemAllNotifications = function(redeemed, callback) {\n\tvar r = redeemed !== undefined ? redeemed : true;\n\n\ttry {\n\t\tvar notifications = this.notifications.get();\n\n\t\t_.forEach(notifications, function(notification) {\n\t\t\tnotification.redeemed = r;\n\t\t});\n\n\t\tthis.notifications.set(notifications);\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(true);\n\t\t}\n\t} catch (e) {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(false);\n\t\t}\n\t}\n};\n\nAutomationController.prototype.locationName = function(locationId) {\n\tvar location = _.find(this.locations, function(loc) { return loc.id === locationId; });\n\treturn location ? location.title : \"\";\n};\n\nAutomationController.prototype.getLocation = function(locations, locationId) {\n\tvar location = [],\n\t\tnspc = null;\n\n\tlocation = locations.filter(function(location) {\n\t\tif (locationId === 'globalRoom') {\n\t\t\treturn location.id === 0 &&\n\t\t\t\tlocation.title === locationId;\n\t\t} else {\n\t\t\treturn location.id === locationId;\n\t\t}\n\t});\n\n\treturn location[0] ? location[0] : null;\n}\n\nAutomationController.prototype.addLocation = function(locProps, callback) {\n\tvar id = this.locations.length > 0 ? Math.max.apply(null, this.locations.map(function(location) {\n\t\treturn location.id;\n\t})) + 1 : 1; // changed after adding global room with id=0 || old: this.locations.length ? this.locations[this.locations.length - 1].id + 1 : 1;\n\tvar locations = this.locations.filter(function(location) {\n\t\treturn location.id === id;\n\t});\n\n\tif (locations.length > 0) {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(false);\n\t\t}\n\t} else {\n\n\t\tvar location = {\n\t\t\tid: id,\n\t\t\ttitle: locProps.title,\n\t\t\tuser_img: locProps.user_img || '',\n\t\t\tdefault_img: locProps.default_img || '',\n\t\t\timg_type: locProps.img_type || '',\n\t\t\tshow_background: locProps.show_background || false,\n\t\t\tmain_sensors: locProps.main_sensors || []\n\t\t};\n\n\t\tthis.locations.push(location);\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(location);\n\t\t}\n\n\t\tthis.saveConfig(true);\n\t\tthis.emit('location.added', location);\n\t}\n};\n\nAutomationController.prototype.removeLocation = function(id, callback) {\n\tvar self = this,\n\t\tlangFile = this.loadMainLang(),\n\t\tlocations = this.locations.filter(function(location) {\n\t\t\treturn location.id === id;\n\t\t});\n\tif (locations.length > 0) {\n\t\tObject.keys(this.devices).forEach(function(vdevId) {\n\t\t\tvar vdev = self.devices[vdevId];\n\t\t\tif (vdev.location === id) {\n\t\t\t\tvdev.location = 0;\n\t\t\t}\n\t\t});\n\n\t\tthis.locations = this.locations.filter(function(location) {\n\t\t\treturn location.id !== id;\n\t\t});\n\n\t\tthis.saveConfig(true);\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(true);\n\t\t}\n\t\tthis.emit('location.removed', id);\n\t} else {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(false);\n\t\t}\n\t\tthis.emit('core.error', new Error(langFile.ac_err_location_not_found));\n\t}\n};\n\nAutomationController.prototype.updateLocation = function(id, title, user_img, default_img, img_type, show_background, main_sensors, callback) {\n\tvar langFile = this.loadMainLang(),\n\t\tlocations = this.locations.filter(function(location) {\n\t\t\treturn location.id === id;\n\t\t});\n\n\tif (locations.length > 0) {\n\t\tvar location = this.locations[this.locations.indexOf(locations[0])];\n\n\t\tlocation.title = title;\n\t\tlocation.show_background = show_background;\n\t\tlocation.main_sensors = main_sensors;\n\t\tif (typeof user_img === 'string') {\n\t\t\tlocation.user_img = user_img;\n\t\t}\n\t\tif (typeof default_img === 'string') {\n\t\t\tlocation.default_img = default_img;\n\t\t}\n\t\tif (typeof img_type === 'string') {\n\t\t\tlocation.img_type = img_type;\n\t\t}\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(location);\n\t\t}\n\n\t\tthis.saveConfig(true);\n\t\tthis.emit('location.updated', location);\n\t} else {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(false);\n\t\t}\n\t\tthis.emit('core.error', new Error(langFile.ac_err_location_not_found));\n\t}\n};\n\nAutomationController.prototype.listNotifications = function(since, to) {\n\tsince = parseInt(since) || 0;\n\tto = parseInt(to) || Math.floor(Date.now() / 1000);\n\n\treturn this.notifications.get().filter(function(notification) {\n\t\treturn notification.id >= since && notification.id <= to;\n\t});\n};\n\nAutomationController.prototype.getNotification = function(id) {\n\tvar filteredNotifications = this.notifications.get().filter(function(notification) {\n\t\treturn parseInt(notification.id) === parseInt(id);\n\t});\n\n\treturn filteredNotifications[0] || null;\n};\n\nAutomationController.prototype.updateNotification = function(id, object, callback) {\n\tvar filteredNotifications = _.find(this.notifications.get(), function(notification) {\n\t\t\treturn parseInt(notification.id) === parseInt(id);\n\t\t}),\n\t\tindex = this.notifications.get().indexOf(filteredNotifications);\n\n\tif (object.hasOwnProperty('redeemed')) {\n\t\tthis.notifications.get()[index].redeemed = object.redeemed;\n\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(this.notifications.get()[index]);\n\t\t}\n\t} else {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(null);\n\t\t}\n\t}\n};\n\n// get list of files from storage that should be ignored during e.g. backup, restore\nAutomationController.prototype.getIgnoredStorageFiles = function(list) {\n\tvar dontSave = [\n\t\t\t\"notifications\",\n\t\t\t\"8084AccessTimeout\",\n\t\t\t\"expertconfig.json\",\n\t\t\t\"de.devices.json\",\n\t\t\t\"en.devices.json\",\n\t\t\t\"history\",\n\t\t\t\"postfix.json\"\n\t\t], // objects that should be ignored\n\t\tdynamicMatches = [\n\t\t\t\"incomingPacket.json\",\n\t\t\t\"outgoingPacket.json\",\n\t\t\t\"originPackets.json\",\n\t\t\t\"parsedPackets.json\",\n\t\t\t\"reorgLog\",\n\t\t\t\"rssidata.json\",\n\t\t\t\"vendors.json\",\n\t\t\t\"history_\"\n\t\t],\n\t\tstorageList = __storageContent;\n\tmatches = [];\n\n\t// add additional list of ignored storage files\n\tdontSave = list && _.isArray(list) ? _.uniq(dontSave.concat(list)) : dontSave;\n\n\t// apply list of dynamic matches to ignore list\n\tif (storageList) {\n\t\t_.forEach(dynamicMatches, function(match) {\n\t\t\tmatches = _.uniq(matches.concat(_.filter(storageList, function(name) {\n\t\t\t\treturn name.indexOf(match) > -1;\n\t\t\t})));\n\t\t});\n\t}\n\n\treturn _.uniq(dontSave.concat(matches));\n};\n\nAutomationController.prototype.safeProfile = function(profile, exclude) {\n\tvar prof = {},\n\t\texcl = [\"password\", \"salt\", \"authTokens\"].concat(exclude);\n\t\t\n\tfor (var property in profile) {\n\t\tif (excl.indexOf(property) === -1) {\n\t\t\tprof[property] = profile[property];\n\t\t}\n\t}\n\n\t// explicitelly copy authTokens if not in exclude list\n\tif (!exclude || exclude.indexOf(\"authTokens\") === -1) {\n\t\tprof.authTokens = [];\n\t\tif (profile.authTokens) {\n\t\t\tprofile.authTokens.forEach(function(authToken) {\n\t\t\t\tprof.authTokens.push({\n\t\t\t\t\tsid: authToken.sid.substr(0,6) + \"...\", // first 6 symbols are uniq - see AuthController\n\t\t\t\t\tagent: authToken.agent,\n\t\t\t\t\tdate: authToken.date,\n\t\t\t\t\tlastSeen: authToken.lastSeen,\n\t\t\t\t\tip: authToken.ip,\n\t\t\t\t\texpire: authToken.expire\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\t\n\treturn prof;\n};\n\n// safely return all profiles removing sensitive data\nAutomationController.prototype.getListProfiles = function() {\n\tvar getProfiles = [],\n\t\tself = this;\n\n\tthis.profiles.forEach(function(profile) {\n\t\tgetProfiles.push(self.safeProfile(profile, [\"authTokens\"]));\n\t});\n\treturn getProfiles;\n};\n\nAutomationController.prototype.getProfile = function(id) {\n\treturn _.find(this.profiles, function(profile) {\n\t\treturn profile.id === parseInt(id);\n\t}) || null;\n};\n\nAutomationController.prototype.createProfile = function(profile) {\n\tvar id = 0,\n\t\tglobalRoom = [0],\n\t\tprofileIds = _.map(this.profiles, function(pro) {\n\t\t\treturn parseInt(pro.id);\n\t\t});\n\n\t// create latest id\n\tid = profileIds.length > 0 ? Math.max.apply(null, profileIds) + 1 : 1;\n\n\tprofile.id = id;\n\n\tif (profile.role === 1) {\n\t\tprofile.rooms = profile.rooms.indexOf(0) > -1 ? profile.rooms : profile.rooms.concat(globalRoom);\n\t}\n\n\tprofile.salt = generateSalt();\n\tprofile.password = hashPassword(profile.password, profile.salt);\n\tprofile.uuid = crypto.guid();\n\n\tthis.profiles.push(profile);\n\t\n\tthis.updateProfileDevices(profile, [], [], profile.rooms, profile.devices);\n\tthis.emit('profile.added', profile);\n\n\tthis.saveConfig(true);\n\treturn profile;\n};\n\n// Detect devices added to the profile\nAutomationController.prototype.updateProfileDevices = function(profile, oldLocations, oldDevices, newLocations, newDevices) {\n\toldLocations = oldLocations || [];\n\toldDevices = oldDevices || [];\n\tnewLocations = newLocations || [];\n\tnewDevices = newDevices || [];\n\n\tvar addedLocations   = _.difference(newLocations, oldLocations), addedDevices   = _.difference(newDevices, oldDevices),\n\t    removedLocations = _.difference(oldLocations, newLocations), removedDevices = _.difference(oldDevices, newDevices);\n\t\n\tvar devicesInAddedLocations   = this.devices.filter(function(d) { return addedLocations.indexOf(d.get(\"location\")) > -1;   }).map(function(d) { return d.id; }),\n\t    devicesInRemovedLocations = this.devices.filter(function(d) { return removedLocations.indexOf(d.get(\"location\")) > -1; }).map(function(d) { return d.id; });\n\n\tvar devicesInOldLocations = this.devices.filter(function(d) { return oldLocations.indexOf(d.get(\"location\")) > -1; }).map(function(d) { return d.id; }),\n\t    devicesInNewLocations = this.devices.filter(function(d) { return newLocations.indexOf(d.get(\"location\")) > -1;  }).map(function(d) { return d.id; });\n\t\n\t    // Device is added if it was added in granted device list or in granted location and was not in those lists before\n\tvar devicesAdded   = _.difference(_.union(addedDevices,   devicesInAddedLocations),   _.union(oldDevices, devicesInOldLocations)),\n\t    // Device is removed if it was deleted from granted device list or from granted location and is not in those lists now\n\t    devicesRemoved = _.difference(_.union(removedDevices, devicesInRemovedLocations), _.union(newDevices, devicesInNewLocations));\n\t\n\tthis.emit('profile.deviceListUpdated', {\n\t\tprofile: profile,\n\t\tadded: devicesAdded,\n\t\tdeleted: devicesRemoved\n\t});\n};\n\nAutomationController.prototype.updateProfile = function(object, id) {\n\tvar profile = _.find(this.profiles, function(profile) {\n\t\t\treturn profile.id === parseInt(id);\n\t\t}),\n\t\tindex;\n\n\tif (profile) {\n\t\tindex = this.profiles.indexOf(profile);\n\n\t\tvar oldLocations = profile.rooms, oldDevices = profile.devices;\n\t\t\n\t\t// update properties\n\t\tfor (var property in object) {\n\t\t\tif (object.hasOwnProperty(property) && profile.hasOwnProperty(property)) {\n\t\t\t\tthis.profiles[index][property] = object[property];\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.updateProfileDevices(profile, oldLocations, oldDevices, profile.rooms, profile.devices);\n\t\tthis.emit('profile.updated', profile);\n\t}\n\t\n\tthis.saveConfig(true);\n\treturn this.profiles[index];\n};\n\nAutomationController.prototype.updateProfileAuth = function(object, id) {\n\tvar profile = _.find(this.profiles, function(profile) {\n\t\t\treturn profile.id === parseInt(id);\n\t\t}),\n\t\tindex;\n\n\tif (profile) {\n\t\tindex = this.profiles.indexOf(profile);\n\n\t\tp = this.profiles[index];\n\n\t\tif (object.hasOwnProperty('password') && object.password !== '' && !!object.password) {\n\t\t\tp.salt = generateSalt();\n\t\t\tp.password = hashPassword(object.password, p.salt);\n\t\t}\n\t\tif (object.hasOwnProperty('login') && object.login !== '' && !!object.login) {\n\t\t\tp.login = object.login;\n\t\t}\n\n\t\tthis.saveConfig(true);\n\n\t\treturn p;\n\t} else {\n\t\treturn null;\n\t}\n};\n\nAutomationController.prototype.removeProfile = function(profileId) {\n\tvar that = this;\n\tthis.profiles = this.profiles.filter(function(profile) {\n\t\treturn profile.id !== profileId;\n\t});\n\n\tthis.emit('profile.removed', profileId);\n\t\n\tthis.saveConfig(true);\n};\n\nAutomationController.prototype.removeToken = function(profile, token, skipSave) {\n\tvar indx = -1;\n\t\n\tif (!profile || !profile.authTokens) return false;\n\t\n\tprofile.authTokens.forEach(function(authToken, index) {\n\t\tif (authToken.sid.substr(0, 6) === token.substr(0, 6)) {\n\t\t\tindx = index;\n\t\t}\n\t});\n\t\n\tif (indx !== -1) {\n\t\tprofile.authTokens.splice(indx, 1);\n\t\tif (!skipSave) this.saveConfig(true);\n\t\treturn true;\n\t} else {\n\t\treturn false;\n\t}\n};\n\nAutomationController.prototype.permanentToken = function(profile, token) {\n\tvar self = this;\n\t\n\tif (!profile.authTokens) return false;\n\t\n\tvar found = false;\n\t\n\tprofile.authTokens.forEach(function(authToken, index) {\n\t\tif (authToken.sid.substr(0, 6) === token.substr(0, 6)) {\n\t\t\tauthToken.expire = 0;\n\t\t\tself.saveConfig(true);\n\t\t\tfound = true;\n\t\t}\n\t});\n\t\n\treturn found;\n};\n\nAutomationController.prototype.getIPAddress = function() {\n\ttry {\n\t\tvar ip = fs.loadJSON(\"localIP.json\");\n\t\tif (typeof ip === \"string\") {\n\t\t\treturn ip;\n\t\t}\n\t} catch (e) {\n\t}\n\t\n\ttry {\n\t\tif (checkBoxtype('zme_hub')) {\n\t\t\treturn system(\". /lib/functions/network.sh; network_get_ipaddr ip wan; echo $ip\")[1].replace(/[\\s\\n]/g, '');\n\t\t} else {\n\t\t\treturn system(\"ip a s dev eth0 | sed -n 's/.*inet \\\\([0-9.]*\\\\)\\\\/.*/\\\\1/p' | head -n 1\")[1].replace(/[\\s\\n]/g, '');\n\t\t}\n\t} catch (e) {\n\t\tconsole.log(e);\n\t}\n\n\treturn \"\";\n}\n\nAutomationController.prototype.getMACAddress = function() {\n\tvar mac = \"\";\n\ttry {\n\t\tif (checkBoxtype('zme_hub')) {\n\t\t\tmac = system(\"cat /sys/class/net/eth0/address\")[1].replace(/[\\s\\n]/g, '');\n\t\t} else {\n\t\t\tmac = system(\"cat /sys/class/net/eth0/address\")[1].replace(/[\\s\\n]/g, '');\n\t\t}\n\t} catch (e) {\n\t\tconsole.log(e);\n\t}\n\n\treturn mac;\n}\n\nAutomationController.prototype.getUUID = function() {\n\treturn this.config.uuid;\n}\n\nAutomationController.prototype.getSerial = function() {\n\treturn this.config.serial;\n}\n\nAutomationController.prototype.getQRCodeData = function(profile, password) {\n\tvar data = {\n\t\t\tid: \"\",\n\t\t\tlogin: \"\",\n\t\t\tservice: \"find.z-wave.me\",\n\t\t\tssid: \"\",\n\t\t\tip: \"\",\n\t\t\twpa: \"\",\n\t\t\tpasswd: \"\"\n\t\t},\n\t\turl = \"\",\n\t\tip = \"\";\n\n\tdata.passwd = password;\n\tdata.login = profile.login;\n\tdata.id = this.getRemoteId();\n\n\tip = this.getIPAddress();\n\tif (ip) {\n\t\tdata.ip = ip;\n\t}\n\n\turl = Object.keys(data).map(function(key) {\n\t\treturn encodeURIComponent(key) + '=' + encodeURIComponent(data[key]);\n\t}).join('&');\n\n\turl = Base64.encode(url);\n\n\treturn url;\n}\n\n// namespaces\nAutomationController.prototype.generateNamespaces = function(callback, device, locationNspcOnly) {\n\tvar that = this,\n\t\tdevStillExists = that.devices.get(device.id),\n\t\tlocationNspcOnly = locationNspcOnly ? locationNspcOnly : false,\n\t\tnspcArr = [],\n\t\tlocNspcArr = [],\n\t\tdevLocation = device.get('location'),\n\t\tlocation = that.getLocation(that.locations, devLocation),\n\t\tdevHidden = device.get('permanently_hidden') || device.get('metrics:removed');\n\n\tif (!!location && !location.namespaces) {\n\t\tlocation.namespaces = [];\n\t}\n\n\tif (device) {\n\n\t\tthis.genNspc = function(nspc, vDev) {\n\t\t\tvar devTypeEntry = 'devices_' + vDev.get('deviceType'),\n\t\t\t\tdevProbeType = vDev.get('probeType'),\n\t\t\t\tdevEntry = {\n\t\t\t\t\tdeviceId: vDev.id,\n\t\t\t\t\tdeviceName: vDev.get('metrics:title')\n\t\t\t\t},\n\t\t\t\taddRemoveEntry = function(entryArr) {\n\t\t\t\t\tvar exists = [];\n\n\t\t\t\t\t// check if entry already exists\n\t\t\t\t\texists = _.filter(entryArr, function(entry) {\n\t\t\t\t\t\treturn entry.deviceId === devEntry.deviceId;\n\t\t\t\t\t});\n\n\t\t\t\t\tif (!!devStillExists && exists.length < 1 && !devHidden) {\n\t\t\t\t\t\t// add entry\n\t\t\t\t\t\tentryArr.push(devEntry);\n\t\t\t\t\t} else if (!!devStillExists && exists[0] && !devHidden) {\n\t\t\t\t\t\t// change existing deviceName\n\t\t\t\t\t\tif (!_.isEqual(exists[0]['deviceName'], devEntry['deviceName'])) {\n\t\t\t\t\t\t\texists[0]['deviceName'] = devEntry['deviceName'];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (devStillExists === null || devHidden) {\n\t\t\t\t\t\t// remove entry\n\t\t\t\t\t\tentryArr = _.filter(entryArr, function(entry) {\n\t\t\t\t\t\t\treturn entry.deviceId !== devEntry.deviceId;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\treturn entryArr;\n\t\t\t\t},\n\t\t\t\tdeleteEmptyProp = function(object, key) {\n\t\t\t\t\t// delete empty CC type entries\n\t\t\t\t\tif ((_.isArray(object[key]) && object[key].length < 1) || (!_.isArray(object[key]) && Object.keys(object[key]).length < 1)) {\n\t\t\t\t\t\tdelete object[key];\n\t\t\t\t\t}\n\t\t\t\t\treturn object;\n\t\t\t\t},\n\t\t\t\tcutType = [],\n\t\t\t\tcutSubType = '',\n\t\t\t\tparamEntry;\n\n\t\t\t// check for type entry\n\t\t\ttypeEntryExists = _.filter(nspc, function(typeEntry) {\n\t\t\t\treturn typeEntry.id === devTypeEntry;\n\t\t\t});\n\n\t\t\tif (typeEntryExists.length > 0) {\n\t\t\t\tparamEntry = typeEntryExists[0] && typeEntryExists[0].params ? typeEntryExists[0].params : paramEntry;\n\t\t\t}\n\n\t\t\t// generate probetype entries\n\t\t\tif (devProbeType !== '') {\n\t\t\t\tcutType = devProbeType === 'general_purpose' ? devProbeType.split() : devProbeType.split('_'),\n\t\t\t\t\t// sub type includes whole probeType after first '_'\n\t\t\t\t\tcutSubType = devProbeType.substr(cutType[0].length + 1);\n\n\t\t\t\tparamEntry = paramEntry ? paramEntry : {};\n\n\t\t\t\t// create 'none' entry to get an object with array of 'none probetype' entries\n\t\t\t\tif (_.isArray(paramEntry)) {\n\t\t\t\t\tparamEntry = {\n\t\t\t\t\t\tnone: paramEntry\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// check for CC sub type and add device namespaces\n\t\t\t\tif (cutType.length > 1) {\n\n\t\t\t\t\t// add CC type\n\t\t\t\t\tif (!paramEntry[cutType[0]]) {\n\t\t\t\t\t\tparamEntry[cutType[0]] = {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// add subtype\n\t\t\t\t\tif (!paramEntry[cutType[0]][cutSubType]) {\n\t\t\t\t\t\tparamEntry[cutType[0]][cutSubType] = [];\n\t\t\t\t\t}\n\n\t\t\t\t\t//check if entry is already there\n\t\t\t\t\tparamEntry[cutType[0]][cutSubType] = addRemoveEntry(paramEntry[cutType[0]][cutSubType]);\n\n\t\t\t\t\t// delete empty suptype entries\n\t\t\t\t\tparamEntry[cutType[0]] = deleteEmptyProp(paramEntry[cutType[0]], cutSubType);\n\n\t\t\t\t\t// add CC type\n\t\t\t\t} else {\n\t\t\t\t\tif (!paramEntry[cutType[0]]) {\n\t\t\t\t\t\tparamEntry[cutType[0]] = [];\n\t\t\t\t\t}\n\n\t\t\t\t\t//check if entry is already there\n\t\t\t\t\tparamEntry[cutType[0]] = addRemoveEntry(paramEntry[cutType[0]]);\n\t\t\t\t}\n\n\t\t\t\t// remove CC if empty\n\t\t\t\tparamEntry = deleteEmptyProp(paramEntry, cutType[0]);\n\n\t\t\t} else {\n\t\t\t\t// add entries to type entries\n\t\t\t\tparamEntry = paramEntry ? paramEntry : [];\n\n\t\t\t\t// create 'none' entry to get an object with array of 'none probetype' entries\n\t\t\t\tif (_.isArray(paramEntry)) {\n\t\t\t\t\tparamEntry = {\n\t\t\t\t\t\tnone: paramEntry\n\t\t\t\t\t};\n\t\t\t\t} else if (!_.isArray(paramEntry) && devProbeType === '') {\n\t\t\t\t\tparamEntry['none'] = paramEntry['none'] ? paramEntry['none'] : [];\n\t\t\t\t}\n\t\t\t\tparamEntry.none = addRemoveEntry(paramEntry.none);\n\t\t\t}\n\n\t\t\t// delete 'none' entry if it exists as a single entry\n\t\t\tif (!_.isArray(paramEntry) && Object.keys(paramEntry).length === 1 && paramEntry['none']) {\n\t\t\t\tparamEntry = paramEntry['none'];\n\t\t\t}\n\n\t\t\t// set namespaces\n\t\t\tthat.setNamespace(devTypeEntry, nspc, paramEntry);\n\n\t\t\t// check for 'devices_all'\n\t\t\tdevicesAll = _.filter(nspc, function(entries) {\n\t\t\t\treturn entries.id === 'devices_all';\n\t\t\t});\n\n\t\t\t// add 'devices_all' with entries\n\t\t\tif (devicesAll.length < 1) {\n\t\t\t\tthat.setNamespace('devices_all', nspc, [devEntry]);\n\t\t\t} else if (devicesAll[0].params && _.isArray(devicesAll[0].params)) {\n\t\t\t\t// check if entry is already there\n\t\t\t\t// add/remove entry to/from devices_all\n\t\t\t\tdevicesAll[0].params = addRemoveEntry(devicesAll[0].params);\n\t\t\t}\n\n\t\t\treturn nspc;\n\t\t};\n\n\t\t// only triggered if there is no explicite location change -\n\t\t// on device: created, removed, destroy, change:metrics:title, change:permanently_hidden, change:metrics:removed\n\t\t// usual update of global namespaces\n\t\t// first setup of location namespace\n\t\tif (!locationNspcOnly) {\n\n\t\t\t// add to location namespaces\n\t\t\tif (!!location) {\n\t\t\t\t_.forEach(that.locations, function(l) {\n\t\t\t\t\tif (l.id === devLocation) {\n\t\t\t\t\t\t// add to namespace\n\t\t\t\t\t\tl.namespaces = that.genNspc(location.namespaces, device);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// update global namespaces\n\t\t\tnspcArr = that.genNspc(that.namespaces, device);\n\n\t\t\tif (typeof callback === 'function') {\n\t\t\t\tcallback(nspcArr);\n\t\t\t}\n\n\t\t\t// if location of device has changed\n\t\t\t// on device: change:location\n\t\t\t// update namespaces for location if necessary\n\t\t} else {\n\t\t\t_.forEach(that.locations, function(l) {\n\t\t\t\tif (!l.namespaces) {\n\t\t\t\t\tl.namespaces = [];\n\t\t\t\t}\n\n\t\t\t\tif (l.id === devLocation) {\n\t\t\t\t\t// if device is assigned to location add to namespace\n\t\t\t\t\tdevStillExists = that.devices.get(device.id);\n\t\t\t\t\tl.namespaces = that.genNspc(l.namespaces, device);\n\t\t\t\t} else {\n\t\t\t\t\t// remove from the other namespaces\n\t\t\t\t\tdevStillExists = null;\n\t\t\t\t\tl.namespaces = that.genNspc(l.namespaces, device);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (typeof callback === 'function') {\n\t\t\t\tcallback(locNspcArr);\n\t\t\t}\n\t\t}\n\n\t} else {\n\t\tif (typeof callback === 'function') {\n\t\t\tcallback(nspcArr);\n\t\t}\n\t}\n};\n\nAutomationController.prototype.getListNamespaces = function(path, namespacesObj, setLocationTitle) {\n\tvar self = this,\n\t\tresult = [],\n\t\tnamespaces = namespacesObj,\n\t\tpath = path || null,\n\t\tpathArr = [],\n\t\tnamespacesPath = '',\n\t\tnspc,\n\t\tv = setLocationTitle ? setLocationTitle : false;\n\n\tthis.getNspcDevAll = function(nspcObj) {\n\t\tvar devicesAll = [],\n\t\t\tobj = {};\n\n\t\tif (_.isArray(nspcObj)) {\n\t\t\tnspcObj.forEach(function(nspcEntry) {\n\t\t\t\tif (!~devicesAll.indexOf(nspcEntry)) {\n\t\t\t\t\tdevicesAll.push(nspcEntry);\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tfor (var prop in nspcObj) {\n\t\t\t\tdevicesAll = devicesAll.concat(self.getNspcDevAll(nspcObj[prop]));\n\t\t\t}\n\t\t}\n\n\t\treturn devicesAll;\n\t};\n\n\t// map all entries (deviceName, deviceId)\n\t// if deviceName add also location title\n\tmapEntries = function(list) {\n\t\t// return list of entries\n\t\treturn _.map(list, function(entry) {\n\t\t\tvar locationTitle = '';\n\n\t\t\tif (setLocationTitle && 0) { // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\t\t\t\tvar vDev = self.devices.get(entry.deviceId),\n\t\t\t\t\tlocation = self.getLocation(self.locations, vDev.get('location'));\n\n\t\t\t\tlocationTitle = currPath === 'deviceName' && !!location && location && location.title !== 'globalRoom' ? location.title.toUpperCase() + ' - ' : '';\n\t\t\t}\n\n\t\t\treturn locationTitle + entry[currPath];\n\t\t});\n\t};\n\n\tif (!!path && namespaces) {\n\n\t\tpathArr = path.split('.');\n\n\t\t// add 'params' to path array if neccessary\n\t\tif (pathArr.length > 1 && pathArr.indexOf('params') === -1) {\n\t\t\tpathArr.splice(1, 0, 'params');\n\t\t}\n\n\t\t// filter for type\n\t\tnspc = namespaces.filter(function(namespace) {\n\t\t\treturn namespace.id === pathArr[0];\n\t\t})[0];\n\n\t\t//nspc = nspc[0]? nspc[0] : nspc;\n\n\t\t// get object/array by path\n\t\tif (nspc && pathArr.length > 1) {\n\t\t\tvar shift = 1;\n\t\t\tfor (var i = 0; i < pathArr.length; i++) {\n\t\t\t\tvar currPath = pathArr[i + shift],\n\t\t\t\t\tobj = {},\n\t\t\t\t\tlastPath = ['deviceId', 'deviceName', 'channelId', 'channelName', 'channelNameEx'];\n\t\t\t\t\n\t\t\t\tif (nspc[currPath]) {\n\t\t\t\t\tnspc = nspc[currPath];\n\t\t\t\t\tresult = nspc;\n\n\t\t\t\t} else if (!nspc[currPath] && ~lastPath.indexOf(currPath)) {\n\t\t\t\t\tresult = self.getNspcDevAll(nspc);\n\n\t\t\t\t\tresult = mapEntries(result);\n\t\t\t\t\t// add backward compatibility\n\t\t\t\t} else if (~lastPath.indexOf(currPath)) {\n\n\t\t\t\t\tif (_.isArray(nspc)) {\n\t\t\t\t\t\t// map all device id's or device names\n\t\t\t\t\t\tresult = mapEntries(nspc);\n\t\t\t\t\t}\n\t\t\t\t} else if (!nspc[currPath] && nspc['devices_all'] && i < 1) {\n\t\t\t\t\tnspc = nspc['devices_all'];\n\t\t\t\t\tresult = nspc;\n\t\t\t\t\t// change shift to get last path entry\n\t\t\t\t\tshift = 0;\n\t\t\t\t} else if (currPath && !nspc[currPath] && i > 0) {\n\t\t\t\t\tnspc = [];\n\t\t\t\t\tresult = nspc;\n\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (currPath) {\n\t\t\t\t\tresult = nspc;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tresult = nspc && nspc['params'] ? nspc['params'] : nspc; // if not return undefined\n\t\t}\n\n\t} else {\n\t\tresult = namespaces;\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.setNamespace = function(id, namespacesArr, data) {\n\tvar result = null,\n\t\tnamespace,\n\t\tindex;\n\n\tid = id || null;\n\n\tif (id && this.getListNamespaces(id, namespacesArr)) {\n\t\tnamespace = _.findWhere(namespacesArr, {\n\t\t\tid: id\n\t\t});\n\t\tif (!!namespace) {\n\t\t\tindex = namespacesArr.indexOf(namespace);\n\n\t\t\t// remove entry if data is empty\n\t\t\tif (~index && (_.isArray(data) && data.length < 1) || ((!_.isArray(data)) && Object.keys(data).length < 1)) {\n\t\t\t\tnamespacesArr = namespacesArr.splice(index, 1);\n\t\t\t\tresult = namespacesArr;\n\t\t\t} else {\n\t\t\t\tnamespacesArr[index].params = data;\n\t\t\t\tresult = namespacesArr[index];\n\t\t\t}\n\t\t}\n\t} else if ((_.isArray(data) && data.length > 0) || ((!_.isArray(data)) && Object.keys(data).length > 0)) {\n\t\tnamespacesArr.push({\n\t\t\tid: id,\n\t\t\tparams: data\n\t\t});\n\t\tresult = null;\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.getListModulesCategories = function(id) {\n\tvar result = null,\n\t\tcategories = this.modules_categories;\n\n\tif (Boolean(id)) {\n\t\tresult = _.find(categories, function(category) {\n\t\t\treturn category.id === id;\n\t\t});\n\t} else {\n\t\tresult = categories;\n\t}\n\n\treturn result;\n};\n\n\nAutomationController.prototype.applyLanguage = function(template, language) {\n\tif (language === null) return template;\n\tObject.keys(language).forEach(function(key) {\n\t\tvar regExp = new RegExp('__' + key + '__', 'g');\n\t\tif (language[key]) {\n\t\t\ttemplate = template.replace(regExp, language[key]);\n\t\t}\n\t});\n\t\n\treturn template;\n};\n\nAutomationController.prototype.getModuleData = function(moduleName) {\n\tvar\n\t\tdefaultLang = this.defaultLang,\n\t\tmoduleMeta = this.modules[moduleName] && this.modules[moduleName].meta || null,\n\t\tlanguageFile = this.loadModuleLang(moduleName),\n\t\tdata = {};\n\n\tif (!this.modules[moduleName]) {\n\t\treturn {}; // module not found (deleted from filesystem or broken?), return empty meta\n\t}\n\n\ttry {\n\t\tmetaStringify = JSON.stringify(moduleMeta);\n\t} catch (e) {\n\t\ttry {\n\t\t\tmetaStringify = JSON.stringify(fs.loadJSON('modules/' + moduleName + '/module.json'));\n\t\t} catch (e) {\n\t\t\ttry {\n\t\t\t\tmetaStringify = JSON.stringify(fs.loadJSON('userModules/' + moduleName + '/module.json'));\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log('Cannot load lang file from module ' + moduleName + '. ERROR: ' + e);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (languageFile !== null) {\n\t\tmetaStringify = this.applyLanguage(metaStringify, languageFile);\n\t\tdata = JSON.parse(metaStringify);\n\t} else {\n\t\tdata = this.modules[moduleName].meta;\n\t}\n\n\treturn data;\n};\n\nAutomationController.prototype.replaceNamespaceFilters = function(moduleMeta) {\n\tvar self = this,\n\t\tmoduleMeta = moduleMeta || null,\n\t\tlangFile = this.loadMainLang();\n\n\t// loop through object\n\tfunction replaceNspcFilters(moduleMeta, obj, keys) {\n\t\tvar objects = [];\n\n\t\tfor (var i in obj) {\n\t\t\tif (obj && !obj[i]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif ((i === 'properties' || i === 'fields') && typeof obj[i] === 'object' && obj[i]['room'] && obj[i]['devicesByRoom']) {\n\t\t\t\tvar k = _.keys(obj[i])\n\t\t\t\tnewObj = {};\n\n\t\t\t\ttry {\n\t\t\t\t\t// overwrite old key with new namespaces array\n\t\t\t\t\tif (i === 'properties') {\n\t\t\t\t\t\tconsole.log(\"Room - Device relation found, try to preparate JSON's schema structure ...\");\n\n\t\t\t\t\t\tvar dSRoom = _.extend({\n\t\t\t\t\t\t\t\t\"type\": \"\",\n\t\t\t\t\t\t\t\t\"field\": \"\",\n\t\t\t\t\t\t\t\t\"datasource\": \"\",\n\t\t\t\t\t\t\t\t\"enum\": \"\",\n\t\t\t\t\t\t\t\t\"title\": \"\"\n\t\t\t\t\t\t\t}, obj[i]['room']),\n\t\t\t\t\t\t\tdSDevByRoom = _.extend({\n\t\t\t\t\t\t\t\t\"type\": \"\",\n\t\t\t\t\t\t\t\t\"datasource\": \"\",\n\t\t\t\t\t\t\t\t\"enum\": \"\",\n\t\t\t\t\t\t\t\t\"title\": \"\",\n\t\t\t\t\t\t\t\t\"dependencies\": \"\"\n\t\t\t\t\t\t\t}, obj[i]['devicesByRoom']);\n\n\t\t\t\t\t\tif (dSRoom['enum'] && !_.isArray(dSRoom['enum'])) {\n\t\t\t\t\t\t\tdSRoom['enum'] = getNspcFromFilters(moduleMeta, dSRoom['enum']);\n\n\t\t\t\t\t\t\tobj[i]['room'] = dSRoom;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (dSDevByRoom['enum'] && !_.isArray(dSDevByRoom['enum']) && _.isArray(dSRoom['enum'])) {\n\t\t\t\t\t\t\tvar path = dSDevByRoom['enum'].substring(21).replace(/:/gi, '.');\n\t\t\t\t\t\t\tif (k.length > 0) {\n\t\t\t\t\t\t\t\tk.forEach(function(key) {\n\t\t\t\t\t\t\t\t\tif (key === 'devicesByRoom') {\n\t\t\t\t\t\t\t\t\t\tdSRoom['enum'].forEach(function(roomId, index) {\n\t\t\t\t\t\t\t\t\t\t\tvar locNspc = [],\n\t\t\t\t\t\t\t\t\t\t\t\tnspc = [];\n\n\t\t\t\t\t\t\t\t\t\t\tlocation = self.getLocation(self.locations, roomId);\n\n\t\t\t\t\t\t\t\t\t\t\tif (!!location) {\n\t\t\t\t\t\t\t\t\t\t\t\tnspc = self.getListNamespaces(path, location.namespaces);\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tdSDevByRoom['enum'] = nspc && nspc.length > 0 ? nspc : [langFile.no_devices_found];\n\t\t\t\t\t\t\t\t\t\t\tdSDevByRoom['dependencies'] = \"room\";\n\n\t\t\t\t\t\t\t\t\t\t\tnewObj['devicesByRoom_' + roomId] = _.clone(dSDevByRoom);\n\t\t\t\t\t\t\t\t\t\t\tif (newObj['devicesByRoom_' + roomId]['title']) {\n\t\t\t\t\t\t\t\t\t\t\t\tnewObj['devicesByRoom_' + roomId]['title'] = newObj['devicesByRoom_' + roomId]['title'] + '_' + roomId;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewObj[key] = obj[i][key];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tobj[i] = newObj;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconsole.log(\"Room - Device relation found, try to preparate JSON's options structure ...\");\n\n\t\t\t\t\t\tvar dSRoom = _.extend({\n\t\t\t\t\t\t\t\t\"type\": \"\",\n\t\t\t\t\t\t\t\t\"field\": \"\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"\"\n\t\t\t\t\t\t\t}, obj[i]['room']),\n\t\t\t\t\t\t\tdSDevByRoom = _.extend({\n\t\t\t\t\t\t\t\t\"dependencies\": {},\n\t\t\t\t\t\t\t\t\"type\": \"\",\n\t\t\t\t\t\t\t\t\"field\": \"\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"\"\n\t\t\t\t\t\t\t}, obj[i]['devicesByRoom']);\n\n\t\t\t\t\t\tif (dSRoom['optionLabels'] && !_.isArray(dSRoom['optionLabels'])) {\n\t\t\t\t\t\t\tdSRoom['optionLabels'] = getNspcFromFilters(moduleMeta, dSRoom['optionLabels']);\n\n\t\t\t\t\t\t\tobj[i]['room'] = dSRoom;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (dSDevByRoom['optionLabels'] && !_.isArray(dSDevByRoom['optionLabels']) && _.isArray(dSRoom['optionLabels'])) {\n\t\t\t\t\t\t\tvar path = dSDevByRoom['optionLabels'].substring(21).replace(/:/gi, '.');\n\t\t\t\t\t\t\tif (k.length > 0) {\n\t\t\t\t\t\t\t\tk.forEach(function(key) {\n\t\t\t\t\t\t\t\t\tif (key === 'devicesByRoom') {\n\t\t\t\t\t\t\t\t\t\tdSRoom['optionLabels'].forEach(function(roomName, index) {\n\n\t\t\t\t\t\t\t\t\t\t\tvar locNspc = [],\n\t\t\t\t\t\t\t\t\t\t\t\tnspc = [],\n\t\t\t\t\t\t\t\t\t\t\t\tlocationId;\n\n\t\t\t\t\t\t\t\t\t\t\tlocation = self.locations.filter(function(location) {\n\t\t\t\t\t\t\t\t\t\t\t\treturn location.title === roomName\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\tlocationId = location[0] ? location[0].id : location.id;\n\n\t\t\t\t\t\t\t\t\t\t\tif (location[0]) {\n\t\t\t\t\t\t\t\t\t\t\t\tnspc = self.getListNamespaces(path, location[0].namespaces);\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\tdSDevByRoom['optionLabels'] = nspc && nspc.length > 0 ? nspc : [langFile.no_devices_found];\n\t\t\t\t\t\t\t\t\t\t\tdSDevByRoom['dependencies'] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\"room\": locationId\n\t\t\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t\t\t\t\tnewObj['devicesByRoom_' + locationId] = _.clone(dSDevByRoom);\n\n\t\t\t\t\t\t\t\t\t\t\tif (newObj['devicesByRoom_' + locationId]['label']) {\n\t\t\t\t\t\t\t\t\t\t\t\tnewObj['devicesByRoom_' + locationId]['label'] = newObj['devicesByRoom_' + locationId]['label'] + '_' + locationId;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewObj[key] = obj[i][key];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tobj[i] = newObj;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.log('Cannot prepare Room-Device related JSON structure. ERROR: ' + e);\n\t\t\t\t\tself.addNotification('warning', langFile.err_preparing_room_dev_structure, 'module', moduleMeta.id);\n\t\t\t\t}\n\n\t\t\t\t// try to replace the other stuff\n\t\t\t\tfor (var key in obj[i]) {\n\t\t\t\t\t_.each(obj[i][key], function(p, index) {\n\t\t\t\t\t\tif (~keys.indexOf(index) && !_.isArray(p)) {\n\t\t\t\t\t\t\tobj[i][key][index] = getNspcFromFilters(moduleMeta, obj[i][key][index]);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (typeof obj[i] === 'object') {\n\t\t\t\tobjects = objects.concat(replaceNspcFilters(moduleMeta, obj[i], keys));\n\t\t\t} else if (keys.indexOf(i) > -1 && !_.isArray(obj[i])) {\n\t\t\t\t// overwrite old key with new namespaces array\n\t\t\t\tobj[i] = getNspcFromFilters(moduleMeta, obj[i]);\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t};\n\n\t// generate namespace arry from filter string\n\tfunction getNspcFromFilters(moduleMeta, nspcfilters) {\n\t\tvar namespaces = [],\n\t\t\tfilters = nspcfilters.split(','),\n\t\t\tapis = ['locations', 'users', 'namespaces', 'loadFunction'],\n\t\t\tfilteredDev = [];\n\n\t\ttry {\n\n\t\t\tif (!_.isArray(filters)) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// do it for each filter\n\t\t\t_.forEach(filters, function(flr, i) {\n\t\t\t\tvar id = flr.split(':'),\n\t\t\t\t\tpath;\n\n\t\t\t\tif (apis.indexOf(id[0]) > -1) {\n\n\t\t\t\t\t// get location ids or titles - except location 0/globalRoom - 'locations:id' or 'locations:title'\n\t\t\t\t\t// should allow dynamic filtering per location\n\t\t\t\t\tif (id[0] === 'locations' && (id[1] === 'id' || id[1] === 'title')) {\n\t\t\t\t\t\tnamespaces = _.filter(self.locations, function(location) {\n\t\t\t\t\t\t\treturn location[id[1]] !== 0 && location[id[1]] !== 'globalRoom';\n\t\t\t\t\t\t}).map(function(location) {\n\t\t\t\t\t\t\treturn location[id[1]];\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// get namespaces of users - 'users:id' or 'users:title'\n\t\t\t\t\t} else if (id[0] === 'users' && (id[1] === 'id' || id[1] === 'title')) {\n\t\t\t\t\t\tnamespaces = _.map(self.profiles, function(profile) {\n\t\t\t\t\t\t\treturn profile[id[1] === 'id' ? 'id' : 'name'];\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t// get namespaces of devices per location - 'locations:locationId:filterPath'\n\t\t\t\t\t} else if (id[0] === 'locations' && id[1] === 'locationId') {\n\t\t\t\t\t\t// don't replace set filters instead\n\t\t\t\t\t\tnamespaces = nspcfilters;\n\n\t\t\t\t\t\t// load function from file\n\t\t\t\t\t} else if (id[0] === 'loadFunction') {\n\t\t\t\t\t\tvar filePath = moduleMeta.location + '/htdocs/js/' + id[1],\n\t\t\t\t\t\t\tjsFile = fs.stat(filePath);\n\n\t\t\t\t\t\tif (id[1] && jsFile && jsFile.type === 'file') {\n\t\t\t\t\t\t\tjsFile = fs.load(filePath);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (moduleMeta.moduleName) {\n\t\t\t\t\t\t\t\tjsFile = this.controller.applyLanguage(jsFile, this.controller.loadModuleLang(moduleMeta.moduleName));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!!jsFile) {\n\t\t\t\t\t\t\t\t//compress string\n\t\t\t\t\t\t\t\tnamespaces = jsFile.replace(/\\s\\s+|\\t/g, ' ');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// get namespaces of devices ignoring locations\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// cut path\n\t\t\t\t\t\tpath = flr.substring(id[0].length + 1).replace(/:/gi, '.');\n\n\t\t\t\t\t\t// get namespaces\n\t\t\t\t\t\tnspc = self.getListNamespaces(path, self.namespaces, true);\n\t\t\t\t\t\tif (nspc) {\n\t\t\t\t\t\t\tnamespaces = namespaces.concat(nspc);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn namespaces;\n\n\t\t} catch (e) {\n\t\t\tconsole.log('Cannot parse filters > ' + nspcfilters + ' < from namespaces. ERROR: ' + e);\n\t\t\tself.addNotification('warning', langFile.err_parsing_npc_filters, 'module', moduleMeta.id);\n\n\t\t\treturn namespaces;\n\t\t}\n\t};\n\n\tif (!!moduleMeta) {\n\t\tvar params = {\n\t\t\tschema: ['enum'],\n\t\t\toptions: ['optionLabels', 'onFieldChange', 'click'],\n\t\t\tpostRender: ''\n\t\t};\n\n\t\t// transform filters\n\t\tfor (var property in params) {\n\t\t\tif (property === 'postRender' && moduleMeta[property] && !_.isArray(moduleMeta[property])) {\n\t\t\t\tmoduleMeta[property] = getNspcFromFilters(moduleMeta, moduleMeta[property]);\n\t\t\t} else if (moduleMeta[property]) {\n\t\t\t\tmoduleMeta[property] = replaceNspcFilters(moduleMeta, moduleMeta[property], params[property]);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn moduleMeta;\n};\n\n// load module lang folder\nAutomationController.prototype.loadModuleLang = function(moduleId) {\n\tvar moduleMeta = this.modules[moduleId] && this.modules[moduleId].meta || null,\n\t\tlanguageFile = null;\n\n\tif (!!moduleMeta) {\n\t\tlanguageFile = this.loadMainLang(moduleMeta.location + '/');\n\t}\n\n\treturn languageFile;\n};\n\n// load lang folder with given prefix\nAutomationController.prototype.loadMainLang = function(pathPrefix) {\n\tvar self = this,\n\t\tlanguageFile = null,\n\t\tprefix;\n\n\tif (pathPrefix === undefined || pathPrefix === null) {\n\t\tprefix = '';\n\t} else {\n\t\tprefix = pathPrefix;\n\t}\n\n\ttry {\n\t\tlanguageFile = fs.loadJSON(prefix + \"lang/\" + self.defaultLang + \".json\");\n\t} catch (e) {\n\t\ttry {\n\t\t\tlanguageFile = fs.loadJSON(prefix + \"lang/en.json\");\n\t\t} catch (e) {\n\t\t\tlanguageFile = null;\n\t\t}\n\t}\n\n\treturn languageFile;\n};\n\nAutomationController.prototype.loadModuleMedia = function(moduleName, fileName) {\n\tvar contentTypes = {\n\t\t\t\"png\": \"image/png\",\n\t\t\t\"jpg\": \"image/jpeg\",\n\t\t\t\"jpeg\": \"image/jpeg\",\n\t\t\t\"gif\": \"image/gif\",\n\t\t\t\"svg\": \"image/svg+xml\",\n\t\t\t\n\t\t\t\"css\": \"text/css\",\n\t\t\t\"js\": \"text/javascript\",\n\t\t\t\"txt\": \"text/txt\",\n\t\t\t\"rtf\": \"text/rtf\",\n\t\t\t\"xml\": \"text/xml\",\n\t\t\t\n\t\t\t\"htm\": \"text/htm\",\n\t\t\t\"html\": \"text/html\",\n\t\t\t\"shtml\": \"text/shtml\",\n\t\t\t\n\t\t\t\"mpeg\": \"video/mpeg\",\n\t\t\t\"mpg\": \"video/mpg\",\n\t\t\t\"mpe\": \"video/mpe\",\n\t\t\t\"qt\": \"video/qt\",\n\t\t\t\"mov\": \"video/mov\",\n\t\t\t\"viv\": \"video/viv\",\n\t\t\t\"vivo\": \"video/vivo\",\n\t\t\t\"avi\": \"video/avi\",\n\t\t\t\"movie\": \"video/movie\",\n\t\t\t\"mp4\": \"video/mp4\",\n\t\t\t\n\t\t\t\"doc\": \"application/msword\",\n\t\t\t\"dot\": \"application/msword\",\n\t\t\t\"docx\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n\t\t\t\"dotx\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.template\",\n\t\t\t\"docm\": \"application/vnd.ms-word.document.macroEnabled.12\",\n\t\t\t\"dotm\": \"application/vnd.ms-word.template.macroEnabled.12\",\n\t\t\t\"xls\": \"application/vnd.ms-excel\",\n\t\t\t\"xlt\": \"application/vnd.ms-excel\",\n\t\t\t\"xla\": \"application/vnd.ms-excel\",\n\t\t\t\"xlsx\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n\t\t\t\"xltx\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.template\",\n\t\t\t\"xlsm\": \"application/vnd.ms-excel.sheet.macroEnabled.12\",\n\t\t\t\"xltm\": \"application/vnd.ms-excel.template.macroEnabled.12\",\n\t\t\t\"xlam\": \"application/vnd.ms-excel.addin.macroEnabled.12\",\n\t\t\t\"xlsb\": \"application/vnd.ms-excel.sheet.binary.macroEnabled.12\",\n\t\t\t\"ppt\": \"application/vnd.ms-powerpoint\",\n\t\t\t\"pot\": \"application/vnd.ms-powerpoint\",\n\t\t\t\"pps\": \"application/vnd.ms-powerpoint\",\n\t\t\t\"ppa\": \"application/vnd.ms-powerpoint\",\n\t\t\t\"pptx\": \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n\t\t\t\"potx\": \"application/vnd.openxmlformats-officedocument.presentationml.template\",\n\t\t\t\"ppsx\": \"application/vnd.openxmlformats-officedocument.presentationml.slideshow\",\n\t\t\t\"ppam\": \"application/vnd.ms-powerpoint.addin.macroEnabled.12\",\n\t\t\t\"pptm\": \"application/vnd.ms-powerpoint.presentation.macroEnabled.12\",\n\t\t\t\"potm\": \"application/vnd.ms-powerpoint.presentation.macroEnabled.12\",\n\t\t\t\"ppsm\": \"application/vnd.ms-powerpoint.slideshow.macroEnabled.12\",\n\t\t},\n\t\tfe,\n\t\tresObject = {\n\t\t\tdata: null,\n\t\t\tct: null\n\t\t};\n\n\ttry {\n\t\tfe = fileName.split(\".\").pop().toLowerCase();\n\t\tresObject.ct = contentTypes[fe] || \"text/plain\";\n\t\t\n\t\ttry {\n\t\t\tresObject.data = fs.load('userModules/' + moduleName + '/htdocs/' + fileName);\n\t\t} catch (e) {\n\t\t\tresObject.data = fs.load('modules/' + moduleName + '/htdocs/' + fileName);\n\t\t}\n\t} catch (e) {\n\t\tresObject = null;\n\t}\n\t\n\treturn resObject;\n};\n\nAutomationController.prototype.loadImage = function(fileName) {\n\tvar data = null,\n\t\timg = loadObject(fileName);\n\n\tif (!!img) {\n\t\tdata = Base64.decode(img);\n\t}\n\n\treturn data;\n};\n\nAutomationController.prototype.hashCode = function(str) {\n\tvar hash = 0,\n\t\ti, chr, len;\n\tif (this.length === 0) {\n\t\treturn hash;\n\t}\n\tfor (i = 0, len = str.length; i < len; i++) {\n\t\tchr = str.charCodeAt(i);\n\t\thash = ((hash << 5) - hash) + chr;\n\t\thash = hash & hash; // Convert to 32bit integer\n\t}\n\treturn hash;\n};\n\nAutomationController.prototype.createBackup = function() {\n\tvar self = this,\n\t\tbackupJSON = {},\n\t\tuserModules = [],\n\t\tskins = [],\n\t\tresult = null;\n\n\tvar list = __storageContent,\n\t\texcludedFiles = this.getIgnoredStorageFiles();\n\n\ttry {\n\t\t// save all objects in storage\n\t\tfor (var ind in list) {\n\t\t\tif (excludedFiles.indexOf(list[ind]) === -1) {\n\t\t\t\tbackupJSON[list[ind]] = loadObject(list[ind]);\n\t\t\t}\n\t\t}\n\n\t\t// add list of current userModules\n\t\t_.forEach(fs.list('userModules') || [], function(moduleName) {\n\t\t\tif (fs.stat('userModules/' + moduleName).type === 'dir' && !_.findWhere(userModules, {\n\t\t\t\t\tname: moduleName\n\t\t\t\t})) {\n\t\t\t\tuserModules.push({\n\t\t\t\t\tname: moduleName,\n\t\t\t\t\tversion: self.modules[moduleName] ? self.modules[moduleName].meta.version : ''\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tif (userModules.length > 0) {\n\t\t\tbackupJSON['__userModules'] = userModules;\n\t\t}\n\n\t\t// add list of current skins excluding default skin\n\t\t_.forEach(this.skins, function(skin) {\n\t\t\tif (skins.indexOf(skin) === -1 && skin.name !== 'default') {\n\t\t\t\tskins.push({\n\t\t\t\t\tname: skin.name,\n\t\t\t\t\tversion: skin.version\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\tif (skins.length > 0) {\n\t\t\tbackupJSON['__userSkins'] = skins;\n\t\t}\n\n\t\t/*\n\t\t //TODO icon backup\n\t\t var ret = \"in progress\";\n\t\t iconinstaller.backup(\n\t\t function(backup) {\n\t\t\t console.log(\"success\", backup);\n\t\t\t console.log(\"success length\", backup.length);\n\t\t\t ret =  new Uint8Array(backup);\n\t\t\t }, function(error){\n\t\t\t console.log(\"error\", error);\n\t\t\t ret = \"failed\";\n\t\t });\n\n\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\twhile (Date.now() < d &&  ret === \"in progress\") {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\t console.log(ret);\n\t\t if(ret !== \"failed\") {\n\t\t\t var bcp = \"\";\n\t\t\t console.log(ret.length);\n\t\t\t for(var i = 0; i < ret.length; i++) {\n\t\t\t bcp += String.fromCharCode(ret[i]);\n\t\t\t }\n\n\t\t\t backupJSON[\"__Icons\"] = bcp;\n\t\t }\n\t\t*/\n\n\t\t// save Z-Way, Zigbee and EnOcean objects\n\t\tif (!!global.ZWave) {\n\t\t\tbackupJSON[\"__ZWay\"] = {};\n\t\t\tglobal.ZWave.list().forEach(function(zwayName) {\n\t\t\t\tvar bcp = \"\",\n\t\t\t\t\tdata = new Uint8Array(global.ZWave[zwayName].zway.controller.Backup());\n\n\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\tbcp += String.fromCharCode(data[i]);\n\t\t\t\t}\n\n\t\t\t\tbackupJSON[\"__ZWay\"][zwayName] = bcp;\n\t\t\t});\n\t\t}\n\t\t\n\t\t/* TODO\n\t\tif (!!global.Zigbee) {\n\t\t\tbackupJSON[\"__ZBee\"] = {};\n\t\t\tglobal.Zigbee.list().forEach(function(zbeeName) {\n\t\t\t\tvar bcp = \"\",\n\t\t\t\t\tdata = new Uint8Array(global.Zigbee[zbeeName].zbee.controller.Backup());\n\n\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\tbcp += String.fromCharCode(data[i]);\n\t\t\t\t}\n\n\t\t\t\tbackupJSON[\"__ZBee\"][zbeeName] = bcp;\n\t\t\t});\n\t\t}\n\t\t*/\n\n\t\t/* TODO\n\t\t if (!!global.EnOcean) {\n\t\t backupJSON[\"__EnOcean\"] = {};\n\t\t global.EnOcean.list().forEach(function(zenoName) {\n\t\t // backupJSON[\"__EnOcean\"][zenoName] = global.EnOcean[zenoName].zeno.controller.Backup();\n\t\t });\n\t\t }\n\t\t */\n\n\t\tresult = backupJSON;\n\t} catch (e) {\n\t\tthrow e.toString();\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.getRemoteId = function() {\n\tvar checkIfTypeError = true,\n\t\tresult = null;\n\n\tif (typeof ZBWConnect === 'function') {\n\t\ttry {\n\t\t\tzbw = new ZBWConnect(); // find zbw by path or use (raspberry) location /etc/zbw as default\n\n\t\t\tif (!!zbw) {\n\t\t\t\tcheckIfTypeError = zbw.getUserId() instanceof TypeError ? true : false;\n\t\t\t}\n\t\t} catch (e) {\n\t\t\ttry {\n\t\t\t\tzbw = new ZBWConnect('./zbw');\n\t\t\t\tcheckIfTypeError = zbw.getUserId() instanceof TypeError ? true : false;\n\t\t\t} catch (er) {\n\t\t\t\tconsole.log('Something went wrong. Reading remote id has failed. Error:' + er.message);\n\t\t\t}\n\t\t}\n\t\tif (checkIfTypeError) {\n\t\t\tconsole.log('Something went wrong. Reading remote id has failed.');\n\t\t} else {\n\t\t\tresult = zbw.getUserId();\n\t\t}\n\t} else {\n\t\tconsole.log('Reading remote id has failed. Service is not available.');\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.getInstancesByModuleName = function(moduleName) {\n\treturn Object.keys(this.registerInstances).map(function(id) {\n\t\treturn controller.registerInstances[id];\n\t}).filter(function(i) {\n\t\treturn i.meta.id === moduleName;\n\t});\n};\n\nAutomationController.prototype.reoderDevices = function(list, action) {\n\tvar self = this,\n\t\tresult = false;\n\ttry {\n\t\t_.each(list, function(id) {\n\t\t\tvar vDev = self.devices.get(id),\n\t\t\t\torder = vDev.get('order');\n\n\t\t\torder[action] = list.indexOf(id);\n\n\t\t\tvDev.set('order', order);\n\t\t});\n\t\tresult = true;\n\t} catch (e) {\n\t\tconsole.log(e);\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.vDevFailedDetection = function(nodeId, isFailed, zwayName) {\n\tthis.devices.filterByNode(nodeId, zwayName).forEach(function(vDev) {\n\t\tif (vDev.get('metrics:isFailed') !== isFailed) { // don't trigger events if values is not changing to minimize the number of events\n\t\t\tvDev.set('metrics:isFailed', isFailed);\n\t\t}\n\t});\n};\n\nAutomationController.prototype.updateNotificationChannelNamespace = function() {\n\tvar self = this;\n\t\n\tthis.setNamespace(\"notificationChannels\", this.namespaces, Object.keys(this.notificationChannels).map(function(id) {\n\t\tvar profile = self.getProfile(self.notificationChannels[id].user);\n\t\treturn {channelId: id, userId: self.notificationChannels[id].user, channelName: self.notificationChannels[id].name, channelNameEx: self.notificationChannels[id].name + \" (\" + (profile ? profile.name : \"-\") + \")\"}; }));\n};\n\nAutomationController.prototype.registerNotificationChannel = function(id, user, name, handler) {\n\tconsole.log(\"Registering notification channel: \" + name + \", user: \" + (user ? user : '(not assigned to a user)'));\n\tthis.notificationChannels[id] = {user: parseInt(user), name: name, handler: handler};\n\tthis.updateNotificationChannelNamespace();\n};\n\nAutomationController.prototype.unregisterNotificationChannel = function(id) {\n\tconsole.log(\"Unregistering notification channel: \" + (this.notificationChannels[id] ? this.notificationChannels[id].name : \"(not found)\"));\n\tdelete this.notificationChannels[id];\n\tthis.updateNotificationChannelNamespace();\n};\n\nAutomationController.prototype.notificationChannelSend = function(id, message) {\n\tif (!this.notificationChannels[id]) {\n\t\tconsole.log(\"Error: Notification channel not found: \" + id + \" (message: \" + message + \")\");\n\t\treturn;\n\t}\n\tthis.notificationChannels[id].handler(message);\n};\n\nAutomationController.prototype.notificationUserChannelsSend = function(id, message) {\n\tvar self = this;\n\tObject.keys(this.notificationChannels).forEach(function(ncId) {\n\t\tif (self.notificationChannels[ncId].user === id) {\n\t\t\tself.notificationChannels[ncId].handler(message);\n\t\t}\n\t});\n};\n\nAutomationController.prototype.notificationAllChannelsSend = function(message) {\n\tvar self = this;\n\tObject.keys(this.notificationChannels).forEach(function(ncId) {\n\t\tself.notificationChannels[ncId].handler(message);\n\t});\n};\n\nAutomationController.prototype.getNotificationChannel = function(id) {\n\treturn this.notificationChannels[id];\n};\n\nAutomationController.prototype.transformIntoNewInstance = function(moduleName) {\n\n\tif (['IfThen', 'LogicalRules', 'ScheduledScene', 'LightScene'].indexOf(moduleName) < 0) {\n\t\treturn null;\n\t}\n\n\tvar self = this,\n\t\tinstances = [],\n\t\tnewInstances = [],\n\t\tresult = [];\n\n\tvar moduleMeta = this.modules[moduleName] && this.modules[moduleName].meta || null;\n\n\tinstances = _.filter(this.instances, function(i) {\n\t\treturn moduleName === i.moduleId && !i.params.transformed;\n\t});\n\n\tif (instances.length && moduleMeta) {\n\t\tinstances.forEach(function(instance) {\n\t\t\tvar newInstance = {};\n\n\t\t\tswitch (moduleName) {\n\t\t\t\tcase 'IfThen':\n\t\t\t\tcase 'LogicalRules':\n\t\t\t\t\tnewInstance = {\n\t\t\t\t\t\tmoduleId: 'Rules',\n\t\t\t\t\t\tactive: false,\n\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tsimple: {\n\t\t\t\t\t\t\t\ttriggerEvent: {},\n\t\t\t\t\t\t\t\ttriggerDelay: 0,\n\t\t\t\t\t\t\t\ttargetElements: [],\n\t\t\t\t\t\t\t\tsendNotifications: [],\n\t\t\t\t\t\t\t\treverseDelay: 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tadvanced: {\n\t\t\t\t\t\t\t\tactive: false,\n\t\t\t\t\t\t\t\ttriggerOnDevicesChange: false,\n\t\t\t\t\t\t\t\ttriggerScenes: [],\n\t\t\t\t\t\t\t\ttriggerDelay: 0,\n\t\t\t\t\t\t\t\tlogicalOperator: 'and',\n\t\t\t\t\t\t\t\ttests: [],\n\t\t\t\t\t\t\t\ttargetElements: [],\n\t\t\t\t\t\t\t\tsendNotifications: [],\n\t\t\t\t\t\t\t\treverseDelay: 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\treverse: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ScheduledScene':\n\n\t\t\t\t\tnewInstance = {\n\t\t\t\t\t\tmoduleId: 'Schedules',\n\t\t\t\t\t\tactive: false,\n\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tweekdays: [],\n\t\t\t\t\t\t\ttimes: [],\n\t\t\t\t\t\t\tdevices: []\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'LightScene':\n\n\t\t\t\t\tnewInstance = {\n\t\t\t\t\t\tmoduleId: 'Scenes',\n\t\t\t\t\t\tactive: false,\n\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\tparams: {\n\t\t\t\t\t\t\tdevices: [],\n\t\t\t\t\t\t\tcustomIcon: {\n\t\t\t\t\t\t\t\ttable: [{\n\t\t\t\t\t\t\t\t\ticon: ''\n\t\t\t\t\t\t\t\t}]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif ((moduleName === 'LogicalRules' && has_higher_version(moduleMeta.version, '1.4.0')) ||\n\t\t\t\t(moduleName === 'IfThen' && has_higher_version(moduleMeta.version, '2.5.0')) ||\n\t\t\t\t(moduleName === 'ScheduledScene' && has_higher_version(moduleMeta.version, '2.2.1')) ||\n\t\t\t\t(moduleName === 'LightScene' && has_higher_version(moduleMeta.version, '1.1.0'))) {\n\n\t\t\t\t// adjust title and instance state\n\t\t\t\tnewInstance.active = instance.active || false;\n\t\t\t\tnewInstance.title = moduleName + ' - ' + instance.title || 'Automatically transformed ' + newInstance.moduleId + ' instance from ' + moduleName + ' instance #' + instance.id;\n\n\t\t\t\tif (moduleName === 'LogicalRules') {\n\n\t\t\t\t\t// transform into advanced Rule\n\t\t\t\t\tnewInstance.params.advanced = self.transformIntoRule('advanced', instance, newInstance.params.advanced);\n\n\t\t\t\t} else if (moduleName === 'IfThen') {\n\n\t\t\t\t\t// transform into simple Rule\n\t\t\t\t\tnewInstance.params.simple = self.transformIntoRule('simple', instance, newInstance.params.simple);\n\n\t\t\t\t} else if (moduleName === 'ScheduledScene') {\n\n\t\t\t\t\t// update params and instance\n\t\t\t\t\tnewInstance.params.devices = self.concatDeviceListEntries(instance.params.devices);\n\t\t\t\t\tnewInstance.params.times = instance.params.times;\n\t\t\t\t\tnewInstance.params.weekdays = instance.params.weekdays;\n\n\t\t\t\t} else if (moduleName === 'LightScene') {\n\n\t\t\t\t\t// update params and instance\n\t\t\t\t\tnewInstance.params.devices = self.concatDeviceListEntries(instance.params);\n\t\t\t\t}\n\n\t\t\t\tnewInstances.push(newInstance);\n\n\t\t\t\t// stop old instance\n\t\t\t\tinstance.active = instance.active || instance.active === 'true' ? false : instance.active;\n\t\t\t\t// set transformed flag\n\t\t\t\tinstance.params.moduleAPITransformed = true;\n\t\t\t\tself.reconfigureInstance(instance.id, instance);\n\t\t\t}\n\t\t});\n\n\t\t// create new instances\n\t\tnewInstances.forEach(function(inst, index) {\n\n\t\t\tvar active = inst.active;\n\t\t\tif (!active) {\n\t\t\t\tinst.active = true;\n\t\t\t}\n\n\t\t\taddedInst = self.createInstance(inst);\n\n\t\t\tresult.push({\n\t\t\t\tid: addedInst.id,\n\t\t\t\ttitle: inst.title,\n\t\t\t\told_moduleId: moduleName\n\t\t\t});\n\n\t\t\t// stop old instance\n\t\t\tif (addedInst && (!active || active === 'false')) {\n\n\t\t\t\tinst.active = false;\n\t\t\t\tself.reconfigureInstance(addedInst.id, inst);\n\t\t\t}\n\t\t});\n\t}\n\n\treturn result;\n};\n\nAutomationController.prototype.transformIntoRule = function(type, instance, object) {\n\tvar self = this,\n\t\ttargetDevices = [],\n\t\ttests = [],\n\t\toldParams = instance.params ? instance.params : null,\n\t\tnewParams = object ? object : null;\n\n\t/*\n\tnewParams = {\n\t\tactive: true,\n\t\ttriggerOnDevicesChange: false,\n\t\ttriggerScenes: [],\n\t\ttriggerDelay: 0,\n\t\tlogicalOperator: 'and',\n\t\ttests: [],\n\t\ttargetElements: [],\n\t\tsendNotifications: [],\n\t\treverseDelay: 0\n\t}\n\t*/\n\n\t// transform old structure to new\n\tif (oldParams && type === 'advanced' && newParams) {\n\n\t\tobject.active = true;\n\t\tobject.triggerOnDevicesChange = oldParams.triggerOnDevicesChange || false;\n\t\tobject.logicalOperator = oldParams.logicalOperator || 'and';\n\t\tobject.tests = oldParams.test || [];\n\t\tobject.targetElements = oldParams.action || [];\n\n\t\t// concat all tests to one list\n\t\toldParams.tests.forEach(function(test) {\n\n\t\t\tif (Object.keys(test)[1]) {\n\t\t\t\tvar entry = test[Object.keys(test)[1]];\n\n\t\t\t\tif (test['testType'] === 'time') {\n\t\t\t\t\ttests.push({\n\t\t\t\t\t\ttype: \"time\",\n\t\t\t\t\t\toperator: entry.testOperator,\n\t\t\t\t\t\tlevel: entry.testValue\n\t\t\t\t\t});\n\t\t\t\t} else if (test['testType'] === 'nested') {\n\t\t\t\t\tvar nested = {\n\t\t\t\t\t\tlogicalOperator: test['testNested']['logicalOperator'],\n\t\t\t\t\t\ttests: []\n\t\t\t\t\t}\n\n\t\t\t\t\ttest['testNested']['tests'].forEach(function(nestedTest) {\n\t\t\t\t\t\tvar nestedTests = [];\n\n\t\t\t\t\t\tif (nestedTest['testType'] === 'time') {\n\t\t\t\t\t\t\tnested.tests.push({\n\t\t\t\t\t\t\t\ttype: \"time\",\n\t\t\t\t\t\t\t\toperator: nestedTest.testOperator,\n\t\t\t\t\t\t\t\tlevel: nestedTest.testValue\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnested.tests.push(self.transformAdvancedEntry('test', nestedTest));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\ttests.push(nested);\n\n\t\t\t\t\t//\n\t\t\t\t} else {\n\t\t\t\t\ttests.push(self.transformAdvancedEntry('test', entry));\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// concat actions to one list\n\t\tObject.keys(oldParams.action).forEach(function(key) {\n\n\t\t\toldParams.action[key].forEach(function(entry) {\n\t\t\t\tif (entry.device || (key === 'scenes' && entry)) {\n\t\t\t\t\tif (key === 'scenes') {\n\t\t\t\t\t\ttargetDevices.push({\n\t\t\t\t\t\t\tdeviceId: entry,\n\t\t\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\t\t\tlevel: 'on'\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (key === 'notification') {\n\t\t\t\t\t\tnewParams.sendNotifications.push(entry);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttargetDevices.push(self.transformAdvancedEntry('action', entry));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\t// set new params\n\t\tnewParams.tests = tests;\n\t\tnewParams.targetElements = targetDevices;\n\n\t} else if (oldParams && type === 'simple' && newParams) {\n\n\t\t/*\n\t\tnewParams = {\n\t\t\ttriggerEvent: {},\n\t\t\ttriggerDelay: 0,\n\t\t\ttargetElements: [],\n\t\t\tsendNotifications: [],\n\t\t\treverseDelay: 0\n\t\t}\n\t\t*/\n\n\t\t// transform trigger event\n\t\tif (Object.keys(oldParams.sourceDevice)[1]) {\n\t\t\tvar entry = oldParams.sourceDevice[Object.keys(oldParams.sourceDevice)[1]];\n\n\t\t\tnewParams.triggerEvent = self.transformSimpleEntry(entry);\n\t\t}\n\n\t\t// concat actions to one list\n\t\toldParams.targets.forEach(function(key) {\n\t\t\tvar targetEntry = key[Object.keys(key)[1]];\n\n\t\t\tif (key['notification']) {\n\t\t\t\tnewParams.sendNotifications.push(targetEntry);\n\t\t\t} else if (key['scene']) {\n\t\t\t\tnewParams.targetElements.push({\n\t\t\t\t\tdeviceId: targetEntry.target,\n\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\tlevel: 'on'\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tnewParams.targetElements.push(self.transformSimpleEntry(targetEntry));\n\t\t\t}\n\t\t});\n\t}\n\n\treturn newParams;\n}\n\nAutomationController.prototype.transformSimpleEntry = function(entry) {\n\t//console.log('simple entry:', JSON.stringify(entry));\n\tvar vdevId = entry && entry.device ? entry.device : entry.target,\n\t\tvDev = this.devices.get(vdevId),\n\t\tlvl = entry.status && ['color', 'level'].indexOf(entry.status) < 0 ? entry.status : (entry.level ? entry.level : (entry.color ? {\n\t\t\tr: entry.color.red,\n\t\t\tg: entry.color.green,\n\t\t\tb: entry.color.blue\n\t\t} : 0));\n\n\tif (vDev) {\n\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes\n\t\t\t{\n\t\t\t    deviceId: '',\n\t\t\t    deviceType: '',\n\t\t\t    level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t    sendAction: true, || false >> don't do this if level is already triggered\n\t\t\t    operator: '',\n\t\t\t    reverseLevel: \"off\"  // set reverse level on or off\n\t\t\t}\n\t\t*/\n\t\treturn {\n\t\t\tdeviceId: vdevId,\n\t\t\tdeviceType: vDev ? vDev.get('deviceType') : '',\n\t\t\tlevel: lvl,\n\t\t\tsendAction: entry.sendAction || false,\n\t\t\toperator: entry.operator,\n\t\t\treverseLevel: \"off\"\n\t\t};\n\t}\n};\n\nAutomationController.prototype.transformAdvancedEntry = function(transformation, entry) {\n\t//console.log('advanced entry:', JSON.stringify(entry));\n\tvar vDev = this.devices.get(entry.device);\n\n\tif (vDev) {\n\t\tif (transformation === 'test') {\n\t\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes\n\t\t\t\t{\n\t\t\t\t    deviceId: '',\n\t\t\t\t    type: '',\n\t\t\t\t    level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t\t    operator: ''\n\t\t\t\t}\n\t\t\t*/\n\t\t\treturn {\n\t\t\t\tdeviceId: vDev.id,\n\t\t\t\ttype: vDev ? vDev.get('deviceType') : '',\n\t\t\t\tlevel: entry['testValue'],\n\t\t\t\toperator: entry['testOperator'] ? entry['testOperator'] : undefined\n\t\t\t}\n\n\t\t} else if (transformation === 'action') {\n\t\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes\n\t\t\t\t{\n\t\t\t\t    deviceId: '',\n\t\t\t\t    deviceType: '',\n\t\t\t\t    level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t\t    sendAction: true || false >> don't do this if level is already triggered\n\t\t\t\t}\n\t\t\t*/\n\t\t\treturn {\n\t\t\t\tdeviceId: entry.device,\n\t\t\t\tdeviceType: vDev ? vDev.get('deviceType') : '',\n\t\t\t\tlevel: entry.status && ['color', 'level'].indexOf(entry.status) < 0 ? entry.status : (entry.level ? entry.level : (entry.color ? {\n\t\t\t\t\tr: entry.color.red,\n\t\t\t\t\tg: entry.color.green,\n\t\t\t\t\tb: entry.color.blue\n\t\t\t\t} : 0)),\n\t\t\t\tsendAction: entry.sendAction || false\n\t\t\t}\n\t\t}\n\t}\n};\n\nAutomationController.prototype.concatDeviceListEntries = function(devices) {\n\tvar self = this,\n\t\tnewDevArr = [],\n\t\tkeys = ['switches', 'dimmers', 'thermostats', 'locks', 'scenes'];\n\n\t// concat all lists to one\n\tObject.keys(devices).forEach(function(key) {\n\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes\n\t\t\t{\n\t\t\t    deviceId: '',\n\t\t\t    deviceType: '',\n\t\t\t    level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t    sendAction: true || false >> don't do this if level is already triggered\n\t\t\t}\n\t\t*/\n\t\tif (_.isArray(devices[key]) && keys.indexOf(key) >= 0) {\n\t\t\tdevices[key].forEach(function(entry) {\n\n\t\t\t\tvar vDev = null;\n\t\t\t\tif (entry.device || (key === 'scenes' && entry)) {\n\t\t\t\t\tif (key === 'scenes') {\n\t\t\t\t\t\tnewDevArr.push({\n\t\t\t\t\t\t\tdeviceId: entry,\n\t\t\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\t\t\tlevel: 'on'\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvDev = self.devices.get(entry.device);\n\n\t\t\t\t\t\tnewDevArr.push({\n\t\t\t\t\t\t\tdeviceId: entry.device,\n\t\t\t\t\t\t\tdeviceType: vDev ? vDev.get('deviceType') : '',\n\t\t\t\t\t\t\tlevel: entry.status && ['color', 'level'].indexOf(entry.status) < 0 ? entry.status : (entry.level ? entry.level : (entry.color ? {\n\t\t\t\t\t\t\t\tr: entry.color.red,\n\t\t\t\t\t\t\t\tg: entry.color.green,\n\t\t\t\t\t\t\t\tb: entry.color.blue\n\t\t\t\t\t\t\t} : 0)),\n\t\t\t\t\t\t\tsendAction: entry.sendAction\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\t// update params and instance\n\treturn newDevArr;\n};\n\nAutomationController.prototype.profileByUser = function(userId) {\n\treturn _.find(this.profiles, function(profile) {\n\t\treturn profile.id === userId\n\t});\n};\n\nAutomationController.prototype.profilesByRole = function(role) {\n\treturn this.profiles.filter(function(profile) {\n\t\treturn profile.role === role;\n\t}).map(function(profile) {\n\t\treturn profile.id;\n\t});\n};\n\nAutomationController.prototype.profilesByDevice = function(devId) {\n\tvar self = this;\n\tvar vDev = this.devices.get(devId);\n\tvar room = vDev ? vDev.get(\"location\") : null;\n\t\n\treturn this.profiles.filter(function(profile) {\n\t\treturn profile.role === self.auth.ROLE.ADMIN || (profile.devices && (profile.devices.indexOf(devId) !== -1)) || (room !== null && profile.rooms && (profile.rooms.indexOf(room) !== -1));\n\t}).map(function(profile) {\n\t\treturn profile.id;\n\t});\n};\n\nAutomationController.prototype.profilesByLocation = function(location) {\n\treturn this.profiles.filter(function(profile) {\n\t\treturn profile.rooms.indexOf(location) !== -1;\n\t}).map(function(profile) {\n\t\treturn profile.id;\n\t});\n};\n\nAutomationController.prototype.devicesByUser = function(userId, filter) {\n\tvar devices = this.devices.filter(filter),\n\t\tprofile = this.profileByUser(userId);\n\n\tif (!profile) {\n\t\treturn [];\n\t}\n\n\tif (profile.role === this.auth.ROLE.ADMIN) {\n\t\treturn devices;\n\t} else {\n\t\t// explicitelly allowed devices\n\t\tvar allowedDevices = [];\n\t\tif (!!profile.devices) {\n\t\t\tallowedDevices = devices.filter(function(dev) {\n\t\t\t\treturn profile.devices.indexOf(dev.id) !== -1;\n\t\t\t});\n\t\t}\n\t\t\n\t\t// devices from allowed rooms\n\t\tif (!!profile.rooms) {\n\t\t\tvar allowedDevicesFromRooms = devices.filter(function(dev) {\n\t\t\t\t// show only devices from allowed rooms (don't show unallocated devices)\n\t\t\t\treturn dev.get(\"location\") != 0 && profile.rooms.indexOf(dev.get(\"location\")) !== -1;\n\t\t\t});\n\t\t\t// append explicitedly allowed devices (unique concat)\n\t\t\tallowedDevices.forEach(function(dev) {\n\t\t\t\tif (allowedDevicesFromRooms.map(function(d) { return d.id; }).indexOf(dev.id) === -1) {\n\t\t\t\t\tallowedDevicesFromRooms.push(dev);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn allowedDevicesFromRooms;\n\t\t} else {\n\t\t\treturn allowedDevices;\n\t\t}\n\t}\n};\n\nAutomationController.prototype.deviceByUser = function(vDevId, userId) {\n\tif (this.devicesByUser(userId).filter(function(device) {\n\t\t\treturn device.id === vDevId\n\t\t}).length) {\n\t\treturn this.devices.get(vDevId);\n\t}\n\treturn null;\n};\n\nAutomationController.prototype.locationsByUser = function(userId) {\n\tvar profile = this.profileByUser(userId);\n\n\tif (!profile) {\n\t\treturn [];\n\t}\n\n\tif (profile.role === this.auth.ROLE.ADMIN) {\n\t\treturn this.locations;\n\t} else {\n\t\tif (!!profile.rooms) {\n\t\t\treturn this.locations.filter(function(location) {\n\t\t\t\treturn profile.rooms.indexOf(location.id) !== -1;\n\t\t\t});\n\t\t} else {\n\t\t\treturn [];\n\t\t}\n\t}\n};\n\nAutomationController.prototype.findModulesReferencingDeviceId = function(device) {\n\tfunction findAllUsages(device) {\n\t\tvar ret = [];\n\t\tfor (var indx in controller.instances) {\n\t\t\tvar instance = controller.instances[indx];\n\t\t\tvar moduleId = instance.moduleId;\n\t\t\tif (!controller.modules[moduleId]) {\n\t\t\t\tconsole.log(\"Module \" + moduleId + \" (\" + instance.id + \") is not installed\");\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tvar schema = controller.modules[moduleId].meta.schema;\n\t\t\tvar config = instance.params;\n\t\t\t\n\t\t\ttry {\n\t\t\t\tif (findUsage(schema, config, device)) {\n\t\t\t\t\tret.push({\n\t\t\t\t\t\tmoduleId: moduleId,\n\t\t\t\t\t\tinstanceId: instance.id,\n\t\t\t\t\t\tinstanceTitle: instance.title\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} catch(e) {\n\t\t\t\tconsole.log(\"Error in searching for references in \" + moduleId + \" instance \" + instance.id + \": \" + e);\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t}\n\n\tfunction findUsage(schema, config, device) {\n\t\tif (schema && config) {\n\t\t\t// module with a pretty config\n\t\t\tswitch(schema.type) {\n\t\t\t\tcase \"object\":\n\t\t\t\t\tfor (var prop in schema.properties) {\n\t\t\t\t\t\tif (findUsage(schema.properties[prop], config[prop], device)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"array\":\n\t\t\t\t\tfor (var index in config) {\n\t\t\t\t\t\tif (findUsage(schema.items, config[index], device)) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase undefined:\n\t\t\t\t\tif (schema.field === \"enum\" && schema.datasource === \"namespaces\" && schema.enum.split(\",\").filter(function(f){ return f.match(/namespaces:.*:deviceId/); }).length) {\n\t\t\t\t\t\tif (config === device) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\t/*\n\t\t\t\t\tif (config === device) {\n\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\t*/\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn false;\n\t\t} else {\n\t\t\t// all other modules\n\t\t\treturn config ? JSON.stringify(config).match(device) : false;\n\t\t}\n\t}\n\n\treturn findAllUsages(device);\n};\n"
  },
  {
    "path": "classes/AutomationModule.js",
    "content": "/*** Z-Way HA Automation module base class ************************************\n\nVersion: 1.0.0\n-------------------------------------------------------------------------------\nAuthor: Gregory Sitnin <sitnin@z-wave.me>\nCopyright: (c) ZWave.Me, 2013\n\n******************************************************************************/\n\nAutomationModule = function(id, controller) {\n\tvar self = this;\n\n\tthis.id = id;\n\tthis.controller = controller;\n\tthis.meta = this.getMeta();\n\n\tthis.actions = {};\n\tthis.actionFuncs = {};\n\tthis.metrics = {};\n\n\tthis.config = {};\n};\n\nAutomationModule.prototype.defaultConfig = function(config) {\n\tvar result = {},\n\t\tself = this;\n\n\tif (this.meta.hasOwnProperty(\"defaults\") && _.isObject(this.meta.defaults)) {\n\t\tObject.keys(_.omit(this.meta.defaults, 'title', 'description')).forEach(function(key) {\n\t\t\tresult[key] = self.meta.defaults[key];\n\t\t});\n\t}\n\n\tif (!!config) {\n\t\tObject.keys(config).forEach(function(key) {\n\t\t\tresult[key] = config[key];\n\t\t});\n\t}\n\n\treturn result;\n};\n\nAutomationModule.prototype.init = function(config) {\n\tconsole.log(\"--- Starting module \" + this.meta.defaults.title);\n\tif (!!config) {\n\t\tthis.saveNewConfig(config);\n\t} else {\n\t\tthis.loadConfig();\n\t}\n};\n\nAutomationModule.prototype.saveNewConfig = function(config) {\n\tif (!!config) {\n\t\tthis.config = this.defaultConfig(config);\n\t\tthis.saveConfig();\n\t}\n};\n\nAutomationModule.prototype.stop = function() {\n\tconsole.log(\"--- Stopping module \" + this.meta.defaults.title);\n};\n\nAutomationModule.prototype.loadConfig = function() {\n\tvar self = this;\n\tvar cfg = loadObject(\"cfg\" + this.id);\n\tif (\"object\" === typeof cfg) {\n\t\tObject.keys(cfg).forEach(function(key) {\n\t\t\tself.config[key] = cfg[key];\n\t\t});\n\t}\n};\n\nAutomationModule.prototype.saveConfig = function(config) {\n\tvar that = this,\n\t\tindex = this.controller.instances.indexOf(_.find(this.controller.instances, function(model) {\n\t\t\treturn model.id === that.id;\n\t\t}));\n\n\tthis.controller.instances[index].params = config || this.config;\n\tthis.controller.saveConfig(true);\n};\n\nAutomationModule.prototype.getName = function() {\n\treturn this.constructor.name;\n};\n\n// This method returns JSON representation\nAutomationModule.prototype.toJSON = function() {\n\treturn {\n\t\tmodule: this.getName(),\n\t\tid: this.id,\n\t\tconfig: this.config\n\t};\n};\n\nAutomationModule.prototype.runAction = function(actionId, args, callback) {\n\t// Run action function with actionId on instance if exists\n\tif (this.actionFuncs.hasOwnProperty(actionId)) {\n\t\tthis.actionFuncs[actionId].call(this, args, callback);\n\t}\n};\n\nAutomationModule.prototype.getMeta = function() {\n\tif (!this.meta) {\n\t\tthis.meta = this.controller.getModuleData(this.constructor.name);\n\t\tthis.meta.id = this.constructor.name;\n\t}\n\treturn this.meta;\n};\n\nAutomationModule.prototype.loadModuleJSON = function(filename) {\n\treturn fs.loadJSON(this.meta.location + \"/\" + filename);\n};\n\nAutomationModule.prototype.getInstanceTitle = function() {\n\tvar instanceId = this.id;\n\n\tvar instanceTitle = this.controller.instances.filter(function(instance) {\n\t\treturn instance.id === instanceId;\n\t});\n\n\treturn instanceTitle[0] && instanceTitle[0].title ? instanceTitle[0].title : this.constructor.name + ' ' + instanceId;\n};\n\nAutomationModule.prototype.loadModuleLang = function() {\n\treturn this.controller.loadModuleLang(this.getName());\n};\n\nAutomationModule.prototype.addNotification = function(severity, message, type) {\n\tthis.controller.addNotification(severity, message, type, this.getName());\n};\n\n// TODO: delete it, should not be here\nAutomationModule.prototype.prepareHTTPResponse = function(body) {\n\tvar result = {},\n\t\tret = {\n\t\t\tstatus: 500,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: {\n\t\t\t\tcode: 500,\n\t\t\t\tmessage: \"500 Something went wrong.\",\n\t\t\t\terror: null,\n\t\t\t\tdata: null\n\t\t\t}\n\t\t};\n\n\treturn body ? _.extend(ret, {\n\t\tstatus: body.code ? body.code : ret.status,\n\t\tbody: body\n\t}) : ret;\n}\n\n// ----------------------------------------------------------------------------\n// --- Logical methods (Rules, Scenes, Schedules, HazardNotification)\n// ----------------------------------------------------------------------------\n\n/*\tcompare old and new level to avoid unnecessary updates\n\n\tvDev\t[string]\t\t\t// device object\n\tvalNew\t[string/number]\t\t// device level like: {color: { r: 0, g: 0, b: 0}}, 'on', 'off', 'open', 'close', [level]\n*/\nAutomationModule.prototype.newValueNotEqualsOldValue = function(vDev, valNew) {\n\tif (vDev) {\n\t\tvar vO = '';\n\n\t\tvN = _.isNaN(parseFloat(valNew)) ? valNew : parseFloat(valNew);\n\n\t\tswitch (vDev.get('deviceType')) {\n\t\t\tcase 'switchRGBW':\n\n\t\t\t\tvO = typeof vN !== 'string' ? vDev.get('metrics:color') : vDev.get('metrics:level');\n\n\t\t\t\tif (valNew !== 'string') {\n\t\t\t\t\treturn !_.isEqual(vO, vN);\n\t\t\t\t}\n\t\t\tcase 'switchControl':\n\t\t\t\tif (_.contains(['on', 'off'], vN) || _.isNumber(vN)) {\n\t\t\t\t\tvO = vDev.get('metrics:level');\n\t\t\t\t} else {\n\t\t\t\t\tvO = vDev.get('metrics:change');\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tvO = vDev.get('metrics:level');\n\t\t}\n\t\treturn vO !== vN;\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\n\tset a new device state\n\n\tvDev\t\t[string]\t\t\t// device object\n\tnew_level\t[string/number]\t\t// device level like: {color: { r: 0, g: 0, b: 0}}, 'on', 'off', 'open', 'close', [level]\n*/\nAutomationModule.prototype.setNewDeviceState = function(vDev, new_level) {\n\tif (vDev) {\n\t\tswitch (vDev.get('deviceType')) {\n\t\t\tcase 'doorlock':\n\t\t\tcase 'switchBinary':\n\t\t\t\tvDev.performCommand(new_level);\n\t\t\t\tbreak;\n\t\t\tcase 'switchMultilevel':\n\t\t\tcase 'thermostat':\n\t\t\t\t_.contains(['on', 'off'], new_level) ? vDev.performCommand(new_level) : vDev.performCommand(\"exact\", {\n\t\t\t\t\tlevel: new_level\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase 'switchRGBW':\n\t\t\t\tif (_.contains([\"on\", \"off\"], new_level)) {\n\t\t\t\t\tvDev.performCommand(new_level);\n\t\t\t\t} else {\n\t\t\t\t\tvDev.performCommand(\"exact\", {\n\t\t\t\t\t\tred: new_level.r,\n\t\t\t\t\t\tgreen: new_level.g,\n\t\t\t\t\t\tblue: new_level.b\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'switchControl':\n\t\t\t\tif (_.contains([\"on\", \"off\"], new_level)) {\n\t\t\t\t\tvDev.performCommand(new_level);\n\t\t\t\t} else if (_.contains([\"upstart\", \"upstop\", \"downstart\", \"downstop\"], new_level)) {\n\t\t\t\t\tvDev.performCommand(\"exact\", {\n\t\t\t\t\t\tchange: new_level\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvDev.performCommand(\"exact\", {\n\t\t\t\t\t\tlevel: new_level\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'toggleButton':\n\t\t\t\tvDev.performCommand('on');\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tvDev.performCommand(new_level);\n\t\t}\n\t}\n};\n\n/*\n\texecute a device action based on compareLevels flag\n\n\tcompareLevels \t[boolean]\t// flag if device level should be checked first before triggering the command\n\tvDev\t\t\t[string]\t// device object\n\ttargetValue\t\t[string]\t// target value\n*/\nAutomationModule.prototype.executeActions = function(compareLevels, vDev, targetValue) {\n\treturn (!compareLevels || (compareLevels && this.newValueNotEqualsOldValue(vDev, targetValue)));\n};\n\n/*\n\tsimply compare two values with help of logical operators\n\n\tdval \t[string]\t// device value that should be check against condition\n\top\t\t[string]\t// operator for comparisation: '=', '<', '>', '<=', '>=', '!='\n\tval\t\t[string]\t// condition value\n*/\nAutomationModule.prototype.op = function(dval, op, val) {\n\tif (op === \"=\") {\n\t\treturn dval === val;\n\t} else if (op === \"!=\") {\n\t\treturn dval !== val;\n\t} else if (op === \">\") {\n\t\treturn dval > val;\n\t} else if (op === \"<\") {\n\t\treturn dval < val;\n\t} else if (op === \">=\") {\n\t\treturn dval >= val;\n\t} else if (op === \"<=\") {\n\t\treturn dval <= val;\n\t}\n\n\treturn null; // error!!\n};\n\n/*\n\tsimply compare switchControl level or changes\n\n\tvDev \t\t[object]\t// device object\n\ttargetValue\t[string]\t// target value that should be switched\n*/\nAutomationModule.prototype.compareSwitchControl = function(vDev, targetValue) {\n\tif (vDev) {\n\t\treturn (_.contains([\"on\", \"off\"], targetValue) && vDev.get('metrics:level') === targetValue) || (_.contains([\"upstart\", \"upstop\", \"downstart\", \"downstop\"], targetValue) && vDev.get(\"metrics:change\") === targetValue)\n\t} else {\n\t\treturn false;\n\t}\n};\n\n/*\n\tsimply compare times in format HH:mm with current time\n\n\ttime \t\t[string]\t// format HH:mm\n\toperator\t[string]\t// operators for comparisation: '<=', '>=' (others doesn't make sence)\n*/\nAutomationModule.prototype.compareTime = function(time, operator) {\n\tvar curTime = new Date(),\n\t\ttime_arr = time.split(\":\").map(function(x) {\n\t\t\treturn parseInt(x, 10);\n\t\t});\n\n\treturn this.op(curTime.getHours() * 60 + curTime.getMinutes(), operator, time_arr[0] * 60 + time_arr[1]);\n};\n\n/*\tswitches a vDev based on it's known object stored in modules config\n\n\treverseLevel\t\t\t[boolean]\t\t\t\t// don't do this if level is already triggered\n\tel = {\n\t    deviceId: '',\t\t\t[string], MUST\t\t\t\t// device ID\n\t    deviceType: '',\t\t\t[string], MUST\t\t\t\t// device type\n\t    level: '', \t\t\t\t[string/number], MUST\t\t// device level like: {color: { r: 0, g: 0, b: 0}}, 'on', 'off', 'open', 'close', [level]\n\t    sendAction: false, \t\t[boolean], MUST\t\t\t\t// don't do this if level is already triggered\n\t    reverseLevel: '',   \t[string/number], OPTIONAL\t// device reverse level like: {color: { r: 0, g: 0, b: 0}}, 'on', 'off', 'open', 'close', [level]\n\t    operator: ''\t\t\t[string], OPTIONAL\t\t\t// operator for comparisation: '=', '<', '>', '<=', '>=', '!='\n\t}\n*/\nAutomationModule.prototype.shiftDevice = function(el, reverse) {\n\tvar vDev = this.controller.devices.get(el.deviceId),\n\t\tlvl = reverse && el.reverseLevel !== undefined && !!el.reverseLevel? el.reverseLevel : el.level,\n\t\tset = this.executeActions(el.sendAction, vDev, lvl);\n\n\t// check if levels are equal and if active don't trigger new state\n\tif (vDev && set) {\n\t\tthis.setNewDeviceState(vDev, lvl);\n\t}\n};"
  },
  {
    "path": "classes/DevicesCollection.js",
    "content": "/*** Z-Way DevicesCollection class ************************************\n\n Version: 1.0.0\n -------------------------------------------------------------------------------\n Author: Stanislav Morozov <morozov@z-wave.me>\n Copyright: (c) ZWave.Me, 2014\n\n ******************************************************************************/\n\nDevicesCollection = function (controller) {\n\tvar that = this;\n\tthat.controller = controller;\n\tthat.config = {};\n\tthat.models = [];\n\tthat.db = {\n\t\tcid: {},\n\t\tid: {},\n\t\tindexes: {},\n\t\thardwareId: {}\n\t};\n\tthat.changed = {\n\t\tremove: [],\n\t\tadd: [],\n\t\tupdate: []\n\t};\n\tthat.length = 0;\n\tthat.initialize.apply(this, arguments);\n};\n\ninherits(DevicesCollection, EventEmitter2);\n\n_.extend(DevicesCollection.prototype, {\n\tinitialize: function () {\n\t\t'use strict';\n\t\t_.bindAll(this, 'updateLength', 'create');\n\t},\n\tupdateLength: function () {\n\t\tthis.length = _.size(this.models);\n\t},\n\tcreate: function (options) {\n\t\tvar that = this,\n\t\t\tvDev = null;\n\n\t\tconsole.log(\"Creating device \" + (options.overlay.deviceType || options.defaults.deviceType) + \" \" + options.deviceId);\n\t\tvDev = new VirtualDevice(_.extend(options, {controller: that.controller}));\n\n\t\tif (vDev !== null) {\n\t\t\tvDev.init();\n\t\t\tthat.add(vDev);\n\t\t\tthat.updateLength();\n\t\t\tthat.emit('created', vDev);\n\t\t\tthat.controller.lastStructureChangeTime = Math.floor(Date.now() / 1000);\n\t\t} else {\n\t\t\tconsole.log(\"Error creating device\");\n\t\t}\n\n\t\tvDev.save();\n\t\t\n\t\treturn vDev;\n\t},\n\tadd: function (model) {\n\t\tif (model.hasOwnProperty('cid')) {\n\t\t\tif (this.db.cid[model.cid] === model) {\n\t\t\t\tdelete this.db.cid[model.cid];\n\t\t\t}\n\t\t\tdelete model.cid;\n\t\t}\n\n\t\tmodel.cid = _.uniqueId('c');\n\t\tthis.db.cid[model.cid] = model;\n\t\tthis.db.id[model.get('id')] = model;\n\t\t// add to collection\n\t\tthis.models.push(model);\n\t\tmodel.index = this.models.indexOf(model);\n\t\tthis.db.indexes[model.index] = model;\n\t\treturn model;\n\t},\n\thas: function (identificator) {\n\t\tvar result = false;\n\t\tif (this.db.id.hasOwnProperty(identificator) || this.db.cid.hasOwnProperty(identificator)) {\n\t\t\tresult = true;\n\t\t}\n\t\treturn result;\n\t},\n\tget: function (identificator) {\n\t\tvar result;\n\t\tif (this.db.id.hasOwnProperty(identificator)) {\n\t\t\tresult = this.db.id[identificator];\n\t\t} else if (this.db.cid.hasOwnProperty(identificator)) {\n\t\t\tresult = this.db.cid[identificator];\n\t\t}\n\t\treturn result || null;\n\t},\n\tfirst: function () {\n\t\treturn _.first(this.models);\n\t},\n\tlast: function () {\n\t\treturn _.last(this.models);\n\t},\n\tsize: function () {\n\t\treturn _.size(this.models);\n\t},\n\ttoJSON: function (options) {\n\t\tvar models, result;\n\t\toptions = options || {};\n\n\t\tmodels = this.models.filter(function (device) {\n\t\t\treturn !!options.since ? !!device.ready && device.toJSON().updateTime >= options.since : !!device.ready;\n\t\t});\n\n\t\tmodels = models.map(function (model) {\n\t\t\treturn model.toJSON();\n\t\t});\n\n\t\treturn models;\n\t},\n\tremove: function (identificator) {\n\t\tvar that = this,\n\t\t\tmodel = that.get(identificator);\n\n\t\tif (!model) {\n\t\t\treturn;\n\t\t}\n\n\t\tthat.models = that.models.filter(function (object) {\n\t\t\treturn object.cid !== model.cid;\n\t\t});\n\n\t\tconsole.log(\"Deleting device \" + model.get(\"deviceType\") + \" \" + identificator);\n\t\tif (that.db.id.hasOwnProperty(identificator)) {\n\t\t\tdelete that.db.id[identificator];\n\t\t} else if (that.db.cid.hasOwnProperty(identificator)) {\n\t\t\tdelete that.db.cid[identificator];\n\t\t} else if (that.db.indexes.hasOwnProperty(model.index)) {\n\t\t\tdelete that.db.indexes[model.index];\n\t\t}\n\n\t\tdelete model.cid;\n\n\t\t// events\n\t\tthat.emit('removed', model);\n\t\tthat.controller.lastStructureChangeTime = Math.floor(Date.now() / 1000);\n\t\treturn model;\n\t},\n\tcleanup: function (identificator) {\n\t\tvar that = this,\n\t\t\tmodel = that.get(identificator);\n\n\t\tif (model) {\n\t\t\tconsole.log(\"Can not cleanup device info: device \" + identificator + \" exists\");\n\t\t}\n\t\t\n\t\tthat.emit('wipedOut', identificator);\n\t\tthat.controller.clearVdevInfo(identificator);\n\t},\n\twhere: function (obj) {\n\t\tvar that = this,\n\t\t\tcheck,\n\t\t\tdevices = _.filter(that.models, function (model) {\n\t\t\tcheck = true;\n\n\t\t\tObject.keys(obj).forEach(function (key) {\n\t\t\t\tif (model.get(key) !== obj[key] && check) {\n\t\t\t\t\tcheck = false;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\treturn check;\n\t\t});\n\n\t\treturn devices.length && Boolean(devices) ? devices : [];\n\t},\n\tfindWhere: function (obj) {\n\t\treturn _.first(this.where(obj));\n\t},\n\tfilter: function (callback) {\n\t\treturn _.filter(this.models, callback);\n\t},\n\tmap: function (callback) {\n\t\treturn _.map(this.models, callback);\n\t},\n\teach: function (callback) {\n\t\treturn _.each(this.models, callback);\n\t},\n\tforEach: function (callback) {\n\t\treturn this.each(callback);\n\t},\n\ton: function () {\n\t\tvar vDevId = \"\",\n\t\t\targs = [];\n\t\t\n\t\tArray.prototype.push.apply(args, arguments);\n\t\t\n\t\tif (args.length < 2 || args.length > 3) {\n\t\t\tthrow \"Invalid number of arguments to on()\";\n\t\t}\n\t\t\n\t\tif (args.length > 2) {\n\t\t\tvDevId = args.shift() + \":\";\n\t\t}\n\t\t\n\t\treturn EventEmitter2.prototype.on.call(this, vDevId + args[0], args[1]);\n\t},\n\toff: function () {\n\t\tvar vDevId = \"\",\n\t\t\targs = [];\n\t\t\n\t\tArray.prototype.push.apply(args, arguments);\n\t\t\n\t\tif (args.length < 2 || args.length > 3) {\n\t\t\tthrow \"Invalid number of arguments to off()\";\n\t\t}\n\t\t\n\t\tif (args.length > 2) {\n\t\t\tvDevId = args.shift() + \":\";\n\t\t}\n\t\t\n\t\treturn EventEmitter2.prototype.off.call(this, vDevId + args[0], args[1]);\n\t},\n\t// filter vDevs by nodeId and zway name\n\tfilterByNode: function (nodeId, zwayName) {\n\t\tvar self = this,\n\t\t\tgetNodeVDevs = [],\n\t\t\tnodeId = nodeId,\n\t\t\tzwayName = zwayName,\n\t\t\tlistZwayNames = ZWave.list().map(function(name) { return name });\n\n\t\t// filter all nodes\n\t\tif (!zwayName) {\n\t\t\tmatches = [];\n\n\t\t\t// prepare vDev id prefixes\n\t\t\tlistZwayNames.forEach(function (name) {\n\t\t\t   matches.push(\"ZWayVDev_\" + name + \"_\" + nodeId);\n\t\t\t});\n\n\t\t\t// get all vDev's by node\n\t\t\tmatches.forEach(function (vDevIdPrefix) {\n\t\t\t\tgetNodeVDevs = getNodeVDevs.concat(_.filter(self.models, function(vDev){\n\t\t\t\t\treturn vDev.id.indexOf(vDevIdPrefix) > -1;\n\t\t\t\t}));\n\t\t\t});\n\t\t// filter all nodes by zway name\n\t\t} else if (zwayName && listZwayNames.indexOf(zwayName) > -1){\n\t\t\tvDevIdPrefix = \"ZWayVDev_\" + zwayName + \"_\" + nodeId;\n\t\t\t\n\t\t\tgetNodeVDevs = _.filter(this.models, function(vDev) {\n\t\t\t\treturn vDev.id.indexOf(vDevIdPrefix) > -1;\n\t\t\t});\n\t\t}\n\n\t\treturn getNodeVDevs;\n\t},\n\t// filter vDevs by creator id\n\tfilterByCreatorId: function (instanceId) {\n\t\tvar instanceVDevs = [];\n\n\t\tinstanceVDevs = _.filter(this.models,function (dev) {\n\t\t\treturn dev.get('creatorId') === instanceId;\n\t\t});\n\n\t\treturn instanceVDevs;\n\t}\n});\n"
  },
  {
    "path": "classes/VirtualDevice.js",
    "content": "/*** Z-Way HA Virtual Device base class ***************************************\n\nVersion: 2.0.0\n-------------------------------------------------------------------------------\nAuthor: Gregory Sitnin <sitnin@z-wave.me> and Stanislav Morozov <morozov@z-wave.me>\nCopyright: (c) ZWave.Me, 2013-2014\n\n******************************************************************************/\n\nVirtualDevice = function (options) {\n\n\tvar probeType = options.defaults.probeType? options.defaults.probeType : (options.overlay.probeType? options.overlay.probeType : ''),\n\t\tpermHidden = options.defaults.hasOwnProperty('permanently_hidden')? options.defaults.permanently_hidden : false,\n\t\tvisibility = options.defaults.hasOwnProperty('visibility')? options.defaults.visibility : true,\n\t\tcustomicons = options.defaults.hasOwnProperty('customIcons') ? options.defaults.customIcons : {},\n\t\tisFailed = this.metrics && this.metrics.hasOwnProperty('isFailed')? this.metrics.isFailed : false,\n\t\ttags = options.defaults.hasOwnProperty('tags')? options.defaults.tags : [],\n\t\torder = options.defaults.hasOwnProperty('order') ? options.defaults.order : { rooms: 0, elements: 0, dashboard: 0 },\n\t\tlocation = options.defaults.hasOwnProperty('location')? options.defaults.location : 0,\n\t\tcreationTime = options.defaults.hasOwnProperty('creationTime')? options.defaults.creationTime : 0;\n\n\t_.defaults(options.defaults, {\n                technology: \"Virtual\",\n                manufacturer: \"Z-Wave.Me\",\n                product: \"Virtual device\",\n                firmware: zwayVersion.release\n\t});\n\t\n\t_.extend(this, options, {\n\t\tid: options.deviceId,\n\t\taccessAttrs: [\n\t\t\t'id',\n\t\t\t'deviceType',\n\t\t\t'metrics',\n\t\t\t'location',\n\t\t\t'locationName',\n\t\t\t'tags',\n\t\t\t'updateTime',\n\t\t\t'permanently_hidden',\n\t\t\t'creatorId',\n\t\t\t'h',\n\t\t\t'hasHistory',\n\t\t\t'visibility',\n\t\t\t'creationTime',\n\t\t\t'probeType',\n\t\t\t'customIcons',\n\t\t\t'manufacturer',\n\t\t\t'product',\n\t\t\t'firmware',\n\t\t\t'order',\n\t\t\t'technology',\n\t\t\t'bindingName',\n\t\t\t'nodeId'\n\t\t],\n\t\tcollection: options.controller.devices,\n\t\tmetrics: {},\n\t\tready: false,\n\t\tlocation: 0,\n\t\tlocationName: \"\",\n\t\ttags: [],\n\t\tupdateTime: 0,\n\t\tattributes: {\n\t\t\tid: options.deviceId,\n\t\t\tmetrics: _.extend(this.metrics, {\n\t\t\t\tisFailed: isFailed\n\t\t\t}),\n\t\t\ttags: tags,\n\t\t\tpermanently_hidden: permHidden,\n\t\t\tlocation: location,\n\t\t\tlocationName: \"\",\n\t\t\th: options.controller.hashCode(options.deviceId),\n\t\t\thasHistory: false,\n\t\t\tvisibility: visibility,\n\t\t\tcreationTime: creationTime,\n\t\t\tprobeType: probeType,\n\t\t\tcustomIcons: customicons,\n\t\t\torder: order\n\t\t},\n\t\toverlay: options.overlay || {},\n\t\tdefaults: options.defaults || {},\n\t\toverlay_metrics: options.hasOwnProperty('overlay') ? options.overlay.metrics : {},\n\t\t_previousAttributes: {}\n\t});\n\n\tif (options.hasOwnProperty('overlay')) {\n\t\tdelete options.overlay.metrics;\n\t}\n\n\n\tif (!!this.collection) {\n\t\tthis.cid = _.uniqueId('c');\n\t}\n\n\tif (!!options.moduleId) {\n\t\tthis.attributes.creatorId = options.moduleId;\n\t}\n\n\n\tthis.initialize.apply(this, arguments);\n\treturn this;\n};\n\nfunction inObj(obj, arr) {\n\tvar result, findObj;\n\n\twhile (arr.length > 0) {\n\t\tfindObj = result === undefined ? obj : result;\n\t\tif (findObj.hasOwnProperty(arr[0])) {\n\t\t\tresult = findObj[arr[0]];\n\t\t} else {\n\t\t\tbreak;\n\t\t}\n\n\t\tarr.shift();\n\t}\n\n\treturn arr.length > 0 ? undefined : result;\n}\n\nfunction setObj(obj, arr, param) {\n\tvar key;\n\n\tif (obj) {\n\t\tkey = arr[0];\n\t\tarr.shift();\n\t\tif (arr.length === 0) {\n\t\t\tobj[key] = param;\n\t\t} else if (obj.hasOwnProperty(key) && arr.length > 0) {\n\t\t\tsetObj(obj[key], arr, param);\n\t\t} else if (!obj.hasOwnProperty(key) && arr.length > 0) {\n\t\t\tobj[key] = {};\n\t\t\tsetObj(obj[key], arr, param);\n\t\t}\n\t}\n\treturn obj;\n}\n\n_.extend(VirtualDevice.prototype, {\n\tinitialize: function () {\n\t\t'use strict';\n\t\t_.bindAll(this, 'get', 'set');\n\t\t_.extend(this.attributes, this.collection.controller.getVdevInfo(this.id));\n\t\t_.extend(this.attributes, this.overlay);\n\t\t_.defaults(this.attributes, { \"metrics\" : {} });\n\t\t_.extend(this.attributes.metrics, this.overlay_metrics);\n\t\t_.defaults(this.attributes, this.defaults); // set default params\n\t\t_.defaults(this.attributes.metrics, this.defaults.metrics); // set default metrics\n\n\t\t// check that location exists\n\t\tvar self = this;\n\t\tvar l = _.find(this.collection.controller.locations, function(loc) { return loc.id === self.attributes.location; });\n\t\tif (!l) {\n\t\t\tthis.attributes.location = 0; // reset to globalRoom if location is not found\n\t\t}\n\t\t_.extend(this.attributes, { locationName: this.collection.controller.locationName(this.attributes.location) });\n\n\t\t// set device creation time\n\t\tthis.setCreationTime();\n\n\t\tthis.attributes = this._sortObjectByKey(this.attributes);\n\t\t\n\t\t// cleanup\n\t\tdelete this.overlay;\n\t\tdelete this.overlay_metrics;\n\t\tdelete this.defaults;\n\t},\n\tsetReady: function () {\n\t\tthis.ready = true;\n\t\tthis.attributes.updateTime = Math.floor(Date.now() / 1000);\n\t},\n\tsetCreationTime: function() {\n\t\tvar vDevInfo = this.collection.controller.vdevInfo[this.id];\n\t\t\n\t\tif (vDevInfo) {\n\t\t\t// check vdevInfo for creation time\n\t\t\tif (vDevInfo.creationTime) {\n\t\t\t\tthis.attributes.creationTime = vDevInfo.creationTime > 0? vDevInfo.creationTime : Math.floor(Date.now() / 1000);\n\t\t\t// add new if it doesn't exist\n\t\t\t} else {\n\t\t\t\tthis.attributes.creationTime = Math.floor(Date.now() / 1000);\n\t\t\t}\n\t\t// add new if it doesn't exist\n\t\t} else {\n\t\t\tthis.attributes.creationTime = Math.floor(Date.now() / 1000);\n\t\t}\n\t},\n\tget: function (param) {\n\t\t'use strict';\n\t\tvar result;\n\n\t\tif (param.split(':').length === 1) {\n\t\t\tif (this.attributes.hasOwnProperty(param)) {\n\t\t\t\tresult = this.attributes[param];\n\t\t\t}\n\t\t} else if (param.split(':').length > 1) {\n\t\t\tresult = inObj(this.toJSON(), param.split(':'));\n\t\t}\n\n\t\treturn result;\n\t},\n\tset: function (keyName, val, options) {\n\t\tvar that = this,\n\t\t\tchanges = [],\n\t\t\tcurrent = _.clone(this.attributes),\n\t\t\tprev = this._previousAttributes,\n\t\t\taccessAttrs,\n\t\t\tattrs,\n\t\t\tfindObj;\n\n\t\tfunction findX(obj, key) {\n\t\t\tvar val = obj[key];\n\t\t\tif (val !== undefined) {\n\t\t\t\treturn obj;\n\t\t\t}\n\t\t\tfor (var name in obj) {\n\t\t\t\tvar result = findX(obj[name]);\n\t\t\t\tif (result !== undefined) {\n\t\t\t\t\treturn obj;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\toptions = options || {};\n\t\taccessAttrs = options.accessAttrs || that.accessAttrs;\n\n\t\tif (_.isString(keyName) && typeof(val) != \"undefined\" && keyName.split(':').length === 1) {\n\t\t\t// to track location change\n\t\t\tvar profilesDevicesBefore;\n\t\t\tif (\"location\" === keyName) {\n\t\t\t\tprofilesDevicesBefore = this.collection.controller.profiles.map(function(p) { return { id: p.id, devices: that.collection.controller.devicesByUser(p.id) }; });\n\t\t\t}\n\n\t\t\tfindObj = findX(this.attributes, keyName);\n\t\t\tif (findObj[keyName] !== val) {\n\t\t\t\tthat.attributes[keyName] = val;\n\t\t\t\tchanges.push(keyName);\n\t\t\t}\n\t\t\t\n\t\t\tif (\"location\" === keyName) {\n\t\t\t\tthis.collection.controller.profiles.forEach(function(p) {\n\t\t\t\t\tvar isPresent = that.collection.controller.devicesByUser(p.id).filter(function(d) { return d.id === that.id; }).length,\n\t\t\t\t\t    wasPresent = profilesDevicesBefore.filter(function(pp) { return pp.id === p.id && pp.devices.filter(function(d) { return d.id === that.id; }).length; }).length;\n\t\t\t\t\t\n\t\t\t\t\tif (isPresent != wasPresent) {\n\t\t\t\t\t\tthat.collection.controller.emit('profile.deviceListUpdated', {\n\t\t\t\t\t\t\tprofile: p,\n\t\t\t\t\t\t\tadded: isPresent ? [that.id] : [],\n\t\t\t\t\t\t\tdeleted: wasPresent ? [that.id] : []\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t} else {\n\t\t\tif (_.isString(keyName) && val !== undefined && keyName.split(':').length > 1) {\n\t\t\t\tsetObj(current, keyName.split(':'), val);\n\t\t\t\t_.extend(that.attributes, current);\n\t\t\t\tchanges.push(keyName);\n\t\t\t} else {\n\t\t\t\t// to track location change\n\t\t\t\tvar profilesDevicesBefore;\n\t\t\t\tif (\"location\" in keyName) {\n\t\t\t\t\tdelete keyName[\"locationName\"]; // remove locationName if present - it will be recalculated\n\t\t\t\t\tprofilesDevicesBefore = this.collection.controller.profiles.map(function(p) { return { id: p.id, devices: that.collection.controller.devicesByUser(p.id) }; });\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tattrs = _.extend(that.attributes, _.pick(keyName, accessAttrs));\n\t\t\t\tObject.keys(attrs).forEach(function (key) {\n\t\t\t\t\tif (!_.isEqual(current[key], attrs[key])) {\n\t\t\t\t\t\t// if metrics has changed go deeper and add change identifier of changed metrics entry\n\t\t\t\t\t\tif (key === 'metrics') {\n\t\t\t\t\t\t\tObject.keys(current[key]).forEach(function (metricsKey) {\n\t\t\t\t\t\t\t\tif (!_.isEqual(current[key][metricsKey], attrs[key][metricsKey])) {\n\t\t\t\t\t\t\t\t\tchanges.push('metrics:' + metricsKey);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t// push also 'metrics' identifier\n\t\t\t\t\t\t\tchanges.push(key);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tchanges.push(key);\n\t\t\t\t\t\t\tconsole.logJS(3, changes)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (\"location\" in keyName) {\n\t\t\t\t\tthis.collection.controller.profiles.forEach(function(p) {\n\t\t\t\t\t\tvar isPresent = that.collection.controller.devicesByUser(p.id).filter(function(d) { return d.id === that.id; }).length,\n\t\t\t\t\t\t    wasPresent = profilesDevicesBefore.filter(function(pp) { return pp.id === p.id && pp.devices.filter(function(d) { return d.id === that.id; }).length; }).length;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (isPresent != wasPresent) {\n\t\t\t\t\t\t\tthat.collection.controller.emit('profile.deviceListUpdated', {\n\t\t\t\t\t\t\t\tprofile: p,\n\t\t\t\t\t\t\t\tadded: isPresent ? [that.id] : [],\n\t\t\t\t\t\t\t\tdeleted: wasPresent ? [that.id] : []\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t\n\t\t\t}\n\t\t}\n\n\n\t\tif (!options.silent) {\n\t\t\tif (changes.length) {\n\t\t\t\tthat.attributes.updateTime = Math.floor(Date.now() / 1000);\n\t\t\t}\n\n\t\t\tchanges.forEach(function (key) {\n\t\t\t\tif (!!that.collection) {\n\t\t\t\t\tthat.collection.emit('change:' + key, that, key);\n\t\t\t\t}\n\t\t\t\tthat.emit('change:' + key, that, key);\n\t\t\t});\n\t\t}\n\n\t\tif (!options.setOnly) {\n\t\t\tthat.save();\n\t\t}\n\t\treturn this;\n\t},\n\tsave: function (attrs, options) {\n\t\tif (!!attrs) {\n\t\t\tthis.set(attrs, options);\n\t\t}\n\t\tthis.collection.controller.setVdevInfo(this.id, this.attributes);\n\t\treturn this;\n\t},\n\ttoJSON: function () {\n\t\treturn _.clone(this.attributes);\n\t},\n\tdestroy: function () {\n\t\tthis.unlink();\n\t\tthis.collection.emit('destroy', this);\n\t\tthis.remove();\n\t},\n\tunlink: function () {\n\t\tthis.collection.remove(this.cid);\n\t},\n\tremove: function () {\n\t\tthis.stopListening();\n\t\treturn this;\n\t},\n\tstopListening: function () {\n\t\tthis.removeAllListeners();\n\t},\n\tinit: function () {\n\t\tthis.setReady();\n\t},\n\tdeviceTitle: function () {\n\t\treturn this.attributes.metrics.hasOwnProperty('title') ? this.attributes.metrics.title : this.id;\n\t},\n\tdeviceIcon: function () {\n\t\treturn this.metrics.icon = this.deviceType;\n\t},\n\tperformCommand: function () {\n\t\tconsole.log(\"--- \", this.id, \"performCommand processing:\", JSON.stringify(arguments));\n\t\tif (typeof this.handler === \"function\") {\n\t\t\ttry {\n\t\t\t\treturn this.handler.apply(this, arguments);\n\t\t\t} catch(e) {\n\t\t\t\tvar langFile = this.controller.loadMainLang();\n\t\t\t\tthis.controller.addNotification(\"error\", langFile.vd_err_virtual_dev + e.toString(), \"module\", \"VirtualDevice\");\n\t\t\t\tconsole.log(e.stack);\n\t\t\t}\n\t\t}\n\t},\n\taddTag: function (tag) {\n\t\tvar tags = this.get('tags');\n\t\tthis.set({'tags': _.uniq(_.union(tags, [tag]))});\n\t},\n\tremoveTag: function (tag) {\n\t\tvar tags = this.get('tags');\n\t\tthis.set({'tags': _.without(tags, tag)});\n\t},\n\t\n\t// wrappers for events\n\ton: function(eventName, func) {\n\t\treturn this.collection.on(this.id + \":\" + eventName, func);\n\t},\n\toff: function(eventName, func) {\n\t\treturn this.collection.off(this.id + \":\" + eventName, func);\n\t},\n\temit: function(eventName, that) {\n\t\treturn this.collection.emit(this.id + \":\" + eventName, that);\n\t},\n\t_sortObjectByKey: function(o){\n\t\tvar sorted = {},\n\t\t\tkey, a = [];\n\n\t\tfor (key in o) {\n\t\t\tif (o.hasOwnProperty(key)) {\n\t\t\t\ta.push(key);\n\t\t\t}\n\t\t}\n\n\t\ta.sort();\n\n\t\tfor (key = 0; key < a.length; key++) {\n\t\t\tsorted[a[key]] = o[a[key]];\n\t\t}\n\t\treturn sorted;\n\t}\n});\n"
  },
  {
    "path": "defaultConfigs/README",
    "content": "These configs are used to prepare distribs for different platforms\n\nNB! Please keep all theses files beautified! Use http://jsbeautifier.org/ to keep them well formatted.\n\nShort legenda:\nconfig.json_ttyACM0 - for Raspberry Pi with UZB\nconfig.json_ttyACM0_ZBW-no - for any Linux machine with UZB but without remote access functionality\nconfig.json_ttyACM0_ZBW-WD - WD special config\nconfig.json_ttyAMA0 - for RaZberry\nconfig.json_ttyAMA0_NonExpert - for RaZberry but no expert view\nconfig.json_ttyS0 - for ttyS0 for embedded boxes\nconfig.json_ttyS0-JBox - for James Box\nconfig.json_ttyS0-ReHub - for Rehau Hub\nconfig.json_ttyS1 - for ttyS1 for embedded boxes\nconfig.json_ttyUSB0_ZBW-no_vDev-no - for old white Z-Stick without any HA and with public Z-Wave API\nconfig.json_windows - for Windows\n"
  },
  {
    "path": "defaultConfigs/config.json",
    "content": "{\n\t\"controller\": {\n\t\t\"initial\": true\n\t},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyACM0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\\n(Added by default)\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}\n"
  },
  {
    "path": "defaultConfigs/config.json_WB",
    "content": "{\n\t\"controller\": {\n\t\t\"initial\": true\n\t},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyMOD4\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"configs/config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\\n(Added by default)\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}, {\n\t\t\"id\": 15,\n\t\t\"moduleId\": \"Zigbee\",\n\t\t\"active\": true,\n\t\t\"title\": \"Zigbee Network Access\",\n\t\t\"params\":{\n\t\t\t\"name\": \"zbee\",\n\t\t\t\"port\": \"/dev/ttyMOD3\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"config\": \"configs/config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t}\n\t}, {\n\t\t\"id\": 16,\n\t\t\"moduleId\": \"WBMQTTNative\",\n\t\t\"active\": true,\n\t\t\"title\": \"Wiren Board MQTT Integration Native\",\n\t\t\"params\": {\n\t\t\t\"clientId\": \"wbzway\",\n\t\t\t\"host\": \"localhost\",\n\t\t\t\"port\": \"1883\",\n\t\t\t\"user\": \"none\",\n\t\t\t\"password\": \"none\",\n\t\t\t\"topicPrefix\": \"/devices/zway\",\n\t\t\t\"topicPostfixSet\": \"on\",\n\t\t\t\"precision\": 0.01,\n\t\t\t\"groupByDevices\": true,\n\t\t\t\"debug\": false\n\t\t}\n\t}, {\n\t\t\"id\": 17,\n\t\t\"moduleId\": \"WBMQTTImport\",\n\t\t\"active\": true,\n\t\t\"title\": \"Wiren Board MQTT connector for Z-Way\",\n\t\t\"params\": {\n\t\t\t\"clientId\": \"zwaywb\",\n\t\t\t\"host\": \"localhost\",\n\t\t\t\"port\": \"1883\",\n\t\t\t\"user\": \"none\",\n\t\t\t\"password\": \"none\",\n\t\t\t\"debug\": false\n\t\t}\n\t}]\n}"
  },
  {
    "path": "defaultConfigs/config.json_ttyACM0",
    "content": "{\n\t\"controller\": {\n\t\t\"initial\": true\n\t},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyACM0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\\n(Added by default)\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}\n"
  },
  {
    "path": "defaultConfigs/config.json_ttyACM0_ZBW-WD",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyACM0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"./zbw\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Info: Licence Upgrade\",\n\t\t\"description\": \"Please follow the steps for licence upgrade.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Info: Licence Upgrade\",\n\t\t\t\t\"text\": \"Please enter the licence key to activate all of your WD SmartHome center’s functions. You can find the key on the keycard provided with your Smart Home Stick. <br><br>Go to the SmartHomeUI and select <strong>Menu > Management > Licence Upgrade</strong> and enter the licence key.\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Info: Lizenzerweiterung \",\n\t\t\t\t\"text\": \"Um alle Funktionen Ihrer WD SmartHome Zentrale nutzen zu können, geben Sie bitte den Lizenzcode ein. Dieser liegt dem Smart Home Stick als Code-Karte bei. <br><br>Wählen Sie in der SmartHomeUI <strong>Menü > Management > Lizenzerweiterung</strong> und geben Sie den Lizenzcode ein.\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}"
  },
  {
    "path": "defaultConfigs/config.json_ttyACM0_ZBW-no",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyACM0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 10,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 11,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}"
  },
  {
    "path": "defaultConfigs/config.json_ttyAMA0",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyAMA0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n }"
  },
  {
    "path": "defaultConfigs/config.json_ttyAMA0_NonExpert",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyAMA0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 10,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 11,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}"
  },
  {
    "path": "defaultConfigs/config.json_ttyS0",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyS0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}\n"
  },
  {
    "path": "defaultConfigs/config.json_ttyS0-JBox",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyS0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"disable\",\n\t\t\t\"config\": \"configs/config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"PhilioHW\",\n\t\t\"active\": true,\n\t\t\"title\": \"Philio hardware support\",\n\t\t\"description\": \"Support for Philio hardware buttons, LEDs, power and battery management\",\n\t\t\"params\": {\n\t\t\t\"no_battery\": false\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"ZMEOpenWRT\",\n\t\t\"active\": true,\n\t\t\"title\": \"Time zone and access from WAN\",\n\t\t\"params\": {\n\t\t\t\"timezone\": \"UTC\",\n\t\t\t\"wan_port_access\": false\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"TamperAutoOff\",\n\t\t\"active\": true,\n\t\t\"title\": \"Tamper Auto Off\",\n\t\t\"params\": {\n\t\t\t\"devices\": [],\n\t\t\t\"timeout\": 30\n\t\t}\n\t}, {\n\t\t\"id\": 11,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 13,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 15,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 16,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}\n"
  },
  {
    "path": "defaultConfigs/config.json_ttyS0-ReHub",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyS0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"disable\",\n\t\t\t\"config\": \"configs/config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"PhilioHW\",\n\t\t\"active\": true,\n\t\t\"title\": \"Philio hardware support\",\n\t\t\"description\": \"Support for Philio hardware buttons, LEDs, power and battery management\",\n\t\t\"params\": {\n\t\t\t\"no_battery\": false\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"ZMEOpenWRT\",\n\t\t\"active\": true,\n\t\t\"title\": \"Time zone and access from WAN\",\n\t\t\"params\": {\n\t\t\t\"timezone\": \"UTC\",\n\t\t\t\"wan_port_access\": false\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"TamperAutoOff\",\n\t\t\"active\": true,\n\t\t\"title\": \"Tamper Auto Off\",\n\t\t\"params\": {\n\t\t\t\"devices\": [],\n\t\t\t\"timeout\": 30\n\t\t}\n\t}, {\n\t\t\"id\": 11,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 13,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 14,\n\t\t\"moduleId\": \"RemoteID_Transfer\",\n\t\t\"active\": true,\n\t\t\"title\": \"Transfer Remote Id to C-Module\",\n\t\t\"description\": \"Sends RemoteId to C-Modul\",\n\t\t\"params\": {}\n\t}, {\n\t\t\"id\": 15,\n\t\t\"moduleId\": \"SensorEvaluation\",\n\t\t\"active\": true,\n\t\t\"title\": \"Send sensordata to the C-Module\",\n\t\t\"description\": \"Send sensordata to the C-Module\",\n\t\t\"params\": {\n\t\t\t\"closeValveOption\": true,\n\t\t\t\"floodSensorOption\": true,\n\t\t\t\"cronSensorsEvaluationUpdateOption\": 1,\n\t\t\t\"cronSendLeckageDeviceDataOption\": 1,\n\t\t\t\"cronSendBatteryAndTempOption\": 30\n\t\t}\n\t}]\n}"
  },
  {
    "path": "defaultConfigs/config.json_ttyS1",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyS1\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"RemoteAccess\",\n\t\t\"active\": true,\n\t\t\"title\": \"Remote Access\",\n\t\t\"description\": \"Is necessary to configure remote access in SmartHome UI.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"path\": \"\",\n\t\t\t\"userId\": \"\",\n\t\t\t\"actStatus\": true,\n\t\t\t\"sshStatus\": false,\n\t\t\t\"zbwStatus\": true,\n\t\t\t\"pass\": \"\",\n\t\t\t\"lastChange\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 10,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 11,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}\n"
  },
  {
    "path": "defaultConfigs/config.json_ttyUSB0_ZBW-no_vDev-no",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"/dev/ttyUSB0\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": true,\n\t\t\t\"createVDev\": false,\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Open ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Öffne ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t},{\n\t\t\t\"id\": 3,\n\t\t\t\"moduleId\": \"CloudBackup\",\n\t\t\t\"active\": true,\n\t\t\t\"title\": \"CloudBackup\",\n\t\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\t\"params\": {\n\t\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\t\"user_active\": false,\n\t\t\t\t\"email\": \"\",\n\t\t\t\t\"email_log\": \"0\",\n\t\t\t\t\"remoteid\": null,\n\t\t\t\t\"days\": \"28\",\n\t\t\t\t\"weekDays\": null,\n\t\t\t\t\"hours\": \"23\",\n\t\t\t\t\"minutes\": \"59\",\n\t\t\t\t\"scheduler\": \"3\"\n\t\t\t}\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong> Menü Anwendungen > Aktiv<strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}]\n}"
  },
  {
    "path": "defaultConfigs/config.json_windows",
    "content": "{\n\t\"controller\": {},\n\t\"vdevInfo\": {},\n\t\"locations\": [{\n\t\t\"id\": 0,\n\t\t\"title\": \"globalRoom\",\n\t\t\"user_img\": \"\",\n\t\t\"default_img\": \"\",\n\t\t\"img_type\": \"\"\n\t}],\n\t\"profiles\": [{\n\t\t\"id\": 1,\n\t\t\"role\": 1,\n\t\t\"login\": \"admin\",\n\t\t\"password\": \"admin\",\n\t\t\"name\": \"Administrator\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}, {\n\t\t\"id\": 2,\n\t\t\"role\": 3,\n\t\t\"login\": \"local\",\n\t\t\"password\": \"local\",\n\t\t\"name\": \"Local User\",\n\t\t\"lang\": \"en\",\n\t\t\"dashboard\": [],\n\t\t\"interval\": 2000,\n\t\t\"devices\": [],\n\t\t\"rooms\": [0],\n\t\t\"expert_view\": true,\n\t\t\"hide_all_device_events\": false,\n\t\t\"hide_system_events\": false,\n\t\t\"hide_single_device_events\": [],\n\t\t\"email\": \"\",\n\t\t\"skin\": \"\",\n\t\t\"night_mode\": false,\n\t\t\"beta\": false\n\t}],\n\t\"instances\": [{\n\t\t\"id\": 1,\n\t\t\"moduleId\": \"ZWave\",\n\t\t\"params\": {\n\t\t\t\"name\": \"zway\",\n\t\t\t\"port\": \"\\\\\\\\.\\\\COM3\",\n\t\t\t\"speed\": 115200,\n\t\t\t\"enableAPI\": true,\n\t\t\t\"publicAPI\": false,\n\t\t\t\"createVDev\": true,\n\t\t\t\"enablePacketLog\": \"enable\",\n\t\t\t\"config\": \"config\",\n\t\t\t\"translations\": \"translations\",\n\t\t\t\"ZDDX\": \"ZDDX\"\n\t\t},\n\t\t\"active\": true,\n\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 2,\n\t\t\"moduleId\": \"Cron\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"System Clock (CRON)\",\n\t\t\"description\": \"Scheduler used by other modules\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 3,\n\t\t\"moduleId\": \"InbandNotifications\",\n\t\t\"params\": {},\n\t\t\"active\": true,\n\t\t\"title\": \"Inband Notifier\",\n\t\t\"description\": \"Creates and records the presentation of events in the event list (Eventlog).\\n(Added by default)\"\n\t}, {\n\t\t\"id\": 4,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Dear Expert User\",\n\t\t\"description\": \"Dieses Modul erzeugt ein Informations Widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Dear Expert User\",\n\t\t\t\t\"text\": \"<center>If you still want to use ExpertUI please go, after you are successfully logged in, to <br><strong> Menu > Devices > Manage with ExpertUI </strong> <br> or call <br><strong> http://MYRASP:8083/expert </strong><br> in your browser. <br> <br>You could hide or remove this widget in menu <br><strong>Apps > Active Tab</strong>. </center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Lieber Expert User\",\n\t\t\t\t\"text\": \"<center>Wenn Sie weiterhin die ExpertUI nutzen möchten, dann klicken Sie bitte, nachdem Sie sich erfolgreich angemeldet haben, auf <br><strong> Menü > Geräte > Verwaltung mit ExpertUI </strong> <br> oder rufen Sie <br><strong> http://MYRASP:8083/expert </strong><br> in Ihrem Browser auf. <br> <br>Sie können dieses Element im Menü <br><strong>Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/logo-z-wave-z-only.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\": 5,\n\t\t\"moduleId\": \"SensorsPolling\",\n\t\t\"active\": false,\n\t\t\"title\": \"Periodical Sensor Polling\",\n\t\t\"description\": \"Queries in an adjustable interval all measurement sensors. It can be entered a list of sensors, which should not be queried.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"pollDevsWithBatteries\": false,\n\t\t\t\"devices\": [],\n\t\t\t\"devicesWithBattery\": [],\n\t\t\t\"period\": \"10\"\n\t\t}\n\t}, {\n\t\t\"id\": 6,\n\t\t\"moduleId\": \"BatteryPolling\",\n\t\t\"active\": true,\n\t\t\"title\": \"Battery Polling\",\n\t\t\"description\": \"Set up an interval that regularly polls the battery status of a battery devices.\\n(Added by default)\",\n\t\t\"params\": {\n\t\t\t\"launchWeekDay\": 0,\n\t\t\t\"warningLevel\": \"20\"\n\t\t}\n\t}, {\n\t\t\"id\": 7,\n\t\t\"moduleId\": \"SwitchControlGenerator\",\n\t\t\"active\": true,\n\t\t\"title\": \"Trap events from Remotes and Sensors\",\n\t\t\"description\": \"\",\n\t\t\"params\": {\n\t\t\t\"trapNew\": true,\n\t\t\t\"banned\": [],\n\t\t\t\"generated\": []\n\t\t}\n\t}, {\n\t\t\"id\": 8,\n\t\t\"moduleId\": \"CloudBackup\",\n\t\t\"active\": true,\n\t\t\"title\": \"CloudBackup\",\n\t\t\"description\": \"Gives possibility to upload and store your backups on the remote server.\",\n\t\t\"params\": {\n\t\t\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\t\t\"user_active\": false,\n\t\t\t\"email\": \"\",\n\t\t\t\"email_log\": \"0\",\n\t\t\t\"remoteid\": null,\n\t\t\t\"days\": \"28\",\n\t\t\t\"weekDays\": null,\n\t\t\t\"hours\": \"23\",\n\t\t\t\"minutes\": \"59\",\n\t\t\t\"scheduler\": \"3\"\n\t\t}\n\t}, {\n\t\t\"id\": 9,\n\t\t\"moduleId\": \"InfoWidget\",\n\t\t\"active\": true,\n\t\t\"title\": \"Cloud Backup Instructions\",\n\t\t\"description\": \"This module creates an information widget.\",\n\t\t\"params\": {\n\t\t\t\"widgets\": [],\n\t\t\t\"internationalize\": true,\n\t\t\t\"widgetsInt\": [{\n\t\t\t\t\"lang\": \"en\",\n\t\t\t\t\"headline\": \"Cloud Backup Instructions\",\n\t\t\t\t\"text\": \"<center>Cloud backup is conveniently saving up to 3 backup files on our server (using SSL encryption).<br>By default, an automatic backup is created every month on 28 at 23:59.<br>If you don’t like to see your backup file on our server, just deactivate this service or change the interval.</br>To change the settings, please click on<br><strong>Menu > Management > Backup & Restore.</strong><br><br>You could hide or remove this widget in<br><strong>Menu >Apps > Active Tab</strong>.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}, {\n\t\t\t\t\"lang\": \"de\",\n\t\t\t\t\"headline\": \"Cloud Backup Anleitung\",\n\t\t\t\t\"text\": \"<center>Cloud Backup sichert bis zu 3 Kopien Ihrer Daten automatisch auf unserem Server (mittels SSL Verschlüsselung).<br>Standard mäßig wird jeden Monat am 28 um 23:59 ein automatisches Backup erstellt.<br>Sollten Sie das nicht wünschen dann ändern Sie den Interval oder deaktivieren Sie diese Funktion.<br>Zum ändern der Einstellungen klicken Sie bitte auf <br><strong>Menü > Management > Datensicherung & Wiederherstellung.</strong><br><br>Sie können dieses Element im<br><strong>Menü > Anwendungen > Aktiv</strong><br> auschalten oder entfernen.</center>\",\n\t\t\t\t\"imgURI\": \"app/img/icon_cloudbackup.png\"\n\t\t\t}]\n\t\t}\n\t}, {\n\t\t\"id\" : 10,\n\t\t\"moduleId\" : \"MobileAppSupport\",\n\t\t\"active\" : true,\n\t\t\"title\" : \"Mobile App Support\",\n\t\t\"description\": \"This module is required by the mobile phone app (Android, iOS). State updates of all devices and events are send at runtime to the mobile phone. Additional notifications can be configured that will be send in background. Currently event forwarding is supported (the same logic as for pushbullet module).\",\n\t\t\"params\" : {\n\t\t\t\"apps\" : []\n\t\t}\n\t}, {\n\t\t\"id\": 11,\n\t\t\"moduleId\": \"HomeKitGate\",\n\t\t\"active\": true,\n\t\t\"title\": \"Apple HomeKit Gate\",\n\t\t\"params\": {\n\t\t\t\"name\": \"Z-Wave.Me\",\n\t\t\t\"skippedDevices\": [],\n\t\t\t\"idMapping\": {}\n\t\t}\n\t}, {\n\t\t\"id\": 12,\n\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notification Filtering\",\n\t\t\"params\": {\n\t\t\t\"rules\": [{\n\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\"user\": 1,\n\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\"devices\": []\n\t\t\t}],\n\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\"normalizeRules\": true\n\t\t}\n\t}, {\n\t\t\"id\": 13,\n\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\"active\": true,\n\t\t\"title\": \"Notifications by E-mail\",\n\t\t\"params\": {\n\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\"channels\": []\n\t\t}\n\t}]\n}\n"
  },
  {
    "path": "lang/cn.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/cz.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Nebyla nalezena závislost modulu: [DEP] :: [MODUL] =\",\n    \"ac_err_dep_not_init\": \"Načtení modulu selhalo, protože pro závislost modulu nebyla vytvořena instance: [DEP] :: [MODUL] =\",\n    \"ac_err_dep_not_loaded\": \"Načtení modulu selhalo, protože závislost modulu nebyla načtení: [DEP] :: [MODUL] =\",\n    \"ac_err_file_load\": \"Nelze načíst\",\n    \"ac_err_init_module\": \"Nelze vytvořit instanci modulu:\",\n    \"ac_err_init_module_not_found\": \"Nelze vytvořit instanci modulu: modul nenalezen v seznamu všech modulů.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Neplatný modul\",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Nelze načíst modules.json z\",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Nelze zastavit modul\",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automatizační Kontrolér je restartován.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"Toto je profil admina. Profil admina je vytvořen automaticky.\",\n    \"profile_name\": \"Administrátor\",\n    \"vd_err_virtual_dev\": \"Chyba, během provádění příkazu:\",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/de.json",
    "content": "{\n    \"ac_err_create_instance\": \"Es konnte keine neue Instanz von der App erzeugt werden. [APP] :: [INSTANZ ID] = \",\n    \"ac_err_dep_not_found\": \"Die Dependency wurde für das Modul nicht gefunden: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Das Modul kann nicht geladen werden, da die Dependency nicht instanziiert wurde: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Das Modul kann nicht geladen werden, da folgende Dependency nicht geladen wurde: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Fehler beim Laden von \",\n    \"ac_err_init_module\": \"Das Modul kann nicht instanziiert werden: \",\n    \"ac_err_init_module_not_found\": \"Das Modul kann nicht instanziiert werden: Das Modul wurde in der Modulliste nicht gefunden.\",\n    \"ac_err_instance_already_exists\": \"Instanzierung fehlgeschlagen. Folgende Instanz Id wird bereits verwendet: \",\n    \"ac_err_instance_empty\": \"Leere Instanzen können nicht instanziert werden: \",\n    \"ac_err_invalid_module\": \"Nicht valides Modul: \",\n    \"ac_err_load_failure\": \"Es trat ein Fehler während der Initialisierung der App auf. Bitte installieren oder laden sie die folgende App erneut\",\n    \"ac_err_load_mod_json\": \"modules.json kann nicht geladen werden. Modul: \",\n    \"ac_err_location_not_found\": \"Der Raum existiert nicht.\",\n    \"ac_err_refonfigure_instance\": \"Folgende Instanz konnte nicht geupdatet werden: \",\n    \"ac_err_stop_mod\": \"Das folgende Modul kann nicht gestoppt werden: \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Die App konnte nicht deinstalliert oder wiederhergestellt werden.\",\n    \"ac_err_uninstall_skin\": \"Das Icon konnte nicht deinstalliert werden.\",\n    \"ac_warn_restart\": \"Der Automation Controller wurde neu gestartet.\",\n    \"err_parsing_npc_filters\": \"Die Namespaces-Filter konnten nicht gefunden\\/gelesen werden.\",\n    \"err_preparing_room_dev_structure\": \"Die Raum-Geräte Beziehung konnte nicht erzeugt werden\",\n    \"no_devices_found\": \"Keine Geräte gefunden\",\n    \"profile_descr\": \"Dies ist das Administratorprofil. Dieses wird automatisch angelegt.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Fehler beim Ausführen des Befehls: \",\n    \"zaap_err_app_install\": \"Während der Installation ist ein Fehler aufgetreten. Die Installation wurde abgebrochen.\",\n    \"zaap_err_no_archives\": \"Diese App hat kein Archiv. Die Installation wurde abgebrochen.\",\n    \"zaap_err_reboot\": \"Die Systemneustart wird auf Ihrem Gerät nicht unterstützt. Starten Sie ihr System neu, in dem Sie kurz die Stromversorgung trennen oder die Anweisungen aus dem Handbuch befolgen.\",\n    \"zaap_err_server\": \"Der Download-Server ist nicht erreichbar oder hat mit einem Fehler geantwortet. Versuchen Sie es später erneut.\",\n    \"zaap_err_uninstall_mod\": \"Die App konnte nicht deinstalliert werden.\",\n    \"zaap_err_unload_mod\": \"Die App konnte nicht gelöscht werden.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"Es stand keine App im Archiv mit dieser Version zur Verfügung. Stattdessen wurde die aktuellste Version installiert. Es kann vorkommen, dass bereits aktive Instanzen dieser App anschließend nicht mehr funktionieren. Bitte entfernen Sie diese von den Anwendungen > Aktiv und fügen Sie diese neu hinzu unter Anwendungen > Lokal.\",\n    \"zaap_war_core_app_is_newer\": \"Die App ist bereits mit der selben oder einer höheren auf ihrem System vorinstalliert. Die Installation wurde abgebrochen. Es kann vorkommen, dass bereits aktive Instanzen dieser App anschließend nicht mehr funktionieren. Bitte entfernen Sie diese von den Anwendungen > Aktiv und fügen Sie diese neu hinzu unter Anwendungen > Lokal.\",\n    \"zaap_war_restart_necessary\": \"Die App wurde erfolgreich herunter geladen, aber die Initialisierung ist fehlgeschlagen. Bitte starten Sie den Server neu um die Initialisierung abzuschließen.\"\n}"
  },
  {
    "path": "lang/en.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/es.json",
    "content": "{\n    \"ac_err_create_instance\": \"No se ha podido crear la instancia. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependencia no encontrada para el módulo: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"No se ha podido cargar el módulo porque la dependencia no se ha instanciado: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"No se ha podido cargar el módulo porque la dependencia no se ha cargado: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"No se ha podido cargar \",\n    \"ac_err_init_module\": \"No se ha podido instanciar el módulo: \",\n    \"ac_err_init_module_not_found\": \"No se ha podido instanciar el módulo: módulo no encontrado en la lista de todos los módulos.\",\n    \"ac_err_instance_already_exists\": \"No se pueden registrar instancias de módulo duplicadas: \",\n    \"ac_err_instance_empty\": \"No se pueden registrar instancias de módulo vacías: \",\n    \"ac_err_invalid_module\": \"Módulo no válido \",\n    \"ac_err_load_failure\": \"Se ha producido un fallo mientras la aplicación se instanciaba. Vuelva a cargar o a instalar la aplicación\",\n    \"ac_err_load_mod_json\": \"No se han podido cargar los módulos .json desde \",\n    \"ac_err_location_not_found\": \"La ubicación no existe.\",\n    \"ac_err_refonfigure_instance\": \"No se ha podido reconfigurar la instancia con el id.: \",\n    \"ac_err_stop_mod\": \"No se ha podido detener el módulo \",\n    \"ac_err_uninstall_icon\": \"No se ha podido desinstalar el icono.\",\n    \"ac_err_uninstall_mod\": \"No se ha podido desinstalar ni reiniciar la aplicación.\",\n    \"ac_err_uninstall_skin\": \"No se ha podido desinstalar el tapiz.\",\n    \"ac_warn_restart\": \"El controlador de automatización se ha reiniciado.\",\n    \"err_parsing_npc_filters\": \"No se han podido analizar los filtros a partir de los espacios nominales.\",\n    \"err_preparing_room_dev_structure\": \"No se ha podido preparar la relación Habitación-Dispositivo.\",\n    \"no_devices_found\": \"No se ha encontrado ningún dispositivo\",\n    \"profile_descr\": \"Este es el perfil del administrador. Perfil del administrador creado automáticamente.\",\n    \"profile_name\": \"Administrador\",\n    \"vd_err_virtual_dev\": \"Error durante la ejecución del comando: \",\n    \"zaap_err_app_install\": \"Se ha producido un error durante la instalación de la aplicación. La instalación se ha cancelado.\",\n    \"zaap_err_no_archives\": \"Esta aplicación no tiene archivo. La instalación se ha cancelado.\",\n    \"zaap_err_reboot\": \"Su plataforma no admite el comando de reinicio, desconecte la alimentación o siga las indicaciones del manual del controlador.\",\n    \"zaap_err_server\": \"No se ha podido acceder al servidor de descarga o este responde con un error. Inténtelo de nuevo más tarde.\",\n    \"zaap_err_uninstall_mod\": \"No se ha podido desinstalar la aplicación.\",\n    \"zaap_err_unload_mod\": \"No se ha podido descargar la aplicación.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"No se ha encontrado ninguna aplicación con esta versión en el archivo disponible. En su lugar se ha instalado la versión más reciente. Puede que las instancias de esta aplicación existentes ya no funcionen. Elimínelas de Apps > Active y añada las nuevas a Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"Esta aplicación ya está instalada con la misma versión o una más reciente. La instalación se ha cancelado. Puede que las instancias existentes de esta aplicación ya no funcionen. Elimínelas de Apps > Active y añada las nuevas a Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"La aplicación se ha descargado correctamente pero la inicialización no se ha podido llevar a cabo. Reinicie el servidor para concluir la inicialización.\"\n}"
  },
  {
    "path": "lang/fi.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/fr.json",
    "content": "{\n    \"ac_err_create_instance\": \"Création d'une instance impossible. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dépendance du module introuvable: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Échec du chargement du module car une dépendance n'est pas initialisé: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Échec du chargement du module car une dépendance n'est pas chargé: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Chargement impossible \",\n    \"ac_err_init_module\": \"Impossible d'appliquer le module: \",\n    \"ac_err_init_module_not_found\": \"Impossible d'appliquer le module: le module est introuvable parmis la liste des modules.\",\n    \"ac_err_instance_already_exists\": \"Impossible d'enregistrer une autre instance du module: \",\n    \"ac_err_instance_empty\": \"Impossible d'enregistrer une instance vide du module: \",\n    \"ac_err_invalid_module\": \"Module invalide \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Chargement impossible de modules.json en provenance de \",\n    \"ac_err_location_not_found\": \"Localité inexistante.\",\n    \"ac_err_refonfigure_instance\": \"Impossible de reconfigurer l'instance avec l'identifiant: \",\n    \"ac_err_stop_mod\": \"Impossible d'arrêter le module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Impossible d'arrêter ou de redémarrer l'application.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Votre contrôleur redémarre.\",\n    \"err_parsing_npc_filters\": \"Impossible de filtrer à partir de l'espace de noms.\",\n    \"err_preparing_room_dev_structure\": \"Impossible de préparer le lien entre la pièce et le dispositif.\",\n    \"no_devices_found\": \"Aucun dispositif trouvé\",\n    \"profile_descr\": \"Ceci est le profil admin. le profil admin est créé automatiquement.\",\n    \"profile_name\": \"Administrateur\",\n    \"vd_err_virtual_dev\": \"Erreur lors de l'exécution de la commande: \",\n    \"zaap_err_app_install\": \"Une erreur s'est produite lors de l'installation de l'application. L'installation a été annulé.\",\n    \"zaap_err_no_archives\": \"Cette application n'a pas d'archive. L'installation a été annulée.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"Le serveur de téléchargement n'est pas accessible ou ne répond pas. Veuillez réessayer plus tard.\",\n    \"zaap_err_uninstall_mod\": \"Impossible de désinataller l'application.\",\n    \"zaap_err_unload_mod\": \"Impossible de décharger l'application.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"Aucune application avec cette version dans les archives disponibles. La dernière version a été installé en remplacement. Il est possible que des instances existantes de cette application cessent de fonctionner. Veuillez les retirer dans Applications > Actives et ajouté les nouvelles sous Applications > Application locale\",\n    \"zaap_war_core_app_is_newer\": \"Cette application est déjà installé avec une version supérieur ou identique. L'installation a été annulée. Il est possible que des instances existantes de cette application cessent de fonctionner. Veuillez les retirer dans Applications > Actives et ajouté les nouvelles sous Applications > Application locale.\",\n    \"zaap_war_restart_necessary\": \"L'application a été téléchargé mais l'initialisation a échoué. Veuillez redémarrer le serveur afin de terminer l'initialisation.\"\n}"
  },
  {
    "path": "lang/it.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/pt.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/ru.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/se.json",
    "content": "{\t\n\t\"ac_warn_restart\":\"Automationskontrollern är omstartad.\",\n\t\"ac_err_init_module_not_found\":\"Cannot instantiate module: module not found in the list of all modules.\",\n\t\"ac_err_init_module\":\"Cannot instantiate module: \",\n\t\"ac_err_dep_not_found\":\"Beroenden kan inte hittas för modul: [DEP]::[MODUL] = \",\n\t\"ac_err_dep_not_loaded\":\"Kan inte ladda modulen då beroendet inte var laddad: [DEP]::[MODUL] = \",\n\t\"ac_err_dep_not_init\":\"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n\t\"ac_err_file_load\":\"Kan inte ladda \",\n\t\"ac_err_invalid_module\":\"Felaktig modul \",\n\t\"ac_err_load_mod_json\":\"Kan inte ladda modules.json från \",\n\t\"ac_err_stop_mod\":\"Kan inte stoppa modul \",\n\t\"ac_err_uninstall_mod\":\"Unable to uninstall or reset app.\",\n\t\"ac_err_uninstall_skin\":\"Unable to uninstall skin.\",\n\t\"ac_err_instance_already_exists\":\"Can't register duplicate module instance: \",\n\t\"ac_err_instance_empty\":\"Can't register empty module instance: \",\n\t\"ac_err_create_instance\":\"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n\t\"ac_err_refonfigure_instance\":\"Cannot reconfigure instance with id: \",\n\t\"ac_err_location_not_found\":\"Location doesn't exist.\",\n\t\"ac_err_load_failure\":\"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n\t\"profile_name\": \"Administratör\",\n\t\"profile_descr\": \"Detta är adminprofilen. Adminprofilen skapades automatiskt.\", \n\t\"vd_err_virtual_dev\":\"Error during perform command execution: \",\n\t\"zaap_err_uninstall_mod\":\"Unable to uninstall app.\",\n\t\"zaap_err_unload_mod\":\"Unable to unload app.\",\n\t\"zaap_war_restart_necessary\":\"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\",\n\t\"zaap_err_app_install\":\"An error has occurred during the app installation. The installation was cancelled.\",\n\t\"zaap_war_app_installed_corrupt_instance\":\"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n\t\"zaap_war_core_app_is_newer\":\"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n\t\"zaap_err_no_archives\":\"This app has no archive. The installation was cancelled.\",\n\t\"zaap_err_server\":\"The download server is not reachable or responses with an error. Please try again later.\",\n\t\"zaap_err_reboot\":\"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\"\n}"
  },
  {
    "path": "lang/sk.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Nebola nájdená závislosť modulu: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Načítanie modulu zlyhalo, pretože pre závislosť modulu nebola vytvorená inštancia: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Načítanie modulu zlyhalo, pretože závislosť modulu nebola načítana: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Nedá sa načítať \",\n    \"ac_err_init_module\": \"Nie je možné vytvoriť inštanciu modulu: \",\n    \"ac_err_init_module_not_found\": \"Nie je možné vytvoriť inštanciu modulu: modul nenájdený v zozname všetkých modulov.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Neplatný modul \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Nedá sa načítať modules.json z \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Nedá sa zastaviť modul \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automatizačný Kontrolér je reštartovaný.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"Toto je profil admina. Profil admina je vytvorený automaticky.\",\n    \"profile_name\": \"Administrátor\",\n    \"vd_err_virtual_dev\": \"Chyba, počas vykonávania príkazu: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lang/sv.json",
    "content": "{\n    \"ac_err_create_instance\": \"Cannot create instance. [APP] :: [INSTANCE ID] = \",\n    \"ac_err_dep_not_found\": \"Dependency not found for module: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_init\": \"Failed to load module because dependency was not instanciated: [DEP]::[MODUL] = \",\n    \"ac_err_dep_not_loaded\": \"Failed to load module because dependency was not loaded: [DEP]::[MODUL] = \",\n    \"ac_err_file_load\": \"Cannot load \",\n    \"ac_err_init_module\": \"Cannot instantiate module: \",\n    \"ac_err_init_module_not_found\": \"Cannot instantiate module: module not found in the list of all modules.\",\n    \"ac_err_instance_already_exists\": \"Can't register duplicate module instance: \",\n    \"ac_err_instance_empty\": \"Can't register empty module instance: \",\n    \"ac_err_invalid_module\": \"Invalid module \",\n    \"ac_err_load_failure\": \"An error has occurred while the app was instantiated. Please reload or reinstall the app\",\n    \"ac_err_load_mod_json\": \"Cannot load modules.json from \",\n    \"ac_err_location_not_found\": \"Location doesn't exist.\",\n    \"ac_err_refonfigure_instance\": \"Cannot reconfigure instance with id: \",\n    \"ac_err_stop_mod\": \"Cannot stop module \",\n    \"ac_err_uninstall_icon\": \"Unable to uninstall icon.\",\n    \"ac_err_uninstall_mod\": \"Unable to uninstall or reset app.\",\n    \"ac_err_uninstall_skin\": \"Unable to uninstall skin.\",\n    \"ac_warn_restart\": \"Automation Controller is restarted.\",\n    \"err_parsing_npc_filters\": \"Cannot parse filters from namespaces.\",\n    \"err_preparing_room_dev_structure\": \"Cannot prepare Room-Device relation.\",\n    \"no_devices_found\": \"No devices found\",\n    \"profile_descr\": \"This is the admin profile. Admin profile created automatically.\",\n    \"profile_name\": \"Administrator\",\n    \"vd_err_virtual_dev\": \"Error during perform command execution: \",\n    \"zaap_err_app_install\": \"An error has occurred during the app installation. The installation was cancelled.\",\n    \"zaap_err_no_archives\": \"This app has no archive. The installation was cancelled.\",\n    \"zaap_err_reboot\": \"Reboot command is not supported on your platform, please unplug the power or follow the controller manual.\",\n    \"zaap_err_server\": \"The download server is not reachable or responses with an error. Please try again later.\",\n    \"zaap_err_uninstall_mod\": \"Unable to uninstall app.\",\n    \"zaap_err_unload_mod\": \"Unable to unload app.\",\n    \"zaap_war_app_installed_corrupt_instance\": \"There was no app with this version in the archive available. The lastest version was installed instead. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_core_app_is_newer\": \"This app is already installed with a newer or same version. The installation was cancelled. It could be that already existing instances of this app do not work anymore. Please remove them from Apps > Active and add new ones under Apps > Local.\",\n    \"zaap_war_restart_necessary\": \"The app was downloaded successfully but the initialization has failed. Please restart the server to finalize the initialization.\"\n}"
  },
  {
    "path": "lib/BAOS_API_2011_01_29_001.js",
    "content": "// BAOS_API_2011_01_29_001\nfunction BaosLib()\n{\n\t//////////////////////////////////////////////////\n\t// Member variables\t\t\t\t\t\t\t\t//\n\t//////////////////////////////////////////////////\n\t\n\tvar m_strIpAddr;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// IP address\n\tvar m_IndicationSession = 0;\t\t\t\t\t\t\t\t\t\t\t\t// Indication session\n\tvar m_IndFormat;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Format used for indications\n\t\n\tvar m_bEnableCallbackRespRcvd\t\t\t= false;\t\t\t\t\t\t\t// Disable callback (response received)\n\tvar m_bEnableCallbackIndicationUpdate\t= false;\t\t\t\t\t\t\t// Disable callback (indication update)\n\tvar m_bEnableCallbackInvalidSettings\t= false;\t\t\t\t\t\t\t// Disable callback (invalid settings)\n\tvar m_bEnableCallbackTransmitError\t\t= false;\t\t\t\t\t\t\t// Disable callback (transmit error)\n\t\n\tvar m_CallbackRespRcvd;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Callback for response received\n\tvar m_CallbackIndicationUpdate;\t\t\t\t\t\t\t\t\t\t\t\t// Callback for indication update\n\tvar m_CallbackInvalidSettings;\t\t\t\t\t\t\t\t\t\t\t\t// Callback for invalid settings\n\tvar m_CallbackTransmitError;\t\t\t\t\t\t\t\t\t\t\t\t// Callback for transmit error\n\t\n\t//////////////////////////////////////////////////\n\t// Public functions\t\t\t\t\t\t\t\t//\n\t//////////////////////////////////////////////////\n\t\n\t// This API function sets the IP address to the BAOS library\n\tthis.API_SetIpAddress = function (strIpAddr)\n\t{\n\t\tm_strIpAddr = strIpAddr;\t\t\t\t\t\t\t\t\t\t\t\t// Set IP address\n\t};\n\t\n\t// This API function sets the callback handler for the responses.\n\tthis.API_SetCallbackRespRcvd = function (strCallback)\n\t{\n\t\tm_CallbackRespRcvd = strCallback;\t\t\t\t\t\t\t\t\t\t// Save callback reference\n\t\tm_bEnableCallbackRespRcvd = true;\t\t\t\t\t\t\t\t\t\t// Enable callback\n\t};\n\t\n\t// This API function sets the callback handler for the indications.\n\tthis.API_SetCallbackIndicationUpdate = function (strCallback)\n\t{\n\t\tm_CallbackIndicationUpdate = strCallback;\t\t\t\t\t\t\t\t// Save callback reference\n\t\tm_bEnableCallbackIndicationUpdate = true;\t\t\t\t\t\t\t\t// Enable callback\n\t};\n\t\n\t// This API function sets the callback handler for informing about\n\t// invalid settings.\n\tthis.API_SetCallbackInvalidSettings = function (strCallback)\n\t{\n\t\tm_CallbackInvalidSettings = strCallback;\t\t\t\t\t\t\t\t// Save callback reference\n\t\tm_bEnableCallbackInvalidSettings = true;\t\t\t\t\t\t\t\t// Enable callback\n\t};\n\t\n\t// This API function sets the callback handler for informing about\n\t// transmission errors.\n\tthis.API_SetCallbackTransmitError = function (strCallback)\n\t{\n\t\tm_CallbackTransmitError = strCallback;\t\t\t\t\t\t\t\t\t// Save callback reference\n\t\tm_bEnableCallbackTransmitError = true;\t\t\t\t\t\t\t\t\t// Enable callback\n\t};\n\t\n\t// This API function gets server items from the BAOS device.\n\tthis.API_GetServerItem = function (strStartItem, strItemCount)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif((IsIpAddrValid(m_strIpAddr)) &&\n\t\t   (IsNumber(strStartItem)) && (IsNumber(strItemCount)))\t\t\t\t// If we have a valid IP address and valid parameters\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/GetServerItem?ItemStart=\" + strStartItem +\n\t\t\t\t\t \"&ItemCount=\" + strItemCount;\t\t\t\t\t\t\t\t// Prepare URL for GetServerItem\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  OnObjSrvRespRcvd(rsp.data);\n                },\n                error: function(rsp){\n                  console.log(\"Error description: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError();\n                },\n                complete: function(rsp){console.log(\"GetServerItem done\");}\n              });\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t};\n\t\n\t// This API function gets datapoint descriptions from the BAOS device.\n\tthis.API_GetDatapointDescription = function (strDatapointStart, strDatapointCount)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif((IsIpAddrValid(m_strIpAddr)) &&\n\t\t   (IsNumber(strDatapointStart)) && (IsNumber(strDatapointCount)))\t\t// If we have a valid IP address and valid parameters\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/GetDatapointDescription?DatapointStart=\" +\n\t\t\t\t\t strDatapointStart + \"&DatapointCount=\"+\n\t\t\t\t\t strDatapointCount;\t\t\t\t\t\t\t\t\t\t\t// Prepare URL for GetDatapointDescription\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  OnObjSrvRespRcvd(rsp.data);\n                },\n                error: function(rsp){\n                  console.log(\"Error DP description: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_GetDatapointDescription done\");}\n              });\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t};\n\t\n\t// This API function gets datapoint description strings from the\n\t// BAOS device.\n\tthis.API_GetDescriptionString = function (strDatapointStart, strDatapointCount)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif((IsIpAddrValid(m_strIpAddr)) &&\n\t\t   (IsNumber(strDatapointStart)) && (IsNumber(strDatapointCount)))\t\t// If we have a valid IP address and valid parameters\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/GetDescriptionString?DatapointStart=\" +\n\t\t\t\t\t strDatapointStart + \"&DatapointCount=\" +\n\t\t\t\t\t strDatapointCount;\t\t\t\t\t\t\t// Prepare URL for GetDescriptionString\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  OnObjSrvRespRcvd(rsp.data);\n                },\n                error: function(rsp){\n                  console.log(\"Error get description string: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_GetDescriptionString done\");}\n              });\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t};\n\t\n\t// This API function gets datapoint values from the BAOS device.\n\tthis.API_GetDatapointValue = function (strDatapointStart, strDatapointCount, strFormat)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif((IsIpAddrValid(m_strIpAddr)) &&\n\t\t   (IsNumber(strDatapointStart)) && (IsNumber(strDatapointCount)))\t\t// If we have a valid IP address and valid parameters\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/GetDatapointValue?DatapointStart=\" +\n\t\t\t\t\t strDatapointStart + \"&DatapointCount=\" +\n\t\t\t\t\t strDatapointCount + \"&Format=\" + strFormat;\t\t\t\t\t\t\t// Prepare URL for GetDatapointValule\n\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  OnObjSrvRespRcvd(rsp.data);\n                },\n                error: function(rsp){\n                  console.log(\"Error Get DP Value: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_GetDatapointValue done\");}\n              });\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t};\n\t\n\t// This API function sets datapoint values to the BAOS device.\n\tthis.API_SetDatapointValue = function (strDatapoint, strFormat, strCommand, strLength, strValue1, strValue2, strValue3, strValue4, strValue5, strValue6)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\tvar strValue;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Value\n\n\t\t//strLength = ConvertLength(strLength);\t\t\t\t\t\t\t\t\t// Convert given length into integer value\n\t\t\n\t\tif((IsIpAddrValid(m_strIpAddr)) &&\n\t\t   (IsNumber(strDatapoint)) && (IsNumber(strLength)))\t\t\t\t\t// If we have a valid IP address and valid parameters\n\t\t{\n\t\t\tswitch(strFormat)\t\t\t\t\t\t\t\t\t\t\t\t\t// Switch due to format\n\t\t\t{\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\t// Formats with 1 value parameter:\t\t//\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\tcase \"RAW\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format raw\n\t\t\t\tcase \"DPT1\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 1\n\t\t\t\tcase \"DPT4\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 4\n\t\t\t\tcase \"DPT5\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 5\n\t\t\t\tcase \"DPT6\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 6\n\t\t\t\tcase \"DPT7\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 7\n\t\t\t\tcase \"DPT8\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 8\n\t\t\t\tcase \"DPT9\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 9\n\t\t\t\tcase \"DPT12\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 12\n\t\t\t\tcase \"DPT13\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 13\n\t\t\t\tcase \"DPT14\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 14\n\t\t\t\tcase \"DPT16\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 16\n\t\t\t\t\tstrValue = \"&Value=\" + strValue1;\t\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"DPT17\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 17\n\t\t\t\t\tstrValue = \"&Scene=\" + strValue1;\t\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\t// Formats with 2 value parameters:\t\t//\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\tcase \"DPT2\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 2\n\t\t\t\t\tstrValue = \"&Control=\" + strValue1 +\n\t\t\t\t\t\t\t   \"&Value=\" + strValue2;\t\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase \"DPT3\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 3\n\t\t\t\t\tstrValue = \"&Control=\" + strValue1 +\n\t\t\t\t\t\t\t   \"&StepCode=\" + strValue2;\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\t\n\t\t\t\tcase \"DPT18\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 18\n\t\t\t\t\tstrValue = \"&Control=\" + strValue1 +\n\t\t\t\t\t\t\t   \"&Scene=\" + strValue2;\t\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\t// Formats with 3 value parameters:\t\t//\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\tcase \"DPT11\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 11\n\t\t\t\t\tstrValue = \"&Day=\" + strValue1 +\n\t\t\t\t\t\t\t   \"&Month=\" + strValue2 +\n\t\t\t\t\t\t\t   \"&Year=\" + strValue3;\t\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\t// Formats with 4 value parameters:\t\t//\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\tcase \"DPT10\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 10\n\t\t\t\t\tstrValue = \"&Weekday=\" + strValue1 +\n\t\t\t\t\t\t\t   \"&Hour=\" + strValue2 +\n\t\t\t\t\t\t\t   \"&Minute=\" + strValue3 +\n\t\t\t\t\t\t\t   \"&Second=\" + strValue4;\t\t\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\t// Formats with 6 value parameters:\t\t//\n\t\t\t\t//////////////////////////////////////////\n\t\t\t\tcase \"DPT15\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 15\n\t\t\t\t\tstrValue = \"&Code=\" + strValue1 +\n\t\t\t\t\t\t\t   \"&Index=\" + strValue2 +\n\t\t\t\t\t\t\t   \"&FlagError=\" + strValue3 +\n\t\t\t\t\t\t\t   \"&FlagPermission=\" + strValue4 +\n\t\t\t\t\t\t\t   \"&FlagReadDirection=\" + strValue5 +\n\t\t\t\t\t\t\t   \"&FlagEncrypted=\" + strValue6;\t\t\t\t\t// Assemble value\n\t\t\t\t\tbreak;\n\t\t\t\t\n\t\t\t\t// Not yet suopported by BAOS 771:\n\t\t\t\tcase \"DPT19\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 19\n\t\t\t\tcase \"DPT20\":\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: Format DPT 20\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/SetDatapointValue?Datapoint=\" + strDatapoint +\n\t\t\t\t\t \"&Format=\" + strFormat + \"&Command=\" + strCommand +\n\t\t\t\t\t \"&Length=\" + strLength + strValue;\n\t\t\n\t\t\tconsole.log(\"Anfrage: \" + strUrl);\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  OnObjSrvRespRcvd(rsp.data);\n                },\n                error: function(rsp){\n                  console.log(\"Error Set DP Value: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_SetDatapointValue done\");}\n              });\n\t\t\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t};\n\t\n\t// This API function gets parameter bytes (set by the ETS parameter\n\t// dialogue) from the BAOS device.\n\tthis.API_GetParamByte = function (strByteStart, strByteCount)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif((IsIpAddrValid(m_strIpAddr)) &&\n\t\t   (IsNumber(strByteStart)) && (IsNumber(strByteCount)))\t\t\t\t// If we have a valid IP address and valid parameters\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/GetParameterByte?ByteStart=\" + strByteStart +\n\t\t\t\t\t \"&ByteCount=\" + strByteCount;\t\t\t\t\t\t\t\t// Prepare URL for GetParamByte\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  OnObjSrvRespRcvd(rsp.data);\n                },\n                error: function(rsp){\n                  console.log(\"Error get param byte: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_GetParamByte done\");}\n              });\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t};\n\t\n\t// This API function checks the validity of a IP address.\n\tthis.API_IsIpAddrValid = function (strIpAddrToValidate)\n\t{\n\t\treturn IsIpAddrValid(strIpAddrToValidate);\n\t};\n\t\n\t// This API function starts the indication listener.\n\tthis.API_StartIndicationListener = function (strFormat)\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tm_IndFormat = strFormat;\t\t\t\t\t\t\t\t\t\t\t\t// Set format used for indications\n\n\t\tif(m_IndicationSession != 0)\t\t\t\t\t\t\t\t\t\t\t// If we already have an indication session\n\t\t{\n\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t}\n\n\t\tif(IsIpAddrValid(m_strIpAddr))\t\t\t\t\t\t\t\t\t\t// If we have a valid IP address\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/StartIndicationSession\";\t\t\t\t\t\t\t// Prepare URL for StartIndicationSession\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  if((rsp.data.Result == true) &&\n\t\t\t\t\t   (rsp.data.Service == \"StartIndicationSession\"))\t\t\t// If indication session could be started\n\t\t\t\t\t{\n\t\t\t\t\t\tm_IndicationSession = rsp.data.Data.SessionId;\t\t\t// Save indication session ID\n\t\t\t\t\t\tGetIndication();\t\t\t\t\t\t\t\t\t\t// Start getting indications\n\t\t\t\t\t}\n                },\n                error: function(rsp){\n                  console.log(\"Error starting indication listener: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_StartIndicationListener done\");}\n              });\n\t\t\t\n\t\t\treturn true;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return success\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t\t\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t};\n\t\n\t// This API function stops the indication listener.\n\tthis.API_StopIndicationListener = function ()\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif(m_IndicationSession == 0)\t\t\t\t\t\t\t\t\t\t\t// If no indication session is available\n\t\t{\n\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t}\n\t\t\n\t\tif(IsIpAddrValid(m_strIpAddr))\t\t\t\t\t\t\t\t\t\t// If we have a valid IP address\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/StopIndicationSession?SessionId=\" +\n\t\t\t\t\t m_IndicationSession;\t\t\t\t\t\t\t\t\t\t// Prepare URL for StopIndicationSession\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  if((rsp.data.Result == true) &&\n\t\t\t\t\t   (rsp.data.Service == \"StopIndicationSession\"))\t\t\t\t// If indication session could be stopped\n\t\t\t\t\t{\n\t\t\t\t\t\tm_IndicationSession = 0;\t\t\t\t\t\t\t\t// Delete indication session\n\t\t\t\t\t}\n                },\n                error: function(rsp){\n                  console.log(\"Error stop indication listener: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"API_StopIndicationListener done\");}\n              });\n\t\t\t\n\t\t\treturn true;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return success\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t\t\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t};\n\t\n\t\n\t//////////////////////////////////////////////////\n\t// Private functions\t\t\t\t\t\t\t//\n\t//////////////////////////////////////////////////\n\t\n\t// This private function checks the validity of a IP address.\n\tfunction IsIpAddrValid(strIpAddrToValidate)\n\t{\n\t\tvar strIpAddrSub = new Array();\t\t\t\t\t\t\t\t\t\t\t// Array used for IP address\n\t\tstrIpAddrSub = strIpAddrToValidate.split(\".\");\t\t\t\t\t\t\t// Split IP address into sub parts\n\t\t\n\t\tif(strIpAddrSub.length != 4)\t\t\t\t\t\t\t\t\t\t\t// If IP address has not 4 sub parts\n\t\t{\n\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t}\n\t\t\n\t\tfor (nIndex = 0; nIndex <strIpAddrSub.length; nIndex++)\t\t\t\t// Loop to handle every IP address sub part\n\t\t{\n\t\t\tif(!IsNumber(strIpAddrSub[nIndex]))\t\t\t\t\t\t\t\t\t// If it is not a number\n\t\t\t{\n\t\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t\t}\n\t\t\t\n\t\t\tvar sub = parseInt(strIpAddrSub[nIndex], 10);\t\t\t\t\t\t// Convert to integer\n\t\t\tif ((isNaN(sub)) || (sub <0) || (sub >255))\t\t\t\t\t\t\t// If it is out of range\n\t\t\t{\n\t\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn true;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return success\n\t}\n\t\n\t// This private function checks, if a string contains only numbers.\n\tfunction IsNumber(strToValidate)\n\t{\n\t\tfor(position=0; position<strToValidate.length; position++)\t\t\t// Loop to handle every position in string\n\t\t{\n\t\t\tvar chr = strToValidate.charAt(position);\t\t\t\t\t\t\t// Get character\n\t\t\t\n\t\t\tif((chr < \"0\") || (chr > \"9\"))\t\t\t\t\t\t\t\t\t\t// If character is not a number\n\t\t\t{\n\t\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Character is not a number\n\t\t\t}\n\t\t}\n\t\t\n\t\treturn true;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Character is a number\n\t}\n\t\n\t// This private function does a length conversion.\n\tfunction ConvertLength(strLength)\n\t{\n\t\tswitch(strLength)\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Switch due to length\n\t\t{\n\t\t\tcase \"1 Bit\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 1 bit\n\t\t\tcase \"2 Bit\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 2 bit\n\t\t\tcase \"4 Bit\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 4 bit\n\t\t\tcase \"1 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 1 byte\n\t\t\t\treturn 1;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 1 byte\n\t\t\t\n\t\t\tcase \"2 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 2 byte\n\t\t\t\treturn 2;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 2 byte\n\t\t\t\t\n\t\t\tcase \"3 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 3 byte\n\t\t\t\treturn 3;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 3 byte\n\t\t\t\t\n\t\t\tcase \"4 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 4 byte\n\t\t\t\treturn 4;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 4 byte\n\t\t\t\t\n\t\t\tcase \"6 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 6 byte\n\t\t\t\treturn 6;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 6 byte\n\t\t\t\t\n\t\t\tcase \"8 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 8 byte\n\t\t\t\treturn 8;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 8 byte\n\t\t\t\t\n\t\t\tcase \"14 Byte\":\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Case: 14 byte\n\t\t\t\treturn 14;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return: Length 14 byte\n\t\t\t\n\t\t\tdefault:\n\t\t\t\treturn 0;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t}\n\t}\n\t\n\t// This private function creates and evaluates a \"get indication\" for the BAOS.\n\tfunction GetIndication()\n\t{\n\t\tvar strUrl;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// URL\n\t\t\n\t\tif(m_IndicationSession == 0)\t\t\t\t\t\t\t\t\t\t\t// If no indication session is available\n\t\t{\n\t\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t\t}\n\t\t\n\t\tif(IsIpAddrValid(m_strIpAddr))\t\t\t\t\t\t\t\t\t\t// If we have a valid IP address\n\t\t{\n\t\t\tstrUrl = \"http://\" + m_strIpAddr +\n\t\t\t\t\t \"/baos/GetIndication?SessionId=\" +\n\t\t\t\t\t m_IndicationSession + \"&Timeout=20\" +\n\t\t\t\t\t \"&Format=\" + m_IndFormat;\t\t\t\t\t\t\t\t\t// Prepare URL for GetIndication\n\t\t\t\n\t\t\thttp.request ({\n                url: strUrl,\n                method: \"GET\",\n                async: true,\n                success: function(rsp){\n                  if(rsp.data.Result == false)\t\t\t\t\t\t\t\t\t// If we got an error\n\t\t\t\t\t{\n\t\t\t\t\t\tif(rsp.data.Error == \"IndTimeout\")\t\t\t\t\t\t// If we have a timeout\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif(m_IndicationSession != 0)\t\t\t\t\t\t// If indication session is valid\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tGetIndication();\t\t\t\t\t\t\t\t// Try to get new indication\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif(rsp.data.Service == \"GetIndication\")\t\t\t\t\t\t// If we have a GetIndication response\n\t\t\t\t\t{\n\t\t\t\t\t\tif(rsp.data.Result == true)\t\t\t\t\t\t\t\t// If we got an indication\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tOnIndicationUpdate(rsp.data);\t\t\t\t\t\t// Indication update\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif(m_IndicationSession != 0)\t\t\t\t\t\t// If indication session is valid\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tGetIndication();\t\t\t\t\t\t\t\t// Try to get new indication\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n                },\n                error: function(rsp){\n                  console.log(\"Error get indication: \" + JSON.stringify(rsp, null, 4));\n                  OnObjSrvError(rsp.data);\n                },\n                complete: function(rsp){console.log(\"GetIndication done\");}\n              });\n\t\t\t\n\t\t\treturn true;\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return success\n\t\t}\n\t\telse\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Else: We have invalid settings\n\t\t{\n\t\t\tOnObjSrvInvalidSettings();\t\t\t\t\t\t\t\t\t\t\t// Call error handler (invalid settings)\n\t\t}\n\t\t\n\t\treturn false;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// Return error\n\t}\n\t\n\t// This private function calls the response handler, if available.\n\tfunction OnObjSrvRespRcvd(dataObjSrvResp)\n\t{\n\t\tif(m_bEnableCallbackRespRcvd == true)\t\t\t\t\t\t\t\t\t// If callback is enabled\n\t\t{\n\t\t\tm_CallbackRespRcvd(dataObjSrvResp);\t\t\t\t\t\t\t\t\t// Call callback function\n\t\t}\n\t}\n\t\n\t// This private function calls the indication handler, if available.\n\tfunction OnIndicationUpdate(dataIndUpdate)\n\t{\n\t\tif(m_bEnableCallbackIndicationUpdate == true)\t\t\t\t\t\t\t// If callback is enabled\n\t\t{\n\t\t\tm_CallbackIndicationUpdate(dataIndUpdate);\t\t\t\t\t\t\t// Call callback function\n\t\t}\n\t}\n\t\n\t// This private function calls the handler for invalid settings,\n\t// if available.\n\tfunction OnObjSrvInvalidSettings()\n\t{\n\t\tif(m_bEnableCallbackInvalidSettings == true)\t\t\t\t\t\t\t// If callback is enabled\n\t\t{\n\t\t\tm_CallbackInvalidSettings();\t\t\t\t\t\t\t\t\t\t// Call callback function\n\t\t}\n\t}\n\t\n\t// This private function calls the handler for errors, if available.\n\tfunction OnObjSrvError(rsp)\n\t{\n\t\tif(m_bEnableCallbackTransmitError == true)\t\t\t\t\t\t\t\t// If callback is enabled\n\t\t{\n\t\t\tm_CallbackTransmitError(rsp);\t\t\t\t\t\t\t\t\t\t// Call callback function\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "lib/IntelHex2bin.js",
    "content": "// Converts IntelHex into binary 128 kB file\nfunction IntelHex2bin(hex) {\n\tfunction hex2dec(digits) {\n\t\treturn parseInt(digits, 16);\n\t}\n\n\tvar BIN_SIZE = 128*1024;\n\n\tvar DATA = 0,\n\t\tEND_OF_FILE = 1,\n\t\tEXT_SEGMENT_ADDR = 2,\n\t\tSTART_SEGMENT_ADDR = 3,\n\t\tEXT_LINEAR_ADDR = 4,\n\t\tSTART_LINEAR_ADDR = 5;\n\n\tvar EMPTY_VALUE = 0xFF;\n\n\tvar LINE_MIN_LENGTH = 11;\n\t\t\n\tvar hexLines = hex.split(\"\\n\");\n\t\n\tvar bin = new Uint8Array(BIN_SIZE);\n\t\n\t// Init binary array\n\tfor (var i = 0; i < BIN_SIZE; i++) {\n\t\tbin[i] = EMPTY_VALUE;\n\t}\n\t\n\t// Start processing\n\tvar bankOffset = 0, maxOffset = 0;\n\tvar end = false;\n\tfor (var i = 0; i < hexLines.length && !end; i++) {\n\t\tvar line = hexLines[i];\n\t\t\n\t\tline = line.replace(/\\r/g, \"\");\n\t\t\n\t\tif (line.length < LINE_MIN_LENGTH) throw(\"Hex file contains too short line \" + i + \" - \" + line);\n\t\tif (line.substr(0, 1) !== \":\") throw(\"Line \" + i + \" should start with : - \" + line);\n\n\t\tvar dataLength = hex2dec(line.substr(1, 2));\n\t\tif (dataLength > 32) throw(\"Data length should not exceed 32 bytes (line \" + i + \") - \" + line);\n\t\tif (line.length !== LINE_MIN_LENGTH + dataLength * 2) throw(\"Data length do not match line length: \" + i + \" - \" + line);\n\t\t\n\t\tvar crc = 0;\n\t\tfor (var n = 0; n < 1 + 2 + 1 + dataLength + 1; n++) {\n\t\t\tcrc += hex2dec(line.substr(1 + n * 2, 2));\n\t\t}\n\t\tcrc &= 0xff;\n\t\tif (crc !== 0) throw(\"CRC do not match in line \" + i + \" - \" + line);\n\t\t\n\t\tvar offset = hex2dec(line.substr(3, 4));\n\t\tvar recType = hex2dec(line.substr(7, 2));\n\t\t\n\t\tswitch (recType) {\n\t\t\tcase DATA:\n\t\t\t\tfor (var j = 0; j < dataLength; j++) {\n\t\t\t\t\tif (bankOffset + offset + j > BIN_SIZE) throw(\"Address \" + (bankOffset + offset + j) + \" is beyond \" + BIN_SIZE + \" - line \" + i + \" - \" + line);\n\t\t\t\t\tbin[bankOffset + offset + j] = hex2dec(line.substr(LINE_MIN_LENGTH - 2 + 2*j, 2));\n\t\t\t\t\tif (maxOffset < bankOffset + offset + j) {\n\t\t\t\t\t\tmaxOffset = bankOffset + offset + j;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase END_OF_FILE:\n\t\t\t\tend = true;\n\t\t\t\tbreak;\n\t\t\tcase EXT_LINEAR_ADDR:\n\t\t\t\tbankOffset = hex2dec(line.substr(LINE_MIN_LENGTH - 2, 4))*256*256;\n\t\t\t\tbreak;\n\t\t}\n\t}\n\t\n\tvar bin_size = maxOffset + 1; // last addr + 1\n\tvar bin_sliced = new Uint8Array(bin_size);\n\t\n\tfor (var k = 0; k < bin_size; k++) {\n\t\tbin_sliced[k] = bin[k];\n\t}\n\t\n\treturn bin_sliced;\n}\n"
  },
  {
    "path": "lib/LimitedArray.js",
    "content": "/*\n * This class creates an object that can be called to save data stored in object using a saver function.\n * The object will be saved only periodically and will be stripped to a limit and filtered using filter function.\n * Object can grow in memory not bigger than to limit + period - then it will be stripped and saved.\n */\nfunction LimitedArray(initial, saver, period, limit, filter) {\n\tthis.object = Array.isArray(initial) ? initial :  [];\n\tthis.saver = saver;   // function\n\tthis.period = period; // integer\n\tthis.limit = limit;   // integer\n\tthis.filter = filter; // function\n\n\tthis.counter = this.period;\n}\n\nLimitedArray.prototype.save = function(force) {\n\tif (force) this.counter = 1;\n\t\n\tif (this.counter-- === 0) {\n\t\tthis.counter = this.period;\n\t\t\n\t\t// first filter the object\n\t\tif (this.filter) {\n\t\t\tthis.object = this.object.filter(this.filter);\n\t\t}\n\n\t\t// then limit the object size\n\t\tif (this.limit) {\n\t\t\tthis.object = this.object.slice(-this.limit);\n\t\t}\n\n\t\t// save the object\n\t\tthis.saver(this.object);\n\t}\n};\n\nLimitedArray.prototype.get = function() {\n\treturn this.object;\n};\n\nLimitedArray.prototype.set = function(value) {\n\tthis.object = value;\n\tthis.save();\n};\n\nLimitedArray.prototype.push = function(value) {\n\tthis.object.push(value);\n\tthis.save();\n};\n\nLimitedArray.prototype.clear = function() {\n        this.object = [];\n        this.save(true); // force save\n};\n\nLimitedArray.prototype.finalize = function() {\n\tthis.save(true); // force save\n\t\n\t// release\n\tthis.saver = null;\n\tthis.filter = null;\n};\n"
  },
  {
    "path": "lib/base64.js",
    "content": "// Public domain version of Base64 encoder/decoder found somewhere in the Internet\n\nvar Base64 = {\n    _keyStr:\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\",\n    encode:function(e){var t=\"\";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},\n    decode:function(e){var t=\"\";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\\+\\/\\=]/g,\"\");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},\n    _utf8_encode:function(e){var t=\"\";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},\n    _utf8_decode:function(e){var t=\"\";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}\n};\n"
  },
  {
    "path": "lib/eventemitter2.js",
    "content": "/*! EventEmitter2 https://github.com/hij1nx/EventEmitter2 Copyright (c) 2013 hij1nx Licensed under the MIT license.*/\n;!function(undefined) {\n\n    var isArray = Array.isArray ? Array.isArray : function _isArray(obj) {\n        return Object.prototype.toString.call(obj) === \"[object Array]\";\n    };\n    var defaultMaxListeners = 10;\n\n    function init() {\n        this._events = {};\n        if (this._conf) {\n            configure.call(this, this._conf);\n        }\n    }\n\n    function configure(conf) {\n        if (conf) {\n\n            this._conf = conf;\n\n            conf.delimiter && (this.delimiter = conf.delimiter);\n            conf.maxListeners && (this._events.maxListeners = conf.maxListeners);\n            conf.wildcard && (this.wildcard = conf.wildcard);\n            conf.newListener && (this.newListener = conf.newListener);\n\n            if (this.wildcard) {\n                this.listenerTree = {};\n            }\n        }\n    }\n\n    function EventEmitter(conf) {\n        this._events = {};\n        this.newListener = false;\n        configure.call(this, conf);\n    }\n\n    //\n    // Attention, function return type now is array, always !\n    // It has zero elements if no any matches found and one or more\n    // elements (leafs) if there are matches\n    //\n    function searchListenerTree(handlers, type, tree, i) {\n        if (!tree) {\n            return [];\n        }\n        var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached,\n            typeLength = type.length, currentType = type[i], nextType = type[i+1];\n        if (i === typeLength && tree._listeners) {\n            //\n            // If at the end of the event(s) list and the tree has listeners\n            // invoke those listeners.\n            //\n            if (typeof tree._listeners === 'function') {\n                handlers && handlers.push(tree._listeners);\n                return [tree];\n            } else {\n                for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) {\n                    handlers && handlers.push(tree._listeners[leaf]);\n                }\n                return [tree];\n            }\n        }\n\n        if ((currentType === '*' || currentType === '**') || tree[currentType]) {\n            //\n            // If the event emitted is '*' at this part\n            // or there is a concrete match at this patch\n            //\n            if (currentType === '*') {\n                for (branch in tree) {\n                    if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {\n                        listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1));\n                    }\n                }\n                return listeners;\n            } else if(currentType === '**') {\n                endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*'));\n                if(endReached && tree._listeners) {\n                    // The next element has a _listeners, add it to the handlers.\n                    listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength));\n                }\n\n                for (branch in tree) {\n                    if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {\n                        if(branch === '*' || branch === '**') {\n                            if(tree[branch]._listeners && !endReached) {\n                                listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength));\n                            }\n                            listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));\n                        } else if(branch === nextType) {\n                            listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2));\n                        } else {\n                            // No match on this one, shift into the tree but not in the type array.\n                            listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));\n                        }\n                    }\n                }\n                return listeners;\n            }\n\n            listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1));\n        }\n\n        xTree = tree['*'];\n        if (xTree) {\n            //\n            // If the listener tree will allow any match for this part,\n            // then recursively explore all branches of the tree\n            //\n            searchListenerTree(handlers, type, xTree, i+1);\n        }\n\n        xxTree = tree['**'];\n        if(xxTree) {\n            if(i < typeLength) {\n                if(xxTree._listeners) {\n                    // If we have a listener on a '**', it will catch all, so add its handler.\n                    searchListenerTree(handlers, type, xxTree, typeLength);\n                }\n\n                // Build arrays of matching next branches and others.\n                for(branch in xxTree) {\n                    if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) {\n                        if(branch === nextType) {\n                            // We know the next element will match, so jump twice.\n                            searchListenerTree(handlers, type, xxTree[branch], i+2);\n                        } else if(branch === currentType) {\n                            // Current node matches, move into the tree.\n                            searchListenerTree(handlers, type, xxTree[branch], i+1);\n                        } else {\n                            isolatedBranch = {};\n                            isolatedBranch[branch] = xxTree[branch];\n                            searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1);\n                        }\n                    }\n                }\n            } else if(xxTree._listeners) {\n                // We have reached the end and still on a '**'\n                searchListenerTree(handlers, type, xxTree, typeLength);\n            } else if(xxTree['*'] && xxTree['*']._listeners) {\n                searchListenerTree(handlers, type, xxTree['*'], typeLength);\n            }\n        }\n\n        return listeners;\n    }\n\n    function growListenerTree(type, listener) {\n\n        type = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n\n        //\n        // Looks for two consecutive '**', if so, don't add the event at all.\n        //\n        for(var i = 0, len = type.length; i+1 < len; i++) {\n            if(type[i] === '**' && type[i+1] === '**') {\n                return;\n            }\n        }\n\n        var tree = this.listenerTree;\n        var name = type.shift();\n\n        while (name) {\n\n            if (!tree[name]) {\n                tree[name] = {};\n            }\n\n            tree = tree[name];\n\n            if (type.length === 0) {\n\n                if (!tree._listeners) {\n                    tree._listeners = listener;\n                }\n                else if(typeof tree._listeners === 'function') {\n                    tree._listeners = [tree._listeners, listener];\n                }\n                else if (isArray(tree._listeners)) {\n\n                    tree._listeners.push(listener);\n\n                    if (!tree._listeners.warned) {\n\n                        var m = defaultMaxListeners;\n\n                        if (typeof this._events.maxListeners !== 'undefined') {\n                            m = this._events.maxListeners;\n                        }\n\n                        if (m > 0 && tree._listeners.length > m) {\n\n                            tree._listeners.warned = true;\n                            console.error('(node) warning: possible EventEmitter memory ' +\n                                'leak detected. %d listeners added. ' +\n                                'Use emitter.setMaxListeners() to increase limit.',\n                                tree._listeners.length);\n                            console.trace();\n                        }\n                    }\n                }\n                return true;\n            }\n            name = type.shift();\n        }\n        return true;\n    }\n\n    // By default EventEmitters will print a warning if more than\n    // 10 listeners are added to it. This is a useful default which\n    // helps finding memory leaks.\n    //\n    // Obviously not all Emitters should be limited to 10. This function allows\n    // that to be increased. Set to zero for unlimited.\n\n    EventEmitter.prototype.delimiter = '.';\n\n    EventEmitter.prototype.setMaxListeners = function(n) {\n        this._events || init.call(this);\n        this._events.maxListeners = n;\n        if (!this._conf) this._conf = {};\n        this._conf.maxListeners = n;\n    };\n\n    EventEmitter.prototype.event = '';\n\n    EventEmitter.prototype.once = function(event, fn) {\n        this.many(event, 1, fn);\n        return this;\n    };\n\n    EventEmitter.prototype.many = function(event, ttl, fn) {\n        var self = this;\n\n        if (typeof fn !== 'function') {\n            throw new Error('many only accepts instances of Function');\n        }\n\n        function listener() {\n            if (--ttl === 0) {\n                self.off(event, listener);\n            }\n            fn.apply(this, arguments);\n        }\n\n        listener._origin = fn;\n\n        this.on(event, listener);\n\n        return self;\n    };\n\n    EventEmitter.prototype.emit = function() {\n\n        this._events || init.call(this);\n\n        var type = arguments[0];\n\n        if (type === 'newListener' && !this.newListener) {\n            if (!this._events.newListener) { return false; }\n        }\n\n        // Loop through the *_all* functions and invoke them.\n        if (this._all) {\n            var l = arguments.length;\n            var args = new Array(l - 1);\n            for (var i = 1; i < l; i++) args[i - 1] = arguments[i];\n            for (i = 0, l = this._all.length; i < l; i++) {\n                this.event = type;\n                this._all[i].apply(this, args);\n            }\n        }\n\n        // If there is no 'error' event listener then throw.\n        if (type === 'error') {\n\n            if (!this._all &&\n                !this._events.error &&\n                !(this.wildcard && this.listenerTree.error)) {\n\n                if (arguments[1] instanceof Error) {\n                    throw arguments[1]; // Unhandled 'error' event\n                } else {\n                    throw new Error(\"Uncaught, unspecified 'error' event.\");\n                }\n                return false;\n            }\n        }\n\n        var handler;\n\n        if(this.wildcard) {\n            handler = [];\n            var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n            searchListenerTree.call(this, handler, ns, this.listenerTree, 0);\n        }\n        else {\n            handler = this._events[type];\n        }\n\n        if (typeof handler === 'function') {\n            this.event = type;\n            if (arguments.length === 1) {\n                handler.call(this);\n            }\n            else if (arguments.length > 1)\n                switch (arguments.length) {\n                    case 2:\n                        handler.call(this, arguments[1]);\n                        break;\n                    case 3:\n                        handler.call(this, arguments[1], arguments[2]);\n                        break;\n                    // slower\n                    default:\n                        var l = arguments.length;\n                        var args = new Array(l - 1);\n                        for (var i = 1; i < l; i++) args[i - 1] = arguments[i];\n                        handler.apply(this, args);\n                }\n            return true;\n        }\n        else if (handler) {\n            var l = arguments.length;\n            var args = new Array(l - 1);\n            for (var i = 1; i < l; i++) args[i - 1] = arguments[i];\n\n            var listeners = handler.slice();\n            for (var i = 0, l = listeners.length; i < l; i++) {\n                this.event = type;\n                listeners[i].apply(this, args);\n            }\n            return (listeners.length > 0) || !!this._all;\n        }\n        else {\n            return !!this._all;\n        }\n\n    };\n\n    EventEmitter.prototype.on = function(type, listener) {\n\n        if (typeof type === 'function') {\n            this.onAny(type);\n            return this;\n        }\n\n        if (typeof listener !== 'function') {\n            throw new Error('on only accepts instances of Function');\n        }\n        this._events || init.call(this);\n\n        // To avoid recursion in the case that type == \"newListeners\"! Before\n        // adding it to the listeners, first emit \"newListeners\".\n        this.emit('newListener', type, listener);\n\n        if(this.wildcard) {\n            growListenerTree.call(this, type, listener);\n            return this;\n        }\n\n        if (!this._events[type]) {\n            // Optimize the case of one listener. Don't need the extra array object.\n            this._events[type] = listener;\n        }\n        else if(typeof this._events[type] === 'function') {\n            // Adding the second element, need to change to array.\n            this._events[type] = [this._events[type], listener];\n        }\n        else if (isArray(this._events[type])) {\n            // If we've already got an array, just append.\n            this._events[type].push(listener);\n\n            // Check for listener leak\n            if (!this._events[type].warned) {\n\n                var m = defaultMaxListeners;\n\n                if (typeof this._events.maxListeners !== 'undefined') {\n                    m = this._events.maxListeners;\n                }\n\n                if (m > 0 && this._events[type].length > m) {\n\n                    this._events[type].warned = true;\n                    console.error('(node) warning: possible EventEmitter memory ' +\n                        'leak detected. %d listeners added. ' +\n                        'Use emitter.setMaxListeners() to increase limit.',\n                        this._events[type].length);\n                    console.trace();\n                }\n            }\n        }\n        return this;\n    };\n\n    EventEmitter.prototype.onAny = function(fn) {\n\n        if (typeof fn !== 'function') {\n            throw new Error('onAny only accepts instances of Function');\n        }\n\n        if(!this._all) {\n            this._all = [];\n        }\n\n        // Add the function to the event listener collection.\n        this._all.push(fn);\n        return this;\n    };\n\n    EventEmitter.prototype.addListener = EventEmitter.prototype.on;\n\n    EventEmitter.prototype.off = function(type, listener) {\n\n        if (typeof listener !== 'function') {\n            throw new Error('removeListener only takes instances of Function');\n        }\n\n        var handlers,leafs=[];\n\n        if(this.wildcard) {\n            var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n            leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);\n        }\n        else {\n            // does not use listeners(), so no side effect of creating _events[type]\n            if (!this._events[type]) return this;\n            handlers = this._events[type];\n            leafs.push({_listeners:handlers});\n        }\n\n        for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {\n            var leaf = leafs[iLeaf];\n            handlers = leaf._listeners;\n            if (isArray(handlers)) {\n\n                var position = -1;\n\n                for (var i = 0, length = handlers.length; i < length; i++) {\n                    if (handlers[i] === listener ||\n                        (handlers[i].listener && handlers[i].listener === listener) ||\n                        (handlers[i]._origin && handlers[i]._origin === listener)) {\n                        position = i;\n                        break;\n                    }\n                }\n\n                if (position < 0) {\n                    continue;\n                }\n\n                if(this.wildcard) {\n                    leaf._listeners.splice(position, 1);\n                }\n                else {\n                    this._events[type].splice(position, 1);\n                }\n\n                if (handlers.length === 0) {\n                    if(this.wildcard) {\n                        delete leaf._listeners;\n                    }\n                    else {\n                        delete this._events[type];\n                    }\n                }\n                return this;\n            }\n            else if (handlers === listener ||\n                (handlers.listener && handlers.listener === listener) ||\n                (handlers._origin && handlers._origin === listener)) {\n                if(this.wildcard) {\n                    delete leaf._listeners;\n                }\n                else {\n                    delete this._events[type];\n                }\n            }\n        }\n\n        function recursivelyGarbageCollect(root) {\n            if (root === undefined) {\n                return;\n            }\n            var keys = Object.keys(root);\n            for (var i in keys) {\n                var key = keys[i];\n                var obj = root[key];\n                if (obj instanceof Function)\n                    continue;\n                if (Object.keys(obj).length > 0) {\n                    recursivelyGarbageCollect(root[key]);\n                }\n                if (Object.keys(obj).length === 0) {\n                    delete root[key];\n                }\n            }\n        }\n        recursivelyGarbageCollect(this.listenerTree);\n        return this;\n    };\n\n    EventEmitter.prototype.offAny = function(fn) {\n        var i = 0, l = 0, fns;\n        if (fn && this._all && this._all.length > 0) {\n            fns = this._all;\n            for(i = 0, l = fns.length; i < l; i++) {\n                if(fn === fns[i]) {\n                    fns.splice(i, 1);\n                    return this;\n                }\n            }\n        } else {\n            this._all = [];\n        }\n        return this;\n    };\n\n    EventEmitter.prototype.removeListener = EventEmitter.prototype.off;\n\n    EventEmitter.prototype.removeAllListeners = function(type) {\n        if (arguments.length === 0) {\n            !this._events || init.call(this);\n            return this;\n        }\n\n        if(this.wildcard) {\n            var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n            var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);\n\n            for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {\n                var leaf = leafs[iLeaf];\n                leaf._listeners = null;\n            }\n        }\n        else {\n            if (!this._events[type]) return this;\n            this._events[type] = null;\n        }\n        return this;\n    };\n\n    EventEmitter.prototype.listeners = function(type) {\n        if(this.wildcard) {\n            var handlers = [];\n            var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();\n            searchListenerTree.call(this, handlers, ns, this.listenerTree, 0);\n            return handlers;\n        }\n\n        this._events || init.call(this);\n\n        if (!this._events[type]) this._events[type] = [];\n        if (!isArray(this._events[type])) {\n            this._events[type] = [this._events[type]];\n        }\n        return this._events[type];\n    };\n\n    EventEmitter.prototype.listenersAny = function() {\n\n        if(this._all) {\n            return this._all;\n        }\n        else {\n            return [];\n        }\n\n    };\n\n    if (typeof define === 'function' && define.amd) {\n        // AMD. Register as an anonymous module.\n        define(function() {\n            return EventEmitter;\n        });\n    } else if (typeof exports === 'object') {\n        // CommonJS\n        exports.EventEmitter2 = EventEmitter;\n    }\n    else {\n        // Browser global.\n        window.EventEmitter2 = EventEmitter;\n    }\n}();"
  },
  {
    "path": "lib/underscore-umd-min.js",
    "content": "!function(n,r){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=r():\"function\"==typeof define&&define.amd?define(\"underscore\",r):(n=\"undefined\"!=typeof globalThis?globalThis:n||self,function(){var t=n._,e=n._=r();e.noConflict=function(){return n._=t,e}}())}(this,(function(){\n//     Underscore.js 1.13.6\n//     https://underscorejs.org\n//     (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors\n//     Underscore may be freely distributed under the MIT license.\nvar n=\"1.13.6\",r=\"object\"==typeof self&&self.self===self&&self||\"object\"==typeof global&&global.global===global&&global||Function(\"return this\")()||{},t=Array.prototype,e=Object.prototype,u=\"undefined\"!=typeof Symbol?Symbol.prototype:null,o=t.push,i=t.slice,a=e.toString,f=e.hasOwnProperty,c=\"undefined\"!=typeof ArrayBuffer,l=\"undefined\"!=typeof DataView,s=Array.isArray,p=Object.keys,v=Object.create,h=c&&ArrayBuffer.isView,y=isNaN,d=isFinite,g=!{toString:null}.propertyIsEnumerable(\"toString\"),b=[\"valueOf\",\"isPrototypeOf\",\"toString\",\"propertyIsEnumerable\",\"hasOwnProperty\",\"toLocaleString\"],m=Math.pow(2,53)-1;function j(n,r){return r=null==r?n.length-1:+r,function(){for(var t=Math.max(arguments.length-r,0),e=Array(t),u=0;u<t;u++)e[u]=arguments[u+r];switch(r){case 0:return n.call(this,e);case 1:return n.call(this,arguments[0],e);case 2:return n.call(this,arguments[0],arguments[1],e)}var o=Array(r+1);for(u=0;u<r;u++)o[u]=arguments[u];return o[r]=e,n.apply(this,o)}}function _(n){var r=typeof n;return\"function\"===r||\"object\"===r&&!!n}function w(n){return void 0===n}function A(n){return!0===n||!1===n||\"[object Boolean]\"===a.call(n)}function x(n){var r=\"[object \"+n+\"]\";return function(n){return a.call(n)===r}}var S=x(\"String\"),O=x(\"Number\"),M=x(\"Date\"),E=x(\"RegExp\"),B=x(\"Error\"),N=x(\"Symbol\"),I=x(\"ArrayBuffer\"),T=x(\"Function\"),k=r.document&&r.document.childNodes;\"function\"!=typeof/./&&\"object\"!=typeof Int8Array&&\"function\"!=typeof k&&(T=function(n){return\"function\"==typeof n||!1});var D=T,R=x(\"Object\"),F=l&&R(new DataView(new ArrayBuffer(8))),V=\"undefined\"!=typeof Map&&R(new Map),P=x(\"DataView\");var q=F?function(n){return null!=n&&D(n.getInt8)&&I(n.buffer)}:P,U=s||x(\"Array\");function W(n,r){return null!=n&&f.call(n,r)}var z=x(\"Arguments\");!function(){z(arguments)||(z=function(n){return W(n,\"callee\")})}();var L=z;function $(n){return O(n)&&y(n)}function C(n){return function(){return n}}function K(n){return function(r){var t=n(r);return\"number\"==typeof t&&t>=0&&t<=m}}function J(n){return function(r){return null==r?void 0:r[n]}}var G=J(\"byteLength\"),H=K(G),Q=/\\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\\]/;var X=c?function(n){return h?h(n)&&!q(n):H(n)&&Q.test(a.call(n))}:C(!1),Y=J(\"length\");function Z(n,r){r=function(n){for(var r={},t=n.length,e=0;e<t;++e)r[n[e]]=!0;return{contains:function(n){return!0===r[n]},push:function(t){return r[t]=!0,n.push(t)}}}(r);var t=b.length,u=n.constructor,o=D(u)&&u.prototype||e,i=\"constructor\";for(W(n,i)&&!r.contains(i)&&r.push(i);t--;)(i=b[t])in n&&n[i]!==o[i]&&!r.contains(i)&&r.push(i)}function nn(n){if(!_(n))return[];if(p)return p(n);var r=[];for(var t in n)W(n,t)&&r.push(t);return g&&Z(n,r),r}function rn(n,r){var t=nn(r),e=t.length;if(null==n)return!e;for(var u=Object(n),o=0;o<e;o++){var i=t[o];if(r[i]!==u[i]||!(i in u))return!1}return!0}function tn(n){return n instanceof tn?n:this instanceof tn?void(this._wrapped=n):new tn(n)}function en(n){return new Uint8Array(n.buffer||n,n.byteOffset||0,G(n))}tn.VERSION=n,tn.prototype.value=function(){return this._wrapped},tn.prototype.valueOf=tn.prototype.toJSON=tn.prototype.value,tn.prototype.toString=function(){return String(this._wrapped)};var un=\"[object DataView]\";function on(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(null==n||null==r)return!1;if(n!=n)return r!=r;var o=typeof n;return(\"function\"===o||\"object\"===o||\"object\"==typeof r)&&function n(r,t,e,o){r instanceof tn&&(r=r._wrapped);t instanceof tn&&(t=t._wrapped);var i=a.call(r);if(i!==a.call(t))return!1;if(F&&\"[object Object]\"==i&&q(r)){if(!q(t))return!1;i=un}switch(i){case\"[object RegExp]\":case\"[object String]\":return\"\"+r==\"\"+t;case\"[object Number]\":return+r!=+r?+t!=+t:0==+r?1/+r==1/t:+r==+t;case\"[object Date]\":case\"[object Boolean]\":return+r==+t;case\"[object Symbol]\":return u.valueOf.call(r)===u.valueOf.call(t);case\"[object ArrayBuffer]\":case un:return n(en(r),en(t),e,o)}var f=\"[object Array]\"===i;if(!f&&X(r)){if(G(r)!==G(t))return!1;if(r.buffer===t.buffer&&r.byteOffset===t.byteOffset)return!0;f=!0}if(!f){if(\"object\"!=typeof r||\"object\"!=typeof t)return!1;var c=r.constructor,l=t.constructor;if(c!==l&&!(D(c)&&c instanceof c&&D(l)&&l instanceof l)&&\"constructor\"in r&&\"constructor\"in t)return!1}o=o||[];var s=(e=e||[]).length;for(;s--;)if(e[s]===r)return o[s]===t;if(e.push(r),o.push(t),f){if((s=r.length)!==t.length)return!1;for(;s--;)if(!on(r[s],t[s],e,o))return!1}else{var p,v=nn(r);if(s=v.length,nn(t).length!==s)return!1;for(;s--;)if(p=v[s],!W(t,p)||!on(r[p],t[p],e,o))return!1}return e.pop(),o.pop(),!0}(n,r,t,e)}function an(n){if(!_(n))return[];var r=[];for(var t in n)r.push(t);return g&&Z(n,r),r}function fn(n){var r=Y(n);return function(t){if(null==t)return!1;var e=an(t);if(Y(e))return!1;for(var u=0;u<r;u++)if(!D(t[n[u]]))return!1;return n!==hn||!D(t[cn])}}var cn=\"forEach\",ln=\"has\",sn=[\"clear\",\"delete\"],pn=[\"get\",ln,\"set\"],vn=sn.concat(cn,pn),hn=sn.concat(pn),yn=[\"add\"].concat(sn,cn,ln),dn=V?fn(vn):x(\"Map\"),gn=V?fn(hn):x(\"WeakMap\"),bn=V?fn(yn):x(\"Set\"),mn=x(\"WeakSet\");function jn(n){for(var r=nn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=n[r[u]];return e}function _n(n){for(var r={},t=nn(n),e=0,u=t.length;e<u;e++)r[n[t[e]]]=t[e];return r}function wn(n){var r=[];for(var t in n)D(n[t])&&r.push(t);return r.sort()}function An(n,r){return function(t){var e=arguments.length;if(r&&(t=Object(t)),e<2||null==t)return t;for(var u=1;u<e;u++)for(var o=arguments[u],i=n(o),a=i.length,f=0;f<a;f++){var c=i[f];r&&void 0!==t[c]||(t[c]=o[c])}return t}}var xn=An(an),Sn=An(nn),On=An(an,!0);function Mn(n){if(!_(n))return{};if(v)return v(n);var r=function(){};r.prototype=n;var t=new r;return r.prototype=null,t}function En(n){return U(n)?n:[n]}function Bn(n){return tn.toPath(n)}function Nn(n,r){for(var t=r.length,e=0;e<t;e++){if(null==n)return;n=n[r[e]]}return t?n:void 0}function In(n,r,t){var e=Nn(n,Bn(r));return w(e)?t:e}function Tn(n){return n}function kn(n){return n=Sn({},n),function(r){return rn(r,n)}}function Dn(n){return n=Bn(n),function(r){return Nn(r,n)}}function Rn(n,r,t){if(void 0===r)return n;switch(null==t?3:t){case 1:return function(t){return n.call(r,t)};case 3:return function(t,e,u){return n.call(r,t,e,u)};case 4:return function(t,e,u,o){return n.call(r,t,e,u,o)}}return function(){return n.apply(r,arguments)}}function Fn(n,r,t){return null==n?Tn:D(n)?Rn(n,r,t):_(n)&&!U(n)?kn(n):Dn(n)}function Vn(n,r){return Fn(n,r,1/0)}function Pn(n,r,t){return tn.iteratee!==Vn?tn.iteratee(n,r):Fn(n,r,t)}function qn(){}function Un(n,r){return null==r&&(r=n,n=0),n+Math.floor(Math.random()*(r-n+1))}tn.toPath=En,tn.iteratee=Vn;var Wn=Date.now||function(){return(new Date).getTime()};function zn(n){var r=function(r){return n[r]},t=\"(?:\"+nn(n).join(\"|\")+\")\",e=RegExp(t),u=RegExp(t,\"g\");return function(n){return n=null==n?\"\":\"\"+n,e.test(n)?n.replace(u,r):n}}var Ln={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#x27;\",\"`\":\"&#x60;\"},$n=zn(Ln),Cn=zn(_n(Ln)),Kn=tn.templateSettings={evaluate:/<%([\\s\\S]+?)%>/g,interpolate:/<%=([\\s\\S]+?)%>/g,escape:/<%-([\\s\\S]+?)%>/g},Jn=/(.)^/,Gn={\"'\":\"'\",\"\\\\\":\"\\\\\",\"\\r\":\"r\",\"\\n\":\"n\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},Hn=/\\\\|'|\\r|\\n|\\u2028|\\u2029/g;function Qn(n){return\"\\\\\"+Gn[n]}var Xn=/^\\s*(\\w|\\$)+\\s*$/;var Yn=0;function Zn(n,r,t,e,u){if(!(e instanceof r))return n.apply(t,u);var o=Mn(n.prototype),i=n.apply(o,u);return _(i)?i:o}var nr=j((function(n,r){var t=nr.placeholder,e=function(){for(var u=0,o=r.length,i=Array(o),a=0;a<o;a++)i[a]=r[a]===t?arguments[u++]:r[a];for(;u<arguments.length;)i.push(arguments[u++]);return Zn(n,e,this,this,i)};return e}));nr.placeholder=tn;var rr=j((function(n,r,t){if(!D(n))throw new TypeError(\"Bind must be called on a function\");var e=j((function(u){return Zn(n,e,r,this,t.concat(u))}));return e})),tr=K(Y);function er(n,r,t,e){if(e=e||[],r||0===r){if(r<=0)return e.concat(n)}else r=1/0;for(var u=e.length,o=0,i=Y(n);o<i;o++){var a=n[o];if(tr(a)&&(U(a)||L(a)))if(r>1)er(a,r-1,t,e),u=e.length;else for(var f=0,c=a.length;f<c;)e[u++]=a[f++];else t||(e[u++]=a)}return e}var ur=j((function(n,r){var t=(r=er(r,!1,!1)).length;if(t<1)throw new Error(\"bindAll must be passed function names\");for(;t--;){var e=r[t];n[e]=rr(n[e],n)}return n}));var or=j((function(n,r,t){return setTimeout((function(){return n.apply(null,t)}),r)})),ir=nr(or,tn,1);function ar(n){return function(){return!n.apply(this,arguments)}}function fr(n,r){var t;return function(){return--n>0&&(t=r.apply(this,arguments)),n<=1&&(r=null),t}}var cr=nr(fr,2);function lr(n,r,t){r=Pn(r,t);for(var e,u=nn(n),o=0,i=u.length;o<i;o++)if(r(n[e=u[o]],e,n))return e}function sr(n){return function(r,t,e){t=Pn(t,e);for(var u=Y(r),o=n>0?0:u-1;o>=0&&o<u;o+=n)if(t(r[o],o,r))return o;return-1}}var pr=sr(1),vr=sr(-1);function hr(n,r,t,e){for(var u=(t=Pn(t,e,1))(r),o=0,i=Y(n);o<i;){var a=Math.floor((o+i)/2);t(n[a])<u?o=a+1:i=a}return o}function yr(n,r,t){return function(e,u,o){var a=0,f=Y(e);if(\"number\"==typeof o)n>0?a=o>=0?o:Math.max(o+f,a):f=o>=0?Math.min(o+1,f):o+f+1;else if(t&&o&&f)return e[o=t(e,u)]===u?o:-1;if(u!=u)return(o=r(i.call(e,a,f),$))>=0?o+a:-1;for(o=n>0?a:f-1;o>=0&&o<f;o+=n)if(e[o]===u)return o;return-1}}var dr=yr(1,pr,hr),gr=yr(-1,vr);function br(n,r,t){var e=(tr(n)?pr:lr)(n,r,t);if(void 0!==e&&-1!==e)return n[e]}function mr(n,r,t){var e,u;if(r=Rn(r,t),tr(n))for(e=0,u=n.length;e<u;e++)r(n[e],e,n);else{var o=nn(n);for(e=0,u=o.length;e<u;e++)r(n[o[e]],o[e],n)}return n}function jr(n,r,t){r=Pn(r,t);for(var e=!tr(n)&&nn(n),u=(e||n).length,o=Array(u),i=0;i<u;i++){var a=e?e[i]:i;o[i]=r(n[a],a,n)}return o}function _r(n){var r=function(r,t,e,u){var o=!tr(r)&&nn(r),i=(o||r).length,a=n>0?0:i-1;for(u||(e=r[o?o[a]:a],a+=n);a>=0&&a<i;a+=n){var f=o?o[a]:a;e=t(e,r[f],f,r)}return e};return function(n,t,e,u){var o=arguments.length>=3;return r(n,Rn(t,u,4),e,o)}}var wr=_r(1),Ar=_r(-1);function xr(n,r,t){var e=[];return r=Pn(r,t),mr(n,(function(n,t,u){r(n,t,u)&&e.push(n)})),e}function Sr(n,r,t){r=Pn(r,t);for(var e=!tr(n)&&nn(n),u=(e||n).length,o=0;o<u;o++){var i=e?e[o]:o;if(!r(n[i],i,n))return!1}return!0}function Or(n,r,t){r=Pn(r,t);for(var e=!tr(n)&&nn(n),u=(e||n).length,o=0;o<u;o++){var i=e?e[o]:o;if(r(n[i],i,n))return!0}return!1}function Mr(n,r,t,e){return tr(n)||(n=jn(n)),(\"number\"!=typeof t||e)&&(t=0),dr(n,r,t)>=0}var Er=j((function(n,r,t){var e,u;return D(r)?u=r:(r=Bn(r),e=r.slice(0,-1),r=r[r.length-1]),jr(n,(function(n){var o=u;if(!o){if(e&&e.length&&(n=Nn(n,e)),null==n)return;o=n[r]}return null==o?o:o.apply(n,t)}))}));function Br(n,r){return jr(n,Dn(r))}function Nr(n,r,t){var e,u,o=-1/0,i=-1/0;if(null==r||\"number\"==typeof r&&\"object\"!=typeof n[0]&&null!=n)for(var a=0,f=(n=tr(n)?n:jn(n)).length;a<f;a++)null!=(e=n[a])&&e>o&&(o=e);else r=Pn(r,t),mr(n,(function(n,t,e){((u=r(n,t,e))>i||u===-1/0&&o===-1/0)&&(o=n,i=u)}));return o}var Ir=/[^\\ud800-\\udfff]|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff]/g;function Tr(n){return n?U(n)?i.call(n):S(n)?n.match(Ir):tr(n)?jr(n,Tn):jn(n):[]}function kr(n,r,t){if(null==r||t)return tr(n)||(n=jn(n)),n[Un(n.length-1)];var e=Tr(n),u=Y(e);r=Math.max(Math.min(r,u),0);for(var o=u-1,i=0;i<r;i++){var a=Un(i,o),f=e[i];e[i]=e[a],e[a]=f}return e.slice(0,r)}function Dr(n,r){return function(t,e,u){var o=r?[[],[]]:{};return e=Pn(e,u),mr(t,(function(r,u){var i=e(r,u,t);n(o,r,i)})),o}}var Rr=Dr((function(n,r,t){W(n,t)?n[t].push(r):n[t]=[r]})),Fr=Dr((function(n,r,t){n[t]=r})),Vr=Dr((function(n,r,t){W(n,t)?n[t]++:n[t]=1})),Pr=Dr((function(n,r,t){n[t?0:1].push(r)}),!0);function qr(n,r,t){return r in t}var Ur=j((function(n,r){var t={},e=r[0];if(null==n)return t;D(e)?(r.length>1&&(e=Rn(e,r[1])),r=an(n)):(e=qr,r=er(r,!1,!1),n=Object(n));for(var u=0,o=r.length;u<o;u++){var i=r[u],a=n[i];e(a,i,n)&&(t[i]=a)}return t})),Wr=j((function(n,r){var t,e=r[0];return D(e)?(e=ar(e),r.length>1&&(t=r[1])):(r=jr(er(r,!1,!1),String),e=function(n,t){return!Mr(r,t)}),Ur(n,e,t)}));function zr(n,r,t){return i.call(n,0,Math.max(0,n.length-(null==r||t?1:r)))}function Lr(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[0]:zr(n,n.length-r)}function $r(n,r,t){return i.call(n,null==r||t?1:r)}var Cr=j((function(n,r){return r=er(r,!0,!0),xr(n,(function(n){return!Mr(r,n)}))})),Kr=j((function(n,r){return Cr(n,r)}));function Jr(n,r,t,e){A(r)||(e=t,t=r,r=!1),null!=t&&(t=Pn(t,e));for(var u=[],o=[],i=0,a=Y(n);i<a;i++){var f=n[i],c=t?t(f,i,n):f;r&&!t?(i&&o===c||u.push(f),o=c):t?Mr(o,c)||(o.push(c),u.push(f)):Mr(u,f)||u.push(f)}return u}var Gr=j((function(n){return Jr(er(n,!0,!0))}));function Hr(n){for(var r=n&&Nr(n,Y).length||0,t=Array(r),e=0;e<r;e++)t[e]=Br(n,e);return t}var Qr=j(Hr);function Xr(n,r){return n._chain?tn(r).chain():r}function Yr(n){return mr(wn(n),(function(r){var t=tn[r]=n[r];tn.prototype[r]=function(){var n=[this._wrapped];return o.apply(n,arguments),Xr(this,t.apply(tn,n))}})),tn}mr([\"pop\",\"push\",\"reverse\",\"shift\",\"sort\",\"splice\",\"unshift\"],(function(n){var r=t[n];tn.prototype[n]=function(){var t=this._wrapped;return null!=t&&(r.apply(t,arguments),\"shift\"!==n&&\"splice\"!==n||0!==t.length||delete t[0]),Xr(this,t)}})),mr([\"concat\",\"join\",\"slice\"],(function(n){var r=t[n];tn.prototype[n]=function(){var n=this._wrapped;return null!=n&&(n=r.apply(n,arguments)),Xr(this,n)}}));var Zr=Yr({__proto__:null,VERSION:n,restArguments:j,isObject:_,isNull:function(n){return null===n},isUndefined:w,isBoolean:A,isElement:function(n){return!(!n||1!==n.nodeType)},isString:S,isNumber:O,isDate:M,isRegExp:E,isError:B,isSymbol:N,isArrayBuffer:I,isDataView:q,isArray:U,isFunction:D,isArguments:L,isFinite:function(n){return!N(n)&&d(n)&&!isNaN(parseFloat(n))},isNaN:$,isTypedArray:X,isEmpty:function(n){if(null==n)return!0;var r=Y(n);return\"number\"==typeof r&&(U(n)||S(n)||L(n))?0===r:0===Y(nn(n))},isMatch:rn,isEqual:function(n,r){return on(n,r)},isMap:dn,isWeakMap:gn,isSet:bn,isWeakSet:mn,keys:nn,allKeys:an,values:jn,pairs:function(n){for(var r=nn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=[r[u],n[r[u]]];return e},invert:_n,functions:wn,methods:wn,extend:xn,extendOwn:Sn,assign:Sn,defaults:On,create:function(n,r){var t=Mn(n);return r&&Sn(t,r),t},clone:function(n){return _(n)?U(n)?n.slice():xn({},n):n},tap:function(n,r){return r(n),n},get:In,has:function(n,r){for(var t=(r=Bn(r)).length,e=0;e<t;e++){var u=r[e];if(!W(n,u))return!1;n=n[u]}return!!t},mapObject:function(n,r,t){r=Pn(r,t);for(var e=nn(n),u=e.length,o={},i=0;i<u;i++){var a=e[i];o[a]=r(n[a],a,n)}return o},identity:Tn,constant:C,noop:qn,toPath:En,property:Dn,propertyOf:function(n){return null==n?qn:function(r){return In(n,r)}},matcher:kn,matches:kn,times:function(n,r,t){var e=Array(Math.max(0,n));r=Rn(r,t,1);for(var u=0;u<n;u++)e[u]=r(u);return e},random:Un,now:Wn,escape:$n,unescape:Cn,templateSettings:Kn,template:function(n,r,t){!r&&t&&(r=t),r=On({},r,tn.templateSettings);var e=RegExp([(r.escape||Jn).source,(r.interpolate||Jn).source,(r.evaluate||Jn).source].join(\"|\")+\"|$\",\"g\"),u=0,o=\"__p+='\";n.replace(e,(function(r,t,e,i,a){return o+=n.slice(u,a).replace(Hn,Qn),u=a+r.length,t?o+=\"'+\\n((__t=(\"+t+\"))==null?'':_.escape(__t))+\\n'\":e?o+=\"'+\\n((__t=(\"+e+\"))==null?'':__t)+\\n'\":i&&(o+=\"';\\n\"+i+\"\\n__p+='\"),r})),o+=\"';\\n\";var i,a=r.variable;if(a){if(!Xn.test(a))throw new Error(\"variable is not a bare identifier: \"+a)}else o=\"with(obj||{}){\\n\"+o+\"}\\n\",a=\"obj\";o=\"var __t,__p='',__j=Array.prototype.join,\"+\"print=function(){__p+=__j.call(arguments,'');};\\n\"+o+\"return __p;\\n\";try{i=new Function(a,\"_\",o)}catch(n){throw n.source=o,n}var f=function(n){return i.call(this,n,tn)};return f.source=\"function(\"+a+\"){\\n\"+o+\"}\",f},result:function(n,r,t){var e=(r=Bn(r)).length;if(!e)return D(t)?t.call(n):t;for(var u=0;u<e;u++){var o=null==n?void 0:n[r[u]];void 0===o&&(o=t,u=e),n=D(o)?o.call(n):o}return n},uniqueId:function(n){var r=++Yn+\"\";return n?n+r:r},chain:function(n){var r=tn(n);return r._chain=!0,r},iteratee:Vn,partial:nr,bind:rr,bindAll:ur,memoize:function(n,r){var t=function(e){var u=t.cache,o=\"\"+(r?r.apply(this,arguments):e);return W(u,o)||(u[o]=n.apply(this,arguments)),u[o]};return t.cache={},t},delay:or,defer:ir,throttle:function(n,r,t){var e,u,o,i,a=0;t||(t={});var f=function(){a=!1===t.leading?0:Wn(),e=null,i=n.apply(u,o),e||(u=o=null)},c=function(){var c=Wn();a||!1!==t.leading||(a=c);var l=r-(c-a);return u=this,o=arguments,l<=0||l>r?(e&&(clearTimeout(e),e=null),a=c,i=n.apply(u,o),e||(u=o=null)):e||!1===t.trailing||(e=setTimeout(f,l)),i};return c.cancel=function(){clearTimeout(e),a=0,e=u=o=null},c},debounce:function(n,r,t){var e,u,o,i,a,f=function(){var c=Wn()-u;r>c?e=setTimeout(f,r-c):(e=null,t||(i=n.apply(a,o)),e||(o=a=null))},c=j((function(c){return a=this,o=c,u=Wn(),e||(e=setTimeout(f,r),t&&(i=n.apply(a,o))),i}));return c.cancel=function(){clearTimeout(e),e=o=a=null},c},wrap:function(n,r){return nr(r,n)},negate:ar,compose:function(){var n=arguments,r=n.length-1;return function(){for(var t=r,e=n[r].apply(this,arguments);t--;)e=n[t].call(this,e);return e}},after:function(n,r){return function(){if(--n<1)return r.apply(this,arguments)}},before:fr,once:cr,findKey:lr,findIndex:pr,findLastIndex:vr,sortedIndex:hr,indexOf:dr,lastIndexOf:gr,find:br,detect:br,findWhere:function(n,r){return br(n,kn(r))},each:mr,forEach:mr,map:jr,collect:jr,reduce:wr,foldl:wr,inject:wr,reduceRight:Ar,foldr:Ar,filter:xr,select:xr,reject:function(n,r,t){return xr(n,ar(Pn(r)),t)},every:Sr,all:Sr,some:Or,any:Or,contains:Mr,includes:Mr,include:Mr,invoke:Er,pluck:Br,where:function(n,r){return xr(n,kn(r))},max:Nr,min:function(n,r,t){var e,u,o=1/0,i=1/0;if(null==r||\"number\"==typeof r&&\"object\"!=typeof n[0]&&null!=n)for(var a=0,f=(n=tr(n)?n:jn(n)).length;a<f;a++)null!=(e=n[a])&&e<o&&(o=e);else r=Pn(r,t),mr(n,(function(n,t,e){((u=r(n,t,e))<i||u===1/0&&o===1/0)&&(o=n,i=u)}));return o},shuffle:function(n){return kr(n,1/0)},sample:kr,sortBy:function(n,r,t){var e=0;return r=Pn(r,t),Br(jr(n,(function(n,t,u){return{value:n,index:e++,criteria:r(n,t,u)}})).sort((function(n,r){var t=n.criteria,e=r.criteria;if(t!==e){if(t>e||void 0===t)return 1;if(t<e||void 0===e)return-1}return n.index-r.index})),\"value\")},groupBy:Rr,indexBy:Fr,countBy:Vr,partition:Pr,toArray:Tr,size:function(n){return null==n?0:tr(n)?n.length:nn(n).length},pick:Ur,omit:Wr,first:Lr,head:Lr,take:Lr,initial:zr,last:function(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[n.length-1]:$r(n,Math.max(0,n.length-r))},rest:$r,tail:$r,drop:$r,compact:function(n){return xr(n,Boolean)},flatten:function(n,r){return er(n,r,!1)},without:Kr,uniq:Jr,unique:Jr,union:Gr,intersection:function(n){for(var r=[],t=arguments.length,e=0,u=Y(n);e<u;e++){var o=n[e];if(!Mr(r,o)){var i;for(i=1;i<t&&Mr(arguments[i],o);i++);i===t&&r.push(o)}}return r},difference:Cr,unzip:Hr,transpose:Hr,zip:Qr,object:function(n,r){for(var t={},e=0,u=Y(n);e<u;e++)r?t[n[e]]=r[e]:t[n[e][0]]=n[e][1];return t},range:function(n,r,t){null==r&&(r=n||0,n=0),t||(t=r<n?-1:1);for(var e=Math.max(Math.ceil((r-n)/t),0),u=Array(e),o=0;o<e;o++,n+=t)u[o]=n;return u},chunk:function(n,r){if(null==r||r<1)return[];for(var t=[],e=0,u=n.length;e<u;)t.push(i.call(n,e,e+=r));return t},mixin:Yr,default:tn});return Zr._=Zr,Zr}));"
  },
  {
    "path": "lib/underscore.js",
    "content": "//     Underscore.js 1.8.3\n//     http://underscorejs.org\n//     (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n//     Underscore may be freely distributed under the MIT license.\n\n(function() {\n\n  // Baseline setup\n  // --------------\n\n  // Establish the root object, `window` in the browser, or `exports` on the server.\n  var root = this;\n\n  // Save the previous value of the `_` variable.\n  var previousUnderscore = root._;\n\n  // Save bytes in the minified (but not gzipped) version:\n  var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;\n\n  // Create quick reference variables for speed access to core prototypes.\n  var\n    push             = ArrayProto.push,\n    slice            = ArrayProto.slice,\n    toString         = ObjProto.toString,\n    hasOwnProperty   = ObjProto.hasOwnProperty;\n\n  // All **ECMAScript 5** native function implementations that we hope to use\n  // are declared here.\n  var\n    nativeIsArray      = Array.isArray,\n    nativeKeys         = Object.keys,\n    nativeBind         = FuncProto.bind,\n    nativeCreate       = Object.create;\n\n  // Naked function reference for surrogate-prototype-swapping.\n  var Ctor = function(){};\n\n  // Create a safe reference to the Underscore object for use below.\n  var _ = function(obj) {\n    if (obj instanceof _) return obj;\n    if (!(this instanceof _)) return new _(obj);\n    this._wrapped = obj;\n  };\n\n  // Export the Underscore object for **Node.js**, with\n  // backwards-compatibility for the old `require()` API. If we're in\n  // the browser, add `_` as a global object.\n  if (typeof exports !== 'undefined') {\n    if (typeof module !== 'undefined' && module.exports) {\n      exports = module.exports = _;\n    }\n    exports._ = _;\n  } else {\n    root._ = _;\n  }\n\n  // Current version.\n  _.VERSION = '1.8.3';\n\n  // Internal function that returns an efficient (for current engines) version\n  // of the passed-in callback, to be repeatedly applied in other Underscore\n  // functions.\n  var optimizeCb = function(func, context, argCount) {\n    if (context === void 0) return func;\n    switch (argCount == null ? 3 : argCount) {\n      case 1: return function(value) {\n        return func.call(context, value);\n      };\n      case 2: return function(value, other) {\n        return func.call(context, value, other);\n      };\n      case 3: return function(value, index, collection) {\n        return func.call(context, value, index, collection);\n      };\n      case 4: return function(accumulator, value, index, collection) {\n        return func.call(context, accumulator, value, index, collection);\n      };\n    }\n    return function() {\n      return func.apply(context, arguments);\n    };\n  };\n\n  // A mostly-internal function to generate callbacks that can be applied\n  // to each element in a collection, returning the desired result — either\n  // identity, an arbitrary callback, a property matcher, or a property accessor.\n  var cb = function(value, context, argCount) {\n    if (value == null) return _.identity;\n    if (_.isFunction(value)) return optimizeCb(value, context, argCount);\n    if (_.isObject(value)) return _.matcher(value);\n    return _.property(value);\n  };\n  _.iteratee = function(value, context) {\n    return cb(value, context, Infinity);\n  };\n\n  // An internal function for creating assigner functions.\n  var createAssigner = function(keysFunc, undefinedOnly) {\n    return function(obj) {\n      var length = arguments.length;\n      if (length < 2 || obj == null) return obj;\n      for (var index = 1; index < length; index++) {\n        var source = arguments[index],\n            keys = keysFunc(source),\n            l = keys.length;\n        for (var i = 0; i < l; i++) {\n          var key = keys[i];\n          if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];\n        }\n      }\n      return obj;\n    };\n  };\n\n  // An internal function for creating a new object that inherits from another.\n  var baseCreate = function(prototype) {\n    if (!_.isObject(prototype)) return {};\n    if (nativeCreate) return nativeCreate(prototype);\n    Ctor.prototype = prototype;\n    var result = new Ctor;\n    Ctor.prototype = null;\n    return result;\n  };\n\n  var property = function(key) {\n    return function(obj) {\n      return obj == null ? void 0 : obj[key];\n    };\n  };\n\n  // Helper for collection methods to determine whether a collection\n  // should be iterated as an array or as an object\n  // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength\n  // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094\n  var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;\n  var getLength = property('length');\n  var isArrayLike = function(collection) {\n    var length = getLength(collection);\n    return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;\n  };\n\n  // Collection Functions\n  // --------------------\n\n  // The cornerstone, an `each` implementation, aka `forEach`.\n  // Handles raw objects in addition to array-likes. Treats all\n  // sparse array-likes as if they were dense.\n  _.each = _.forEach = function(obj, iteratee, context) {\n    iteratee = optimizeCb(iteratee, context);\n    var i, length;\n    if (isArrayLike(obj)) {\n      for (i = 0, length = obj.length; i < length; i++) {\n        iteratee(obj[i], i, obj);\n      }\n    } else {\n      var keys = _.keys(obj);\n      for (i = 0, length = keys.length; i < length; i++) {\n        iteratee(obj[keys[i]], keys[i], obj);\n      }\n    }\n    return obj;\n  };\n\n  // Return the results of applying the iteratee to each element.\n  _.map = _.collect = function(obj, iteratee, context) {\n    iteratee = cb(iteratee, context);\n    var keys = !isArrayLike(obj) && _.keys(obj),\n        length = (keys || obj).length,\n        results = Array(length);\n    for (var index = 0; index < length; index++) {\n      var currentKey = keys ? keys[index] : index;\n      results[index] = iteratee(obj[currentKey], currentKey, obj);\n    }\n    return results;\n  };\n\n  // Create a reducing function iterating left or right.\n  function createReduce(dir) {\n    // Optimized iterator function as using arguments.length\n    // in the main function will deoptimize the, see #1991.\n    function iterator(obj, iteratee, memo, keys, index, length) {\n      for (; index >= 0 && index < length; index += dir) {\n        var currentKey = keys ? keys[index] : index;\n        memo = iteratee(memo, obj[currentKey], currentKey, obj);\n      }\n      return memo;\n    }\n\n    return function(obj, iteratee, memo, context) {\n      iteratee = optimizeCb(iteratee, context, 4);\n      var keys = !isArrayLike(obj) && _.keys(obj),\n          length = (keys || obj).length,\n          index = dir > 0 ? 0 : length - 1;\n      // Determine the initial value if none is provided.\n      if (arguments.length < 3) {\n        memo = obj[keys ? keys[index] : index];\n        index += dir;\n      }\n      return iterator(obj, iteratee, memo, keys, index, length);\n    };\n  }\n\n  // **Reduce** builds up a single result from a list of values, aka `inject`,\n  // or `foldl`.\n  _.reduce = _.foldl = _.inject = createReduce(1);\n\n  // The right-associative version of reduce, also known as `foldr`.\n  _.reduceRight = _.foldr = createReduce(-1);\n\n  // Return the first value which passes a truth test. Aliased as `detect`.\n  _.find = _.detect = function(obj, predicate, context) {\n    var key;\n    if (isArrayLike(obj)) {\n      key = _.findIndex(obj, predicate, context);\n    } else {\n      key = _.findKey(obj, predicate, context);\n    }\n    if (key !== void 0 && key !== -1) return obj[key];\n  };\n\n  // Return all the elements that pass a truth test.\n  // Aliased as `select`.\n  _.filter = _.select = function(obj, predicate, context) {\n    var results = [];\n    predicate = cb(predicate, context);\n    _.each(obj, function(value, index, list) {\n      if (predicate(value, index, list)) results.push(value);\n    });\n    return results;\n  };\n\n  // Return all the elements for which a truth test fails.\n  _.reject = function(obj, predicate, context) {\n    return _.filter(obj, _.negate(cb(predicate)), context);\n  };\n\n  // Determine whether all of the elements match a truth test.\n  // Aliased as `all`.\n  _.every = _.all = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var keys = !isArrayLike(obj) && _.keys(obj),\n        length = (keys || obj).length;\n    for (var index = 0; index < length; index++) {\n      var currentKey = keys ? keys[index] : index;\n      if (!predicate(obj[currentKey], currentKey, obj)) return false;\n    }\n    return true;\n  };\n\n  // Determine if at least one element in the object matches a truth test.\n  // Aliased as `any`.\n  _.some = _.any = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var keys = !isArrayLike(obj) && _.keys(obj),\n        length = (keys || obj).length;\n    for (var index = 0; index < length; index++) {\n      var currentKey = keys ? keys[index] : index;\n      if (predicate(obj[currentKey], currentKey, obj)) return true;\n    }\n    return false;\n  };\n\n  // Determine if the array or object contains a given item (using `===`).\n  // Aliased as `includes` and `include`.\n  _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {\n    if (!isArrayLike(obj)) obj = _.values(obj);\n    if (typeof fromIndex != 'number' || guard) fromIndex = 0;\n    return _.indexOf(obj, item, fromIndex) >= 0;\n  };\n\n  // Invoke a method (with arguments) on every item in a collection.\n  _.invoke = function(obj, method) {\n    var args = slice.call(arguments, 2);\n    var isFunc = _.isFunction(method);\n    return _.map(obj, function(value) {\n      var func = isFunc ? method : value[method];\n      return func == null ? func : func.apply(value, args);\n    });\n  };\n\n  // Convenience version of a common use case of `map`: fetching a property.\n  _.pluck = function(obj, key) {\n    return _.map(obj, _.property(key));\n  };\n\n  // Convenience version of a common use case of `filter`: selecting only objects\n  // containing specific `key:value` pairs.\n  _.where = function(obj, attrs) {\n    return _.filter(obj, _.matcher(attrs));\n  };\n\n  // Convenience version of a common use case of `find`: getting the first object\n  // containing specific `key:value` pairs.\n  _.findWhere = function(obj, attrs) {\n    return _.find(obj, _.matcher(attrs));\n  };\n\n  // Return the maximum element (or element-based computation).\n  _.max = function(obj, iteratee, context) {\n    var result = -Infinity, lastComputed = -Infinity,\n        value, computed;\n    if (iteratee == null && obj != null) {\n      obj = isArrayLike(obj) ? obj : _.values(obj);\n      for (var i = 0, length = obj.length; i < length; i++) {\n        value = obj[i];\n        if (value > result) {\n          result = value;\n        }\n      }\n    } else {\n      iteratee = cb(iteratee, context);\n      _.each(obj, function(value, index, list) {\n        computed = iteratee(value, index, list);\n        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {\n          result = value;\n          lastComputed = computed;\n        }\n      });\n    }\n    return result;\n  };\n\n  // Return the minimum element (or element-based computation).\n  _.min = function(obj, iteratee, context) {\n    var result = Infinity, lastComputed = Infinity,\n        value, computed;\n    if (iteratee == null && obj != null) {\n      obj = isArrayLike(obj) ? obj : _.values(obj);\n      for (var i = 0, length = obj.length; i < length; i++) {\n        value = obj[i];\n        if (value < result) {\n          result = value;\n        }\n      }\n    } else {\n      iteratee = cb(iteratee, context);\n      _.each(obj, function(value, index, list) {\n        computed = iteratee(value, index, list);\n        if (computed < lastComputed || computed === Infinity && result === Infinity) {\n          result = value;\n          lastComputed = computed;\n        }\n      });\n    }\n    return result;\n  };\n\n  // Shuffle a collection, using the modern version of the\n  // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).\n  _.shuffle = function(obj) {\n    var set = isArrayLike(obj) ? obj : _.values(obj);\n    var length = set.length;\n    var shuffled = Array(length);\n    for (var index = 0, rand; index < length; index++) {\n      rand = _.random(0, index);\n      if (rand !== index) shuffled[index] = shuffled[rand];\n      shuffled[rand] = set[index];\n    }\n    return shuffled;\n  };\n\n  // Sample **n** random values from a collection.\n  // If **n** is not specified, returns a single random element.\n  // The internal `guard` argument allows it to work with `map`.\n  _.sample = function(obj, n, guard) {\n    if (n == null || guard) {\n      if (!isArrayLike(obj)) obj = _.values(obj);\n      return obj[_.random(obj.length - 1)];\n    }\n    return _.shuffle(obj).slice(0, Math.max(0, n));\n  };\n\n  // Sort the object's values by a criterion produced by an iteratee.\n  _.sortBy = function(obj, iteratee, context) {\n    iteratee = cb(iteratee, context);\n    return _.pluck(_.map(obj, function(value, index, list) {\n      return {\n        value: value,\n        index: index,\n        criteria: iteratee(value, index, list)\n      };\n    }).sort(function(left, right) {\n      var a = left.criteria;\n      var b = right.criteria;\n      if (a !== b) {\n        if (a > b || a === void 0) return 1;\n        if (a < b || b === void 0) return -1;\n      }\n      return left.index - right.index;\n    }), 'value');\n  };\n\n  // An internal function used for aggregate \"group by\" operations.\n  var group = function(behavior) {\n    return function(obj, iteratee, context) {\n      var result = {};\n      iteratee = cb(iteratee, context);\n      _.each(obj, function(value, index) {\n        var key = iteratee(value, index, obj);\n        behavior(result, value, key);\n      });\n      return result;\n    };\n  };\n\n  // Groups the object's values by a criterion. Pass either a string attribute\n  // to group by, or a function that returns the criterion.\n  _.groupBy = group(function(result, value, key) {\n    if (_.has(result, key)) result[key].push(value); else result[key] = [value];\n  });\n\n  // Indexes the object's values by a criterion, similar to `groupBy`, but for\n  // when you know that your index values will be unique.\n  _.indexBy = group(function(result, value, key) {\n    result[key] = value;\n  });\n\n  // Counts instances of an object that group by a certain criterion. Pass\n  // either a string attribute to count by, or a function that returns the\n  // criterion.\n  _.countBy = group(function(result, value, key) {\n    if (_.has(result, key)) result[key]++; else result[key] = 1;\n  });\n\n  // Safely create a real, live array from anything iterable.\n  _.toArray = function(obj) {\n    if (!obj) return [];\n    if (_.isArray(obj)) return slice.call(obj);\n    if (isArrayLike(obj)) return _.map(obj, _.identity);\n    return _.values(obj);\n  };\n\n  // Return the number of elements in an object.\n  _.size = function(obj) {\n    if (obj == null) return 0;\n    return isArrayLike(obj) ? obj.length : _.keys(obj).length;\n  };\n\n  // Split a collection into two arrays: one whose elements all satisfy the given\n  // predicate, and one whose elements all do not satisfy the predicate.\n  _.partition = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var pass = [], fail = [];\n    _.each(obj, function(value, key, obj) {\n      (predicate(value, key, obj) ? pass : fail).push(value);\n    });\n    return [pass, fail];\n  };\n\n  // Array Functions\n  // ---------------\n\n  // Get the first element of an array. Passing **n** will return the first N\n  // values in the array. Aliased as `head` and `take`. The **guard** check\n  // allows it to work with `_.map`.\n  _.first = _.head = _.take = function(array, n, guard) {\n    if (array == null) return void 0;\n    if (n == null || guard) return array[0];\n    return _.initial(array, array.length - n);\n  };\n\n  // Returns everything but the last entry of the array. Especially useful on\n  // the arguments object. Passing **n** will return all the values in\n  // the array, excluding the last N.\n  _.initial = function(array, n, guard) {\n    return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));\n  };\n\n  // Get the last element of an array. Passing **n** will return the last N\n  // values in the array.\n  _.last = function(array, n, guard) {\n    if (array == null) return void 0;\n    if (n == null || guard) return array[array.length - 1];\n    return _.rest(array, Math.max(0, array.length - n));\n  };\n\n  // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.\n  // Especially useful on the arguments object. Passing an **n** will return\n  // the rest N values in the array.\n  _.rest = _.tail = _.drop = function(array, n, guard) {\n    return slice.call(array, n == null || guard ? 1 : n);\n  };\n\n  // Trim out all falsy values from an array.\n  _.compact = function(array) {\n    return _.filter(array, _.identity);\n  };\n\n  // Internal implementation of a recursive `flatten` function.\n  var flatten = function(input, shallow, strict, startIndex) {\n    var output = [], idx = 0;\n    for (var i = startIndex || 0, length = getLength(input); i < length; i++) {\n      var value = input[i];\n      if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {\n        //flatten current level of array or arguments object\n        if (!shallow) value = flatten(value, shallow, strict);\n        var j = 0, len = value.length;\n        output.length += len;\n        while (j < len) {\n          output[idx++] = value[j++];\n        }\n      } else if (!strict) {\n        output[idx++] = value;\n      }\n    }\n    return output;\n  };\n\n  // Flatten out an array, either recursively (by default), or just one level.\n  _.flatten = function(array, shallow) {\n    return flatten(array, shallow, false);\n  };\n\n  // Return a version of the array that does not contain the specified value(s).\n  _.without = function(array) {\n    return _.difference(array, slice.call(arguments, 1));\n  };\n\n  // Produce a duplicate-free version of the array. If the array has already\n  // been sorted, you have the option of using a faster algorithm.\n  // Aliased as `unique`.\n  _.uniq = _.unique = function(array, isSorted, iteratee, context) {\n    if (!_.isBoolean(isSorted)) {\n      context = iteratee;\n      iteratee = isSorted;\n      isSorted = false;\n    }\n    if (iteratee != null) iteratee = cb(iteratee, context);\n    var result = [];\n    var seen = [];\n    for (var i = 0, length = getLength(array); i < length; i++) {\n      var value = array[i],\n          computed = iteratee ? iteratee(value, i, array) : value;\n      if (isSorted) {\n        if (!i || seen !== computed) result.push(value);\n        seen = computed;\n      } else if (iteratee) {\n        if (!_.contains(seen, computed)) {\n          seen.push(computed);\n          result.push(value);\n        }\n      } else if (!_.contains(result, value)) {\n        result.push(value);\n      }\n    }\n    return result;\n  };\n\n  // Produce an array that contains the union: each distinct element from all of\n  // the passed-in arrays.\n  _.union = function() {\n    return _.uniq(flatten(arguments, true, true));\n  };\n\n  // Produce an array that contains every item shared between all the\n  // passed-in arrays.\n  _.intersection = function(array) {\n    var result = [];\n    var argsLength = arguments.length;\n    for (var i = 0, length = getLength(array); i < length; i++) {\n      var item = array[i];\n      if (_.contains(result, item)) continue;\n      for (var j = 1; j < argsLength; j++) {\n        if (!_.contains(arguments[j], item)) break;\n      }\n      if (j === argsLength) result.push(item);\n    }\n    return result;\n  };\n\n  // Take the difference between one array and a number of other arrays.\n  // Only the elements present in just the first array will remain.\n  _.difference = function(array) {\n    var rest = flatten(arguments, true, true, 1);\n    return _.filter(array, function(value){\n      return !_.contains(rest, value);\n    });\n  };\n\n  // Zip together multiple lists into a single array -- elements that share\n  // an index go together.\n  _.zip = function() {\n    return _.unzip(arguments);\n  };\n\n  // Complement of _.zip. Unzip accepts an array of arrays and groups\n  // each array's elements on shared indices\n  _.unzip = function(array) {\n    var length = array && _.max(array, getLength).length || 0;\n    var result = Array(length);\n\n    for (var index = 0; index < length; index++) {\n      result[index] = _.pluck(array, index);\n    }\n    return result;\n  };\n\n  // Converts lists into objects. Pass either a single array of `[key, value]`\n  // pairs, or two parallel arrays of the same length -- one of keys, and one of\n  // the corresponding values.\n  _.object = function(list, values) {\n    var result = {};\n    for (var i = 0, length = getLength(list); i < length; i++) {\n      if (values) {\n        result[list[i]] = values[i];\n      } else {\n        result[list[i][0]] = list[i][1];\n      }\n    }\n    return result;\n  };\n\n  // Generator function to create the findIndex and findLastIndex functions\n  function createPredicateIndexFinder(dir) {\n    return function(array, predicate, context) {\n      predicate = cb(predicate, context);\n      var length = getLength(array);\n      var index = dir > 0 ? 0 : length - 1;\n      for (; index >= 0 && index < length; index += dir) {\n        if (predicate(array[index], index, array)) return index;\n      }\n      return -1;\n    };\n  }\n\n  // Returns the first index on an array-like that passes a predicate test\n  _.findIndex = createPredicateIndexFinder(1);\n  _.findLastIndex = createPredicateIndexFinder(-1);\n\n  // Use a comparator function to figure out the smallest index at which\n  // an object should be inserted so as to maintain order. Uses binary search.\n  _.sortedIndex = function(array, obj, iteratee, context) {\n    iteratee = cb(iteratee, context, 1);\n    var value = iteratee(obj);\n    var low = 0, high = getLength(array);\n    while (low < high) {\n      var mid = Math.floor((low + high) / 2);\n      if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;\n    }\n    return low;\n  };\n\n  // Generator function to create the indexOf and lastIndexOf functions\n  function createIndexFinder(dir, predicateFind, sortedIndex) {\n    return function(array, item, idx) {\n      var i = 0, length = getLength(array);\n      if (typeof idx == 'number') {\n        if (dir > 0) {\n            i = idx >= 0 ? idx : Math.max(idx + length, i);\n        } else {\n            length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;\n        }\n      } else if (sortedIndex && idx && length) {\n        idx = sortedIndex(array, item);\n        return array[idx] === item ? idx : -1;\n      }\n      if (item !== item) {\n        idx = predicateFind(slice.call(array, i, length), _.isNaN);\n        return idx >= 0 ? idx + i : -1;\n      }\n      for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {\n        if (array[idx] === item) return idx;\n      }\n      return -1;\n    };\n  }\n\n  // Return the position of the first occurrence of an item in an array,\n  // or -1 if the item is not included in the array.\n  // If the array is large and already in sort order, pass `true`\n  // for **isSorted** to use binary search.\n  _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);\n  _.lastIndexOf = createIndexFinder(-1, _.findLastIndex);\n\n  // Generate an integer Array containing an arithmetic progression. A port of\n  // the native Python `range()` function. See\n  // [the Python documentation](http://docs.python.org/library/functions.html#range).\n  _.range = function(start, stop, step) {\n    if (stop == null) {\n      stop = start || 0;\n      start = 0;\n    }\n    step = step || 1;\n\n    var length = Math.max(Math.ceil((stop - start) / step), 0);\n    var range = Array(length);\n\n    for (var idx = 0; idx < length; idx++, start += step) {\n      range[idx] = start;\n    }\n\n    return range;\n  };\n\n  // Function (ahem) Functions\n  // ------------------\n\n  // Determines whether to execute a function as a constructor\n  // or a normal function with the provided arguments\n  var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {\n    if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);\n    var self = baseCreate(sourceFunc.prototype);\n    var result = sourceFunc.apply(self, args);\n    if (_.isObject(result)) return result;\n    return self;\n  };\n\n  // Create a function bound to a given object (assigning `this`, and arguments,\n  // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if\n  // available.\n  _.bind = function(func, context) {\n    if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));\n    if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');\n    var args = slice.call(arguments, 2);\n    var bound = function() {\n      return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));\n    };\n    return bound;\n  };\n\n  // Partially apply a function by creating a version that has had some of its\n  // arguments pre-filled, without changing its dynamic `this` context. _ acts\n  // as a placeholder, allowing any combination of arguments to be pre-filled.\n  _.partial = function(func) {\n    var boundArgs = slice.call(arguments, 1);\n    var bound = function() {\n      var position = 0, length = boundArgs.length;\n      var args = Array(length);\n      for (var i = 0; i < length; i++) {\n        args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];\n      }\n      while (position < arguments.length) args.push(arguments[position++]);\n      return executeBound(func, bound, this, this, args);\n    };\n    return bound;\n  };\n\n  // Bind a number of an object's methods to that object. Remaining arguments\n  // are the method names to be bound. Useful for ensuring that all callbacks\n  // defined on an object belong to it.\n  _.bindAll = function(obj) {\n    var i, length = arguments.length, key;\n    if (length <= 1) throw new Error('bindAll must be passed function names');\n    for (i = 1; i < length; i++) {\n      key = arguments[i];\n      obj[key] = _.bind(obj[key], obj);\n    }\n    return obj;\n  };\n\n  // Memoize an expensive function by storing its results.\n  _.memoize = function(func, hasher) {\n    var memoize = function(key) {\n      var cache = memoize.cache;\n      var address = '' + (hasher ? hasher.apply(this, arguments) : key);\n      if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);\n      return cache[address];\n    };\n    memoize.cache = {};\n    return memoize;\n  };\n\n  // Delays a function for the given number of milliseconds, and then calls\n  // it with the arguments supplied.\n  _.delay = function(func, wait) {\n    var args = slice.call(arguments, 2);\n    return setTimeout(function(){\n      return func.apply(null, args);\n    }, wait);\n  };\n\n  // Defers a function, scheduling it to run after the current call stack has\n  // cleared.\n  _.defer = _.partial(_.delay, _, 1);\n\n  // Returns a function, that, when invoked, will only be triggered at most once\n  // during a given window of time. Normally, the throttled function will run\n  // as much as it can, without ever going more than once per `wait` duration;\n  // but if you'd like to disable the execution on the leading edge, pass\n  // `{leading: false}`. To disable execution on the trailing edge, ditto.\n  _.throttle = function(func, wait, options) {\n    var context, args, result;\n    var timeout = null;\n    var previous = 0;\n    if (!options) options = {};\n    var later = function() {\n      previous = options.leading === false ? 0 : _.now();\n      timeout = null;\n      result = func.apply(context, args);\n      if (!timeout) context = args = null;\n    };\n    return function() {\n      var now = _.now();\n      if (!previous && options.leading === false) previous = now;\n      var remaining = wait - (now - previous);\n      context = this;\n      args = arguments;\n      if (remaining <= 0 || remaining > wait) {\n        if (timeout) {\n          clearTimeout(timeout);\n          timeout = null;\n        }\n        previous = now;\n        result = func.apply(context, args);\n        if (!timeout) context = args = null;\n      } else if (!timeout && options.trailing !== false) {\n        timeout = setTimeout(later, remaining);\n      }\n      return result;\n    };\n  };\n\n  // Returns a function, that, as long as it continues to be invoked, will not\n  // be triggered. The function will be called after it stops being called for\n  // N milliseconds. If `immediate` is passed, trigger the function on the\n  // leading edge, instead of the trailing.\n  _.debounce = function(func, wait, immediate) {\n    var timeout, args, context, timestamp, result;\n\n    var later = function() {\n      var last = _.now() - timestamp;\n\n      if (last < wait && last >= 0) {\n        timeout = setTimeout(later, wait - last);\n      } else {\n        timeout = null;\n        if (!immediate) {\n          result = func.apply(context, args);\n          if (!timeout) context = args = null;\n        }\n      }\n    };\n\n    return function() {\n      context = this;\n      args = arguments;\n      timestamp = _.now();\n      var callNow = immediate && !timeout;\n      if (!timeout) timeout = setTimeout(later, wait);\n      if (callNow) {\n        result = func.apply(context, args);\n        context = args = null;\n      }\n\n      return result;\n    };\n  };\n\n  // Returns the first function passed as an argument to the second,\n  // allowing you to adjust arguments, run code before and after, and\n  // conditionally execute the original function.\n  _.wrap = function(func, wrapper) {\n    return _.partial(wrapper, func);\n  };\n\n  // Returns a negated version of the passed-in predicate.\n  _.negate = function(predicate) {\n    return function() {\n      return !predicate.apply(this, arguments);\n    };\n  };\n\n  // Returns a function that is the composition of a list of functions, each\n  // consuming the return value of the function that follows.\n  _.compose = function() {\n    var args = arguments;\n    var start = args.length - 1;\n    return function() {\n      var i = start;\n      var result = args[start].apply(this, arguments);\n      while (i--) result = args[i].call(this, result);\n      return result;\n    };\n  };\n\n  // Returns a function that will only be executed on and after the Nth call.\n  _.after = function(times, func) {\n    return function() {\n      if (--times < 1) {\n        return func.apply(this, arguments);\n      }\n    };\n  };\n\n  // Returns a function that will only be executed up to (but not including) the Nth call.\n  _.before = function(times, func) {\n    var memo;\n    return function() {\n      if (--times > 0) {\n        memo = func.apply(this, arguments);\n      }\n      if (times <= 1) func = null;\n      return memo;\n    };\n  };\n\n  // Returns a function that will be executed at most one time, no matter how\n  // often you call it. Useful for lazy initialization.\n  _.once = _.partial(_.before, 2);\n\n  // Object Functions\n  // ----------------\n\n  // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.\n  var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');\n  var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',\n                      'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];\n\n  function collectNonEnumProps(obj, keys) {\n    var nonEnumIdx = nonEnumerableProps.length;\n    var constructor = obj.constructor;\n    var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;\n\n    // Constructor is a special case.\n    var prop = 'constructor';\n    if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);\n\n    while (nonEnumIdx--) {\n      prop = nonEnumerableProps[nonEnumIdx];\n      if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {\n        keys.push(prop);\n      }\n    }\n  }\n\n  // Retrieve the names of an object's own properties.\n  // Delegates to **ECMAScript 5**'s native `Object.keys`\n  _.keys = function(obj) {\n    if (!_.isObject(obj)) return [];\n    if (nativeKeys) return nativeKeys(obj);\n    var keys = [];\n    for (var key in obj) if (_.has(obj, key)) keys.push(key);\n    // Ahem, IE < 9.\n    if (hasEnumBug) collectNonEnumProps(obj, keys);\n    return keys;\n  };\n\n  // Retrieve all the property names of an object.\n  _.allKeys = function(obj) {\n    if (!_.isObject(obj)) return [];\n    var keys = [];\n    for (var key in obj) keys.push(key);\n    // Ahem, IE < 9.\n    if (hasEnumBug) collectNonEnumProps(obj, keys);\n    return keys;\n  };\n\n  // Retrieve the values of an object's properties.\n  _.values = function(obj) {\n    var keys = _.keys(obj);\n    var length = keys.length;\n    var values = Array(length);\n    for (var i = 0; i < length; i++) {\n      values[i] = obj[keys[i]];\n    }\n    return values;\n  };\n\n  // Returns the results of applying the iteratee to each element of the object\n  // In contrast to _.map it returns an object\n  _.mapObject = function(obj, iteratee, context) {\n    iteratee = cb(iteratee, context);\n    var keys =  _.keys(obj),\n          length = keys.length,\n          results = {},\n          currentKey;\n      for (var index = 0; index < length; index++) {\n        currentKey = keys[index];\n        results[currentKey] = iteratee(obj[currentKey], currentKey, obj);\n      }\n      return results;\n  };\n\n  // Convert an object into a list of `[key, value]` pairs.\n  _.pairs = function(obj) {\n    var keys = _.keys(obj);\n    var length = keys.length;\n    var pairs = Array(length);\n    for (var i = 0; i < length; i++) {\n      pairs[i] = [keys[i], obj[keys[i]]];\n    }\n    return pairs;\n  };\n\n  // Invert the keys and values of an object. The values must be serializable.\n  _.invert = function(obj) {\n    var result = {};\n    var keys = _.keys(obj);\n    for (var i = 0, length = keys.length; i < length; i++) {\n      result[obj[keys[i]]] = keys[i];\n    }\n    return result;\n  };\n\n  // Return a sorted list of the function names available on the object.\n  // Aliased as `methods`\n  _.functions = _.methods = function(obj) {\n    var names = [];\n    for (var key in obj) {\n      if (_.isFunction(obj[key])) names.push(key);\n    }\n    return names.sort();\n  };\n\n  // Extend a given object with all the properties in passed-in object(s).\n  _.extend = createAssigner(_.allKeys);\n\n  // Assigns a given object with all the own properties in the passed-in object(s)\n  // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)\n  _.extendOwn = _.assign = createAssigner(_.keys);\n\n  // Returns the first key on an object that passes a predicate test\n  _.findKey = function(obj, predicate, context) {\n    predicate = cb(predicate, context);\n    var keys = _.keys(obj), key;\n    for (var i = 0, length = keys.length; i < length; i++) {\n      key = keys[i];\n      if (predicate(obj[key], key, obj)) return key;\n    }\n  };\n\n  // Return a copy of the object only containing the whitelisted properties.\n  _.pick = function(object, oiteratee, context) {\n    var result = {}, obj = object, iteratee, keys;\n    if (obj == null) return result;\n    if (_.isFunction(oiteratee)) {\n      keys = _.allKeys(obj);\n      iteratee = optimizeCb(oiteratee, context);\n    } else {\n      keys = flatten(arguments, false, false, 1);\n      iteratee = function(value, key, obj) { return key in obj; };\n      obj = Object(obj);\n    }\n    for (var i = 0, length = keys.length; i < length; i++) {\n      var key = keys[i];\n      var value = obj[key];\n      if (iteratee(value, key, obj)) result[key] = value;\n    }\n    return result;\n  };\n\n   // Return a copy of the object without the blacklisted properties.\n  _.omit = function(obj, iteratee, context) {\n    if (_.isFunction(iteratee)) {\n      iteratee = _.negate(iteratee);\n    } else {\n      var keys = _.map(flatten(arguments, false, false, 1), String);\n      iteratee = function(value, key) {\n        return !_.contains(keys, key);\n      };\n    }\n    return _.pick(obj, iteratee, context);\n  };\n\n  // Fill in a given object with default properties.\n  _.defaults = createAssigner(_.allKeys, true);\n\n  // Creates an object that inherits from the given prototype object.\n  // If additional properties are provided then they will be added to the\n  // created object.\n  _.create = function(prototype, props) {\n    var result = baseCreate(prototype);\n    if (props) _.extendOwn(result, props);\n    return result;\n  };\n\n  // Create a (shallow-cloned) duplicate of an object.\n  _.clone = function(obj) {\n    if (!_.isObject(obj)) return obj;\n    return _.isArray(obj) ? obj.slice() : _.extend({}, obj);\n  };\n\n  // Invokes interceptor with the obj, and then returns obj.\n  // The primary purpose of this method is to \"tap into\" a method chain, in\n  // order to perform operations on intermediate results within the chain.\n  _.tap = function(obj, interceptor) {\n    interceptor(obj);\n    return obj;\n  };\n\n  // Returns whether an object has a given set of `key:value` pairs.\n  _.isMatch = function(object, attrs) {\n    var keys = _.keys(attrs), length = keys.length;\n    if (object == null) return !length;\n    var obj = Object(object);\n    for (var i = 0; i < length; i++) {\n      var key = keys[i];\n      if (attrs[key] !== obj[key] || !(key in obj)) return false;\n    }\n    return true;\n  };\n\n\n  // Internal recursive comparison function for `isEqual`.\n  var eq = function(a, b, aStack, bStack) {\n    // Identical objects are equal. `0 === -0`, but they aren't identical.\n    // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).\n    if (a === b) return a !== 0 || 1 / a === 1 / b;\n    // A strict comparison is necessary because `null == undefined`.\n    if (a == null || b == null) return a === b;\n    // Unwrap any wrapped objects.\n    if (a instanceof _) a = a._wrapped;\n    if (b instanceof _) b = b._wrapped;\n    // Compare `[[Class]]` names.\n    var className = toString.call(a);\n    if (className !== toString.call(b)) return false;\n    switch (className) {\n      // Strings, numbers, regular expressions, dates, and booleans are compared by value.\n      case '[object RegExp]':\n      // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')\n      case '[object String]':\n        // Primitives and their corresponding object wrappers are equivalent; thus, `\"5\"` is\n        // equivalent to `new String(\"5\")`.\n        return '' + a === '' + b;\n      case '[object Number]':\n        // `NaN`s are equivalent, but non-reflexive.\n        // Object(NaN) is equivalent to NaN\n        if (+a !== +a) return +b !== +b;\n        // An `egal` comparison is performed for other numeric values.\n        return +a === 0 ? 1 / +a === 1 / b : +a === +b;\n      case '[object Date]':\n      case '[object Boolean]':\n        // Coerce dates and booleans to numeric primitive values. Dates are compared by their\n        // millisecond representations. Note that invalid dates with millisecond representations\n        // of `NaN` are not equivalent.\n        return +a === +b;\n    }\n\n    var areArrays = className === '[object Array]';\n    if (!areArrays) {\n      if (typeof a != 'object' || typeof b != 'object') return false;\n\n      // Objects with different constructors are not equivalent, but `Object`s or `Array`s\n      // from different frames are.\n      var aCtor = a.constructor, bCtor = b.constructor;\n      if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&\n                               _.isFunction(bCtor) && bCtor instanceof bCtor)\n                          && ('constructor' in a && 'constructor' in b)) {\n        return false;\n      }\n    }\n    // Assume equality for cyclic structures. The algorithm for detecting cyclic\n    // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.\n\n    // Initializing stack of traversed objects.\n    // It's done here since we only need them for objects and arrays comparison.\n    aStack = aStack || [];\n    bStack = bStack || [];\n    var length = aStack.length;\n    while (length--) {\n      // Linear search. Performance is inversely proportional to the number of\n      // unique nested structures.\n      if (aStack[length] === a) return bStack[length] === b;\n    }\n\n    // Add the first object to the stack of traversed objects.\n    aStack.push(a);\n    bStack.push(b);\n\n    // Recursively compare objects and arrays.\n    if (areArrays) {\n      // Compare array lengths to determine if a deep comparison is necessary.\n      length = a.length;\n      if (length !== b.length) return false;\n      // Deep compare the contents, ignoring non-numeric properties.\n      while (length--) {\n        if (!eq(a[length], b[length], aStack, bStack)) return false;\n      }\n    } else {\n      // Deep compare objects.\n      var keys = _.keys(a), key;\n      length = keys.length;\n      // Ensure that both objects contain the same number of properties before comparing deep equality.\n      if (_.keys(b).length !== length) return false;\n      while (length--) {\n        // Deep compare each member\n        key = keys[length];\n        if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;\n      }\n    }\n    // Remove the first object from the stack of traversed objects.\n    aStack.pop();\n    bStack.pop();\n    return true;\n  };\n\n  // Perform a deep comparison to check if two objects are equal.\n  _.isEqual = function(a, b) {\n    return eq(a, b);\n  };\n\n  // Is a given array, string, or object empty?\n  // An \"empty\" object has no enumerable own-properties.\n  _.isEmpty = function(obj) {\n    if (obj == null) return true;\n    if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;\n    return _.keys(obj).length === 0;\n  };\n\n  // Is a given value a DOM element?\n  _.isElement = function(obj) {\n    return !!(obj && obj.nodeType === 1);\n  };\n\n  // Is a given value an array?\n  // Delegates to ECMA5's native Array.isArray\n  _.isArray = nativeIsArray || function(obj) {\n    return toString.call(obj) === '[object Array]';\n  };\n\n  // Is a given variable an object?\n  _.isObject = function(obj) {\n    var type = typeof obj;\n    return type === 'function' || type === 'object' && !!obj;\n  };\n\n  // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.\n  _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {\n    _['is' + name] = function(obj) {\n      return toString.call(obj) === '[object ' + name + ']';\n    };\n  });\n\n  // Define a fallback version of the method in browsers (ahem, IE < 9), where\n  // there isn't any inspectable \"Arguments\" type.\n  if (!_.isArguments(arguments)) {\n    _.isArguments = function(obj) {\n      return _.has(obj, 'callee');\n    };\n  }\n\n  // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,\n  // IE 11 (#1621), and in Safari 8 (#1929).\n  if (typeof /./ != 'function' && typeof Int8Array != 'object') {\n    _.isFunction = function(obj) {\n      return typeof obj == 'function' || false;\n    };\n  }\n\n  // Is a given object a finite number?\n  _.isFinite = function(obj) {\n    return isFinite(obj) && !isNaN(parseFloat(obj));\n  };\n\n  // Is the given value `NaN`? (NaN is the only number which does not equal itself).\n  _.isNaN = function(obj) {\n    return _.isNumber(obj) && obj !== +obj;\n  };\n\n  // Is a given value a boolean?\n  _.isBoolean = function(obj) {\n    return obj === true || obj === false || toString.call(obj) === '[object Boolean]';\n  };\n\n  // Is a given value equal to null?\n  _.isNull = function(obj) {\n    return obj === null;\n  };\n\n  // Is a given variable undefined?\n  _.isUndefined = function(obj) {\n    return obj === void 0;\n  };\n\n  // Shortcut function for checking if an object has a given property directly\n  // on itself (in other words, not on a prototype).\n  _.has = function(obj, key) {\n    return obj != null && hasOwnProperty.call(obj, key);\n  };\n\n  // Utility Functions\n  // -----------------\n\n  // Run Underscore.js in *noConflict* mode, returning the `_` variable to its\n  // previous owner. Returns a reference to the Underscore object.\n  _.noConflict = function() {\n    root._ = previousUnderscore;\n    return this;\n  };\n\n  // Keep the identity function around for default iteratees.\n  _.identity = function(value) {\n    return value;\n  };\n\n  // Predicate-generating functions. Often useful outside of Underscore.\n  _.constant = function(value) {\n    return function() {\n      return value;\n    };\n  };\n\n  _.noop = function(){};\n\n  _.property = property;\n\n  // Generates a function for a given object that returns a given property.\n  _.propertyOf = function(obj) {\n    return obj == null ? function(){} : function(key) {\n      return obj[key];\n    };\n  };\n\n  // Returns a predicate for checking whether an object has a given set of\n  // `key:value` pairs.\n  _.matcher = _.matches = function(attrs) {\n    attrs = _.extendOwn({}, attrs);\n    return function(obj) {\n      return _.isMatch(obj, attrs);\n    };\n  };\n\n  // Run a function **n** times.\n  _.times = function(n, iteratee, context) {\n    var accum = Array(Math.max(0, n));\n    iteratee = optimizeCb(iteratee, context, 1);\n    for (var i = 0; i < n; i++) accum[i] = iteratee(i);\n    return accum;\n  };\n\n  // Return a random integer between min and max (inclusive).\n  _.random = function(min, max) {\n    if (max == null) {\n      max = min;\n      min = 0;\n    }\n    return min + Math.floor(Math.random() * (max - min + 1));\n  };\n\n  // A (possibly faster) way to get the current timestamp as an integer.\n  _.now = Date.now || function() {\n    return new Date().getTime();\n  };\n\n   // List of HTML entities for escaping.\n  var escapeMap = {\n    '&': '&amp;',\n    '<': '&lt;',\n    '>': '&gt;',\n    '\"': '&quot;',\n    \"'\": '&#x27;',\n    '`': '&#x60;'\n  };\n  var unescapeMap = _.invert(escapeMap);\n\n  // Functions for escaping and unescaping strings to/from HTML interpolation.\n  var createEscaper = function(map) {\n    var escaper = function(match) {\n      return map[match];\n    };\n    // Regexes for identifying a key that needs to be escaped\n    var source = '(?:' + _.keys(map).join('|') + ')';\n    var testRegexp = RegExp(source);\n    var replaceRegexp = RegExp(source, 'g');\n    return function(string) {\n      string = string == null ? '' : '' + string;\n      return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;\n    };\n  };\n  _.escape = createEscaper(escapeMap);\n  _.unescape = createEscaper(unescapeMap);\n\n  // If the value of the named `property` is a function then invoke it with the\n  // `object` as context; otherwise, return it.\n  _.result = function(object, property, fallback) {\n    var value = object == null ? void 0 : object[property];\n    if (value === void 0) {\n      value = fallback;\n    }\n    return _.isFunction(value) ? value.call(object) : value;\n  };\n\n  // Generate a unique integer id (unique within the entire client session).\n  // Useful for temporary DOM ids.\n  var idCounter = 0;\n  _.uniqueId = function(prefix) {\n    var id = ++idCounter + '';\n    return prefix ? prefix + id : id;\n  };\n\n  // By default, Underscore uses ERB-style template delimiters, change the\n  // following template settings to use alternative delimiters.\n  _.templateSettings = {\n    evaluate    : /<%([\\s\\S]+?)%>/g,\n    interpolate : /<%=([\\s\\S]+?)%>/g,\n    escape      : /<%-([\\s\\S]+?)%>/g\n  };\n\n  // When customizing `templateSettings`, if you don't want to define an\n  // interpolation, evaluation or escaping regex, we need one that is\n  // guaranteed not to match.\n  var noMatch = /(.)^/;\n\n  // Certain characters need to be escaped so that they can be put into a\n  // string literal.\n  var escapes = {\n    \"'\":      \"'\",\n    '\\\\':     '\\\\',\n    '\\r':     'r',\n    '\\n':     'n',\n    '\\u2028': 'u2028',\n    '\\u2029': 'u2029'\n  };\n\n  var escaper = /\\\\|'|\\r|\\n|\\u2028|\\u2029/g;\n\n  var escapeChar = function(match) {\n    return '\\\\' + escapes[match];\n  };\n\n  // JavaScript micro-templating, similar to John Resig's implementation.\n  // Underscore templating handles arbitrary delimiters, preserves whitespace,\n  // and correctly escapes quotes within interpolated code.\n  // NB: `oldSettings` only exists for backwards compatibility.\n  _.template = function(text, settings, oldSettings) {\n    if (!settings && oldSettings) settings = oldSettings;\n    settings = _.defaults({}, settings, _.templateSettings);\n\n    // Combine delimiters into one regular expression via alternation.\n    var matcher = RegExp([\n      (settings.escape || noMatch).source,\n      (settings.interpolate || noMatch).source,\n      (settings.evaluate || noMatch).source\n    ].join('|') + '|$', 'g');\n\n    // Compile the template source, escaping string literals appropriately.\n    var index = 0;\n    var source = \"__p+='\";\n    text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {\n      source += text.slice(index, offset).replace(escaper, escapeChar);\n      index = offset + match.length;\n\n      if (escape) {\n        source += \"'+\\n((__t=(\" + escape + \"))==null?'':_.escape(__t))+\\n'\";\n      } else if (interpolate) {\n        source += \"'+\\n((__t=(\" + interpolate + \"))==null?'':__t)+\\n'\";\n      } else if (evaluate) {\n        source += \"';\\n\" + evaluate + \"\\n__p+='\";\n      }\n\n      // Adobe VMs need the match returned to produce the correct offest.\n      return match;\n    });\n    source += \"';\\n\";\n\n    // If a variable is not specified, place data values in local scope.\n    if (!settings.variable) source = 'with(obj||{}){\\n' + source + '}\\n';\n\n    source = \"var __t,__p='',__j=Array.prototype.join,\" +\n      \"print=function(){__p+=__j.call(arguments,'');};\\n\" +\n      source + 'return __p;\\n';\n\n    try {\n      var render = new Function(settings.variable || 'obj', '_', source);\n    } catch (e) {\n      e.source = source;\n      throw e;\n    }\n\n    var template = function(data) {\n      return render.call(this, data, _);\n    };\n\n    // Provide the compiled source as a convenience for precompilation.\n    var argument = settings.variable || 'obj';\n    template.source = 'function(' + argument + '){\\n' + source + '}';\n\n    return template;\n  };\n\n  // Add a \"chain\" function. Start chaining a wrapped Underscore object.\n  _.chain = function(obj) {\n    var instance = _(obj);\n    instance._chain = true;\n    return instance;\n  };\n\n  // OOP\n  // ---------------\n  // If Underscore is called as a function, it returns a wrapped object that\n  // can be used OO-style. This wrapper holds altered versions of all the\n  // underscore functions. Wrapped objects may be chained.\n\n  // Helper function to continue chaining intermediate results.\n  var result = function(instance, obj) {\n    return instance._chain ? _(obj).chain() : obj;\n  };\n\n  // Add your own custom functions to the Underscore object.\n  _.mixin = function(obj) {\n    _.each(_.functions(obj), function(name) {\n      var func = _[name] = obj[name];\n      _.prototype[name] = function() {\n        var args = [this._wrapped];\n        push.apply(args, arguments);\n        return result(this, func.apply(_, args));\n      };\n    });\n  };\n\n  // Add all of the Underscore functions to the wrapper object.\n  _.mixin(_);\n\n  // Add all mutator Array functions to the wrapper.\n  _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      var obj = this._wrapped;\n      method.apply(obj, arguments);\n      if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];\n      return result(this, obj);\n    };\n  });\n\n  // Add all accessor Array functions to the wrapper.\n  _.each(['concat', 'join', 'slice'], function(name) {\n    var method = ArrayProto[name];\n    _.prototype[name] = function() {\n      return result(this, method.apply(this._wrapped, arguments));\n    };\n  });\n\n  // Extracts the result from a wrapped and chained object.\n  _.prototype.value = function() {\n    return this._wrapped;\n  };\n\n  // Provide unwrapping proxy for some methods used in engine operations\n  // such as arithmetic and JSON stringification.\n  _.prototype.valueOf = _.prototype.toJSON = _.prototype.value;\n\n  _.prototype.toString = function() {\n    return '' + this._wrapped;\n  };\n\n  // AMD registration happens at the end for compatibility with AMD loaders\n  // that may not enforce next-turn semantics on modules. Even though general\n  // practice for AMD registration is to be anonymous, underscore registers\n  // as a named module because, like jQuery, it is a base library that is\n  // popular enough to be bundled in a third party lib, but not be part of\n  // an AMD load request. Those cases could generate an error when an\n  // anonymous define() is called outside of a loader request.\n  if (typeof define === 'function' && define.amd) {\n    define('underscore', [], function() {\n      return _;\n    });\n  }\n}.call(this));\n"
  },
  {
    "path": "main.js",
    "content": "/*** Z-Way Home Automation Engine main executable *****************************\n\nVersion: 0.1.2\n(c) ZWave.Me, 2013\n\n-------------------------------------------------------------------------------\nAuthor: Gregory Sitnin <sitnin@z-wave.me>\n\nDescription:\n  This is a main executable script which is loaded and executed solely\n  by the z-way-server daemon. The very magic starts here.\n\n******************************************************************************/\n\n//--- Define global variables and helpers\n\nvar window = global = this;\n\n// load utilities\nexecuteFile(\"Utils.js\");\n\n// do transition script to adopt old versions to new\nexecuteFile(\"updateBackendConfig.js\");\n\n// overload saveObject to allow backup/restore of all JSON files in storage\n__saveObject = saveObject;\n__saveObjectTimer = {};\n__storageContent = loadObject(\"__storageContent\") || [];\n\n// check against storage if listed files really exists\n__storageContent = __storageContent.filter(function(name) {\n\ttry {\n\t\treturn !!loadObject(name);\n\t} catch (e) {\n\t\tconsole.log(\"Error loading \" + name + \" from storage: JSON file corrupted: \" + e.toString());\n\t\treturn false;\n\t}\n});\n\n// Saves object as name, adds name to the storageContent.\n// Defer save: immediate can be undefined (to use default seconds), true or 0 (save now), integer (to defer by N seconds)\nsaveObject = function(name, object, immediate) {\n\t// defer tests\n\t\n\tvar deferTime;\n\t\n\tif (immediate === true || immediate === 0) {\n\t\tdeferTime = 0;\n\t} else if (immediate > 0) {\n\t\tdeferTime = immediate;\n\t} else {\n\t\tdeferTime = 5 * 60;\n\t}\n\tdeferTime *= 1000;\n\t\n\tif (!__saveObjectTimer[name]) {\n\t\t__saveObjectTimer[name] = {\n\t\t\ttimer: null,\n\t\t\tlastSave: 0\n\t\t};\n\t}\n\t\n\tif (__saveObjectTimer[name].timer) {\n\t\tclearTimeout(__saveObjectTimer[name].timer);\n\t\t__saveObjectTimer[name].timer = null;\n\t}\n\t\n\tdeferTime -= Date.now() - __saveObjectTimer[name].lastSave;\n\tif (deferTime > 0) {\n\t\t// restart the time with the new object and remaining time\n\t\t__saveObjectTimer[name].object = object;\n\t\t__saveObjectTimer[name].saver = function() {\n\t\t\t__saveObjectTimer[name].timer = null;\n\t\t\t__saveObjectTimer[name].saver = null;\n\t\t\tsaveObject(name, __saveObjectTimer[name].object, true); // call itself\n\t\t};\n\t\t__saveObjectTimer[name].timer = setTimeout(__saveObjectTimer[name].saver, deferTime);\n\t\t\n\t\treturn; // defer save\n\t}\n\t\n\t__saveObjectTimer[name].lastSave = Date.now();\n\t\n\t// add entry to __storageContent if it does not already exist\n\tif (__storageContent.indexOf(name) === -1 && !!name) {\n\t\t__storageContent.push(name);\n\t\t__saveObject(\"__storageContent\", __storageContent);\n\n\t// remove entry from __storageContent if deleted\n\t} else if (!!name && object === null) {\n\t\t__storageContent = _.filter(__storageContent, function(fileName){\n\t\t\treturn fileName !== name;\n\t\t});\n\t\t__saveObject(\"__storageContent\", __storageContent);\n\t}\n\n\t__saveObject(name, object);\n};\n\nfunction __saveObjectsNow() {\n\tfor (var name in __saveObjectTimer) {\n\t\tif (__saveObjectTimer[name].timer != null && __saveObjectTimer[name].saver != null)\n\t\t{\n\t\t\tclearTimeout(__saveObjectTimer[name].timer);\n\t\t\t__saveObjectTimer[name].timer = null;\n\t\t\t__saveObjectTimer[name].saver();\n\t\t\t__saveObjectTimer[name].saver = null;\n\t\t}\n\t}\n}\n\n//--- Load configuration\nvar config, files, templates, schemas, modules, namespaces;\ntry {\n\tconfig = loadObject(\"config.json\");\n\tfiles = loadObject(\"files.json\") || {};\n\tschemas = loadObject(\"schemas.json\") || [];\n} catch (ex) {\n\tconsole.log(\"Error loading config.json or files.json:\", ex.message);\n}\n\nif (!config && config === null) {\n\tconsole.log(\"Can't read config.json or it's broken.\");\n\tconsole.log(\"ZAutomation engine not started.\");\n} else {\n\tconfig.libPath = \"lib\";\n\tconfig.classesPath = \"classes\";\n\tconfig.resourcesPath = \"res\";\n\n\t// add modules_categories\n\tconfig.modules_categories = fs.loadJSON(\"modulesCategories.json\");\n\n\t//--- Load 3d-party dependencies\n\texecuteFile(config.libPath + \"/eventemitter2.js\");\n\t// executeFile(config.libPath + \"/underscore.js\");\n\texecuteFile(config.libPath + \"/underscore-umd-min.js\");\n\texecuteFile(config.libPath + \"/papaparse.min.js\");\n\texecuteFile(config.libPath + \"/zlib_and_gzip.min.js\"); // TODO Test!\n\texecuteFile(config.libPath + \"/BAOS_API_2011_01_29_001.js\");\n\texecuteFile(config.libPath + \"/IntelHex2bin.js\");\n\texecuteFile(config.libPath + \"/base64.js\");\n\texecuteFile(config.libPath + \"/LimitedArray.js\");\n\t//--- Load Automation subsystem classes\n\texecuteFile(config.classesPath + \"/VirtualDevice.js\");\n\texecuteFile(config.classesPath + \"/DevicesCollection.js\");\n\texecuteFile(config.classesPath + \"/AutomationController.js\");\n\texecuteFile(config.classesPath + \"/AuthController.js\");\n\texecuteFile(config.classesPath + \"/AutomationModule.js\");\n\texecuteFile(\"Webserver.js\");\n\texecuteFile(\"WebserverRequestRouter.js\");\n\texecuteFile(\"ZAutomationAPIProvider.js\");\n\texecuteFile(\"StorageProvider.js\");\n\n\t//--- Instantiate Automation Controller\n\n\tvar api = null,\n\t\tstorage = null,\n\t\tcontroller = new AutomationController(config),\n\t\tnow = new Date();\n\n\tcontroller.on('core.init', function () {\n\t\tconsole.log('Starting ZWay Automation webserver');\n\t\t// first start up\n\t\tconfig.controller.first_start_up = !config.controller.first_start_up? now : config.controller.first_start_up;\n\t\t// count server restarts\n\t\tconfig.controller.count_of_reconnects = config.controller.count_of_reconnects? parseInt(config.controller.count_of_reconnects, 10) + 1 : 1;\n\t\t\n\t\t// generate the uuid\n\t\tif (!config.controller.uuid) config.controller.uuid = crypto.guid();\n\t\tif (!config.controller.serial) config.controller.serial = config.controller.uuid;\n\t});\n\n\tcontroller.on('core.start', function () {\n\t\tconsole.log('ZWay Automation started');\n\t});\n\n\tcontroller.on('core.stop', function () {\n\t\t__saveObjectsNow()\n\t\tconsole.log('ZWay Automation stopped');\n\t});\n\n\tcontroller.on('core.error', function (err) {\n\t\tconsole.log(\"--- ERROR:\", err.message);\n\t\tcontroller.addNotification(\"error\", err.message, \"core\", \"core controller\");\n\t});\n\n\t//--- main\n\tcontroller.init();\n\tcontroller.start();\n\n\t//--- Init JS handler for Admin\n\n\tJS = function() {\n\t\treturn { status: 400, body: \"Bad JS request\" };\n\t};\n\tws.allowExternalAccess(\"JS\", controller.auth.ROLE.ADMIN);\n\n\tJS.Run = function(url) {\n\t\t\t// skip trailing slash\n\t\turl = url.substring(1);\n\t\ttry {\n\t\t\tvar r = eval(url);\n\t\t\tif (typeof r === \"function\") {\n\t\t\t\t// special case for functions, otherwise they show up as JSON 'null'\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 204,\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t\t},\n\t\t\t\t\tbody: JSON.stringify(r)\n\t\t\t};\n\t\t} catch (e) {\n\t\t\tconsole.log(\"Error handling request \" + url + \": \" + e.toString());\n\t\t\treturn { status: 500, body: e.toString() };\n\t\t}\n\t};\n\tws.allowExternalAccess(\"JS.Run\", controller.auth.ROLE.ADMIN);\n\n\t// overwrite console.debug function\n\tconsole.debug = function(){\n\t\tvar arr = [];\n\n\t\t// use JS API /JS/Run/controller.debug=true / false to activate debug output\n\t\tif (controller.debug){\n\t\t\tfor (var key in arguments) {\n\t\t\t\tvar arg = '';\n\n\t\t\t\t//format objects automatically\n\t\t\t\tif (typeof arguments[key] === 'object' && !!arguments[key]) {\n\t\t\t\t\targ = JSON.stringify(arguments[key], null, 4);\n\t\t\t\t} else {\n\t\t\t\t\targ = arguments[key];\n\t\t\t\t}\n\t\t\t\tarr.push(arg);\n\t\t\t}\n\n\t\t\tdebugPrint(arr);\n\t\t}\n\t};\n}\n"
  },
  {
    "path": "modules/Alexa/index.js",
    "content": "/*** Alexa Z-Way HA module *******************************************\n\n Version: 1.1.0\n (c) Z-Wave.Me, 2016\n -----------------------------------------------------------------------------\n Author: Michael Hensche <mh@zwave.eu>\n Description: Supports Alexa SmartHome Skill API version 2\n\n ******************************************************************************/\n\nfunction Alexa (id, controller) {\n    // Call superconstructor first (AutomationModule)\n    Alexa.super_.call(this, id, controller);\n\n    // namespaces\n    this.NAMESPACE_CONTROL = \"Alexa.ConnectedHome.Control\";\n    this.NAMESPACE_DISCOVERY = \"Alexa.ConnectedHome.Discovery\";\n    this.NAMESPACE_QUERY = \"Alexa.ConnectedHome.Query\";\n\n    // discovery\n    this.REQUEST_DISCOVER = \"DiscoverAppliancesRequest\";\n    this.RESPONSE_DISCOVER = \"DiscoverAppliancesResponse\";\n\n    // control\n    this.REQUEST_TURN_ON = \"TurnOnRequest\";\n    this.RESPONSE_TURN_ON = \"TurnOnConfirmation\";\n    this.REQUEST_TURN_OFF = \"TurnOffRequest\";\n    this.RESPONSE_TURN_OFF = \"TurnOffConfirmation\";\n    this.REQUEST_SET_PERCENTAGE = \"SetPercentageRequest\";\n    this.RESPONSE_SET_PERCENTAGE = \"SetPercentageConfirmation\";\n    this.REQUEST_INCREMENT_PERCENTAGE = \"IncrementPercentageRequest\";\n    this.RESPONSE_INCREMENT_PERCENTAGE = \"IncrementPercentageConfirmation\";\n    this.REQUEST_DECREMENT_PERCENTAGE = \"DecrementPercentageRequest\";\n    this.RESPONSE_DECREMENT_PERCENTAGE = \"DecrementPercentageConfirmation\";\n    this.REQUEST_SET_TARGET_TEMPERATURE = \"SetTargetTemperatureRequest\";\n    this.RESPONSE_SET_TARGET_TEMPERATURE = \"SetTargetTemperatureConfirmation\";\n    this.REQUEST_INCREMENT_TARGET_TEMPERATURE = \"IncrementTargetTemperatureRequest\";\n    this.RESPONSE_INCREMENT_TARGET_TEMPERATURE = \"IncrementTargetTemperatureConfirmation\";\n    this.REQUEST_DECREMENT_TARGET_TEMPERATURE = \"DecrementTargetTemperatureRequest\";\n    this.RESPONSE_DECREMENT_TARGET_TEMPERATURE = \"DecrementTargetTemperatureConfirmation\";\n    this.REQUEST_SET_LOCK_STATE = \"SetLockStateRequest\";\n    this.RESPONSE_SET_LOCK_STATE = \"SetLockStateConfirmation\";\n    this.REQUEST_SET_COLOR = \"SetColorRequest\";\n    this.RESPONSE_SET_COLOR = \"SetColorConfirmation\";\n\n    // query\n    this.REQUEST_LOCK_STATE = \"GetLockStateRequest\";\n    this.RESPONSE_GET_LOCK_STATE = \"GetLockStateResponse\";\n    this.REQUEST_TARGET_TEMPERATURE = \"GetTargetTemperatureRequest\";\n    this.RESPONSE_TARGET_TEMPERATURE = \"GetTargetTemperatureResponse\";\n    this.REQUEST_TARGET_READING_TEMPERATURE = \"GetTemperatureReadingRequest\";\n    this.RESPONSE_TARGET_READING_TEMPERATURE = \"GetTemperatureReadingResponse\";\n\n    // errors\n    this.ERROR_UNSUPPORTED_OPERATION = \"UnsupportedOperationError\";\n    this.ERROR_UNEXPECTED_INFO = \"UnexpectedInformationReceivedError\";\n    this.ERROR_NO_SUCH_TARGET = \"NoSuchTargetError\";\n    this.ERROR_TARGET_OFFLINE = \"TargetOfflineError\";\n    this.ERROR_VALUE_OUT_OF_RANGE = \"ValueOutOfRangeError\"; \n\n\n    this.whiteListDeviceType = [{\"sensorMultilevel\":[\"temperature\"]}, {\"switchBinary\":[]}, {\"toggleButton\":[]}, {\"switchMultilevel\":[]}, {\"thermostat\":[]}, {\"doorlock\":[]}];\n}\n\ninherits(Alexa, AutomationModule);\n\n_module = Alexa;\n\nAlexa.prototype.init = function(config) {\n    var self = this;\n\n    Alexa.super_.prototype.init.call(this, config);\n\n    this.defineHandlers();\n    this.externalAPIAllow();\n    global[\"AlexaAPI\"] = this.AlexaAPI;\n};\n\nAlexa.prototype.stop = function() {\n    var self = this;\n\n    delete global[\"AlexaAPI\"];\n\n    Alexa.super_.prototype.stop.call(this);\n};\n\nAlexa.prototype.handleDiscovery = function(event) {\n    var self = this,\n        appliances = self.buildAppliances(),\n        header = self.createHeader(self.NAMESPACE_DISCOVERY, self.RESPONSE_DISCOVER),\n        payload = {\n            \"discoveredAppliances\": appliances\n        };\n\n    return self.createDirective(header, payload);\n};\n\nAlexa.prototype.handleControl = function(event) {\n    var self = this,\n        response = null,\n        requestedName = event.header.name;\n\n    switch (requestedName) {\n        case self.REQUEST_TURN_ON :\n            response = self.handleControlTurnOn(event);\n            break;\n        case self.REQUEST_TURN_OFF :\n            response = self.handleControlTurnOff(event);\n            break;\n        case self.REQUEST_SET_PERCENTAGE :\n            response = self.handleControlSetPercentage(event);\n            break;\n        case self.REQUEST_INCREMENT_PERCENTAGE :\n            response = self.handleControlIncrementPercentage(event);\n            break;\n        case self.REQUEST_DECREMENT_PERCENTAGE :\n            response = self.handleControlDecrementPercentage(event);\n            break;\n        case self.REQUEST_SET_TARGET_TEMPERATURE :\n            response = self.handleControlSetTargetTemperature(event);\n            break;\n        case self.REQUEST_INCREMENT_TARGET_TEMPERATURE :\n            response = self.handleControlIncrementTargetTemperature(event);\n            break;\n        case self.REQUEST_DECREMENT_TARGET_TEMPERATURE :\n            response = self.handleControlDecrementTargetTemperature(event);\n            break;\n        case self.REQUEST_SET_LOCK_STATE :\n            response = self.handleControlSetLockState(event);\n            break;\n        case self.REQUEST_SET_COLOR:\n            response = self.handleControlSetColor(event);\n            break;\n        default:\n            console.log(\"Error\", \"Unsupported operation\" + requestedName);\n            response = self.handleUnsupportedOperation();\n            break;\n    }\n    return response;\n};\n\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"TurnOnRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"TurnOnConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {}\n   * }\n   */\nAlexa.prototype.handleControlTurnOn = function(event) {\n     var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_TURN_ON);\n        vDev.performCommand(\"on\");    \n    }\n        \n    return self.createDirective(header, {});\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"TurnOffRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"TurnOffConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {}\n   * }\n   */\nAlexa.prototype.handleControlTurnOff = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {};\n   \n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_TURN_OFF)\n        vDev.performCommand(\"off\");    \n    }\n\n    return self.createDirective(header, {});\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"SetPercentageRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"percentageState\": {\n   *            \"value\": 50.0\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"SetPercentageConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {}\n   * }\n   */\nAlexa.prototype.handleControlSetPercentage = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_SET_PERCENTAGE);\n        var level = event.payload.percentageState.value;\n        vDev.performCommand(\"exact\", {level: level});\n    }\n\n    return self.createDirective(header, {});\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"IncrementPercentageRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"deltaPercentage\": {\n   *            \"value\": 10.0\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"IncrementPercentageConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {}\n   * }\n   */\nAlexa.prototype.handleControlIncrementPercentage = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        maxLevel = 99,\n        minLevel = 0,\n        newLevel = 0,\n        delta = event.payload.deltaPercentage.value,\n        response = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_INCREMENT_PERCENTAGE);\n        var curLevel = vDev.get(\"metrics:level\");\n        if(curLevel + delta <= maxLevel) {\n            newLevel = curLevel + delta;\n        } else {\n            newLevel = maxLevel;\n        }\n\n        vDev.performCommand(\"exact\", {level: newLevel});\n    }\n\n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"DecrementPercentageRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"deltaPercentage\": {\n   *            \"value\": 10.0\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"DecrementPercentageConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {}\n   * }\n   */\nAlexa.prototype.handleControlDecrementPercentage = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        minLevel = 0,\n        newLevel = 0,\n        delta = event.payload.deltaPercentage.value;\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_DECREMENT_PERCENTAGE);\n        var curLevel = vDev.get(\"metrics:level\");\n\n        if(curLevel - delta >= minLevel) {\n            newLevel = curLevel - delta;\n        } else {\n            newLevel = minLevel;\n        }\n\n        vDev.performCommand(\"exact\", {level: newLevel});\n    }\n\n    return self.createDirective(header, {});\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"SetTargetTemperatureRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"targetTemperature\": {\n   *            \"value\": 25.0\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"SetTargetTemperatureConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"targetTemperature\": {\n   *             \"value\": 25.0   \n   *         },\n   *         \"temperatureMode\": {\n   *             \"value\" \"AUTO\"\n   *         },\n   *         \"previousState\": {\n   *             \"targetTemperature\": {\n   *                 \"value\": 21.0\n   *             },\n   *             \"mode\": {\n   *                 \"value\": \"AUTO\"\n   *             }   \n   *         }\n   *     }\n   * }\n   */\nAlexa.prototype.handleControlSetTargetTemperature = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        temperature = event.payload.targetTemperature.value,\n        response = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n      var maxTemp = vDev.get(\"metrics:max\"),\n          minTemp = vDev.get(\"metrics:min\"),\n          prevTemp = vDev.get(\"metrics:level\");\n\n      if (temperature < minTemp || temperature > maxTemp) {\n          header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_VALUE_OUT_OF_RANGE);\n          response = {\n              \"minimumValue\": minTemp,\n              \"maximumValue\": maxTemp\n          };\n      } else {\n          header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_SET_TARGET_TEMPERATURE);\n          vDev.performCommand(\"exact\", {level: temperature});\n\n          response = {\n              \"targetTemperature\": {\n                  \"value\": temperature\n              },\n              \"temperatureMode\": {\n                  \"value\": \"AUTO\"\n              },\n              \"previousState\": {\n                  \"targetTemperature\": {\n                      \"value\": prevTemp\n                  },\n                  \"mode\": {\n                      \"value\": \"AUTO\"\n                  }\n              }\n          };\n      }\n    }\n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"IncrementTargetTemperatureRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"deltaTemperature\": {\n   *            \"value\": 3.6\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"IncrementTargetTemperatureConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"previousState\": {\n   *             \"targetTemperature\": {\n   *                 \"value\": 21.0\n   *             },\n   *             \"mode\": {\n   *                 \"value\": \"AUTO\"\n   *             }   \n   *         }\n   *         \"targetTemperature\": {\n   *             \"value\": 24.6   \n   *         },\n   *         \"temperatureMode\": {\n   *             \"value\" \"AUTO\"\n   *         }\n   *     }\n   * }\n   */\nAlexa.prototype.handleControlIncrementTargetTemperature = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        newTemp = 0,\n        temperature = event.payload.deltaTemperature.value,\n        response = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n      var maxTemp = vDev.get(\"metrics:max\"),\n          minTemp = vDev.get(\"metrics:min\"),\n          curTemp = vDev.get(\"metrics:level\");\n\n      if(curTemp + temperature > maxTemp) {\n          header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_VALUE_OUT_OF_RANGE);\n          response = {\n              \"minimumValue\": minTemp,\n              \"maximumValue\": maxTemp\n          };\n      } else {\n          header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_INCREMENT_TARGET_TEMPERATURE)\n          \n          newTemp = curTemp + temperature;\n\n          vDev.performCommand(\"exact\", {level: newTemp});\n\n          response = {\n              \"previousState\": {\n                  \"mode\": {\n                      \"value\": \"AUTO\"\n                  },\n                  \"targetTemperature\": {\n                      \"value\": curTemp\n                  }\n              },\n              \"targetTemperature\": {\n                  \"value\": newTemp\n              },\n              \"temperatureMode\": {\n                  \"value\": \"AUTO\"\n              }\n          };\n      }\n    }\n\n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"DecrementTargetTemperatureRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"deltaTemperature\": {\n   *            \"value\": 2\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"DecrementTargetTemperatureConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"previousState\": {\n   *             \"targetTemperature\": {\n   *                 \"value\": 23.0\n   *             },\n   *             \"mode\": {\n   *                 \"value\": \"AUTO\"\n   *             }   \n   *         }\n   *         \"targetTemperature\": {\n   *             \"value\": 21.0   \n   *         },\n   *         \"temperatureMode\": {\n   *             \"value\" \"AUTO\"\n   *         }\n   *     }\n   * }\n   */\nAlexa.prototype.handleControlDecrementTargetTemperature = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        newTemp = 0,\n        temperature = event.payload.deltaTemperature.value,\n        response = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n      var minTemp = vDev.get(\"metrics:min\"),\n          maxTemp = vDev.get(\"metrics:max\"),\n          curTemp = vDev.get(\"metrics:level\");\n\n      if(curTemp - temperature < minTemp) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_VALUE_OUT_OF_RANGE);\n        response = {\n            \"minimumValue\": minTemp,\n            \"maximumValue\": maxTemp\n        };\n      } else {\n\n        newTemp = curTemp - temperature;\n\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_DECREMENT_TARGET_TEMPERATURE);\n        vDev.performCommand(\"exact\", {level: newTemp});\n\n        response = {\n            \"previousState\": {\n                \"mode\": {\n                    \"value\": \"AUTO\"\n                },\n                \"targetTemperature\": {\n                    \"value\": curTemp\n                }\n            },\n            \"targetTemperature\": {\n                \"value\": newTemp\n            },\n            \"temperatureMode\": {\n                \"value\": \"AUTO\"\n            }\n        };\n      }\n    }\n    \n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"SetLockStateRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"lockState\": \"LOCKED\"\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"SetLockStateConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"lockState\": \"LOCKED\"\n   *     }\n   * }\n   */\nAlexa.prototype.handleControlSetLockState = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        lockState = event.payload.targetTemperature;\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_SET_LOCK_STATE)\n        var newLevel = lockState == \"LOCKED\" ? \"close\" : \"open\";\n\n        vDev.performCommand(\"exact\", {level: newLevel});\n\n        var response = {\n            \"lockState\": lockState\n        };\n    }\n\n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"SetColorRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        },\n   *        \"color\": {\n   *            \"hue\": 0.0,\n   *            \"saturation\": 1.0000,\n   *            \"brightness\": 1.0000\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"SetColorConfirmation\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"achievedState\": {\n   *             \"color\": {\n   *                \"hue\": 0.0,\n   *                \"saturation\": 1.0000,\n   *                \"brightness\": 1.0000\n   *            }\n   *         }\n   *     }\n   * }\n   */\nAlexa.prototype.handleControlSetColor = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        response = {},\n        hue = event.payload.color.hue,\n        saturation = event.payload.color.saturation,\n        brightness = event.payload.color.brightness,\n        color = hsvToRgb(hue, saturation, brightness);\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        var header = self.createHeader(self.NAMESPACE_CONTROL, self.RESPONSE_SET_COLOR);\n        response = {\n            \"achievedState\": {\n              \"color\": {\n                \"hue\": hue,\n                    \"saturation\": saturation,\n                    \"brightness\": brightness\n                }\n            }\n        }\n        vDev.performCommand(\"exact\", {red: color.r, green: color.g, blue: color.b});\n    }\n\n    return self.createDirective(header, response);\n}   \n\nAlexa.prototype.handleQuery = function(event) {\n    var self = this,\n        response = null,\n        requestedName = event.header.name;\n\n    //console.log(\"Handle Query: \", JSON.stringify(event));\n\n    switch (requestedName) {\n        case self.REQUEST_LOCK_STATE :\n            response = self.handleQueryLockState(event);\n            break;\n        case self.REQUEST_TARGET_TEMPERATURE :\n            response = self.handleQueryTargetTemperature(event);\n            break;\n        case self.REQUEST_TARGET_READING_TEMPERATURE :\n            response = self.handleQueryTargetReadingTemperature(event);\n            break;\n        default:\n            console.log(\"Error\", \"Unsupported operation\" + requestedName);\n            response = self.handleUnsupportedOperation();\n            break;\n    }\n    return response;\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"GetLockStateRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"GetLockStateResponse\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"lockSate\": \"LOCKED\",\n   *         \"applianceResponseTimestamp\": \"2017-01-12T23:20:50.52Z\"\n   *     }\n   * }\n   */\nAlexa.prototype.handleQueryLockState = function(event) {\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        response = {};\n\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        var curLevel = vDev.get(\"metrics:level\"),\n            updateTime = new Date(vDev.get(\"updateTime\") * 1000),\n            lockState = curLevel == \"open\" ? \"UNLOCKED\" : \"LOCKED\";\n        \n        header = self.createHeader(self.NAMESPACE_QUERY, self.RESPONSE_GET_LOCK_STATE);\n        \n        response = {\n            \"lockState\": lockState,\n            \"applianceResponseTimestamp\": self.ISODateString(updateTime)\n        };\n    }\n\n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"GetTargetTemperatureRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"GetTargetTemperatureResponse \",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"targetTemperature\": {\n   *             \"value\": 23.00,\n   *             \"scale\": \"CELSIUS\"\n   *         },\n   *         \"applianceResponseTimestamp\": \"2017-01-12T23:20:50.52Z\",\n   *         \"temperatureMode\": {\n   *             \"value\": \"HEAT\",\n   *             \"friendlyName\": \"\"\n   *         }\n   *     }\n   * }\n   */\nAlexa.prototype.handleQueryTargetTemperature = function(event){\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        response = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        var curTemp = Math.round(vDev.get(\"metrics:level\")),\n            updateTime = new Date(vDev.get(\"updateTime\") * 1000);\n        \n        header = self.createHeader(self.NAMESPACE_QUERY, self.RESPONSE_TARGET_TEMPERATURE),\n\n        response = {\n            \"targetTemperature\": {\n                \"value\": curTemp,\n                \"scale\": \"CELSIUS\"\n            },\n            \"applianceResponseTimestamp\": self.ISODateString(updateTime),\n            \"temperatureMode\": {\n                \"value\": \"AUTO\",\n                \"friendlyName\": \"\"\n            }\n        };\n    }\n\n    return self.createDirective(header, response);\n};\n\n/**\n   *\n   * @param event\n   * {\n   *  \"header\": {\n   *       \"messageId\": \"01ebf625-0b89-4c4d-b3aa-32340e894688\",\n   *        \"name\": \"GetTemperatureReadingRequest\",\n   *        \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *        \"payloadVersion\": \"2\"\n   *  },\n   *  \"payload\": {\n   *        \"accessToken\": \"[OAuth token here]\",\n   *        \"appliance\": {\n   *            \"additionalApplianceDetails\": {\n   *                {\"device\": \"[Z-Way Device ID]\"}\n   *            },\n   *            \"applianceId\": \"[Device ID]\"\n   *        }\n   *    }\n   * }\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"GetTemperatureReadingResponse \",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"temperatureReading\": {\n   *             \"value\": 23.00,\n   *             \"scale\": \"CELSIUS\"\n   *         },\n   *         \"applianceResponseTimestamp\": \"2017-01-12T23:20:50.52Z\"\n   *     }\n   * }\n   */\nAlexa.prototype.handleQueryTargetReadingTemperature = function(event){\n    var self = this,\n        vDev = self.getvDev(event.payload.appliance.additionalApplianceDetails.device),\n        header = {},\n        response = {};\n\n    if(!vDev) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_NO_SUCH_TARGET);\n    } else if(vDev.get(\"metrics:isFailed\")) {\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_TARGET_OFFLINE);\n    } else {\n        var curTemp = Math.round(vDev.get(\"metrics:level\")),\n            updateTime = new Date(vDev.get(\"updateTime\") * 1000);\n\n        header = self.createHeader(self.NAMESPACE_QUERY, self.RESPONSE_TARGET_READING_TEMPERATURE)\n        \n        response = {\n            \"temperatureReading\": {\n                \"value\": curTemp,\n                \"scale\": \"CELSIUS\"\n            },\n            \"applianceResponseTimestamp\": self.ISODateString(updateTime)\n        };\n    }\n\n    return self.createDirective(header, response);\n};\n\n\n/**\n   *\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"UnsupportedOperationError\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {}\n   * }\n   */\nAlexa.prototype.handleUnsupportedOperation = function() {\n    var self = this,\n        header = self.createHeader(self.NAMESPACE_CONTROL, self.ERROR_UNSUPPORTED_OPERATION);\n    return self.createDirective(header, {});\n};\n\n\n/**\n   * @param fault\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"UnexpectedInformationReceivedError\",\n   *         \"namespace\": \"Alexa.ConnectedHome.Control\",\n   *         \"payloadVersion\": \"2\"\n   *     },\n   *     \"payload\": {\n   *         \"faultingParameter\": \"[FAULT]\"\n   *     }\n   * }\n   */\nAlexa.prototype.handleUnexpectedInfo = function(fault) {\n    var self = this,\n        header = self.createHeader(NAMESPACE_CONTROL, ERROR_UNEXPECTED_INFO);\n\n    var payload = {\n        \"faultingParameter\" : fault\n    };\n\n    return createDirective(header,payload);\n};\n\nAlexa.prototype.getvDev = function(deviceId) {\n    var self = this,\n        vDev = self.controller.devices.get(deviceId);\n\n    return vDev;\n};\n\n/**\n   * @param namespace\n   * @param name\n   * @return {{}}\n   * {\n   *     \n   *         \"messageId\": \"26fa11a8-accb-4f66-a272-8b1ff7abd722\",\n   *         \"name\": \"[name]\",\n   *         \"namespace\": \"[namespace]\",\n   *         \"payloadVersion\": \"2\"\n   *     \n   * }\n   */\nAlexa.prototype.createHeader = function(namespace, name) {\n    var self = this;\n    return {\n        \"messageId\": self.createMessageId(),\n        \"namespace\": namespace,\n        \"name\": name,\n        \"payloadVersion\": \"2\"\n    };\n};\n\n/**\n   * @param header\n   * @param payload\n   * @return {{}}\n   * {\n   *     \"header\": {\n   *         [\"header\"]\n   *     },\n   *     \"payload\": {\n   *         [\"payload\"]\n   *     }\n   * }\n   */\nAlexa.prototype.createDirective = function(header, payload) {\n    return {\n        \"header\" : header,\n        \"payload\" : payload\n    };\n};\n\nAlexa.prototype.buildAppliances = function() {\n    var self = this,\n        devices = self.controller.devices,\n        locations = self.controller.locations,\n        moduleName = \"Alexa\",\n        langFile = self.controller.loadModuleLang(moduleName),\n        instances = self.controller.instances,\n        active_devices = self.config.devices.map(function(dev) {return dev.id}); \n\n    var appliances = devices.filter(function(device) {\n        var vDev = self.controller.devices.get(device.id),\n            pos = active_devices.indexOf(device.id);\n        \n        if(pos != -1) {\n            return vDev;\n        }\n    }).map(function(vDev) {\n        var appliance = {\n            \"applianceId\": \"\",\n            \"friendlyDescription\": \"undefined\",\n            \"friendlyName\": \"undefined\",\n            \"isReachable\": true,\n            \"manufacturerName\": \"undefined\",\n            \"modelName\": \"undefined\",\n            \"version\": \"undefined\",\n            \"additionalApplianceDetails\": {},\n            \"actions\": [],\n            \"applianceTypes\": []\n        };\n\n        switch(vDev.get(\"deviceType\")) {\n            case \"switchBinary\":\n                appliance.actions.push(\"turnOn\", \"turnOff\");\n                break;\n            case \"switchMultilevel\":\n                appliance.actions.push(\"turnOn\", \"turnOff\", \"setPercentage\", \"incrementPercentage\", \"decrementPercentage\");\n                break;\n            case \"sensorMultilevel\":\n                appliance.actions.push(\"getTargetTemperature\", \"getTemperatureReading\");\n                break;\n            case \"toggleButton\":\n                appliance.actions.push(\"turnOn\");\n                var scene = _.find(instances, function(inst) {\n                   return inst.id == vDev.get(\"creatorId\") && inst.moduleId == \"LightScene\";\n                });\n                if(typeof scene !== 'undefined') {appliance.applianceTypes.push(\"SCENE_TRIGGER\");}\n                break;\n            case \"thermostat\":\n                appliance.actions.push(\"setTargetTemperature\", \"incrementTargetTemperature\", \"decrementTargetTemperature\", \"getTargetTemperature\", \"getTemperatureReading\");\n                appliance.applianceTypes.push(\"THERMOSTAT\");\n                break;\n            case \"doorlock\":\n                appliance.actions.push(\"getLockState\", \"setLockState\");\n                appliance.applianceTypes.push(\"SMARTLOCK\");\n                break;\n            case \"switchRGBW\":\n                appliance.actions.push(\"setColor\", \"turnOff\", \"turnOn\");\n                appliance.applianceTypes.push(\"LIGHT\");\n                break;\n        }\n\n        appliance.applianceId = vDev.id.replace(/[^\\w_\\-=#;:?@&]/g, '_'); // replace not allowed characters\n        appliance.friendlyDescription;\n\n        var pos = active_devices.indexOf(vDev.id),\n            locationId = vDev.get(\"location\");\n        if(pos !== -1) {\n            var deviceName = self.config.devices[pos].callName;\n        } else {\n            // fallback if no call name set\n            var deviceName = vDev.get(\"metrics:title\") == \"\" ? \"Unknow device\" : vDev.get(\"metrics:title\");\n        }\n\n        if(locationId !== 0 && self.config.assign_room) {\n            var location = _.find(locations, function(location) {\n               return location.id === locationId;\n            });\n            var room = location.title;\n            friendlyName = deviceName + \" \" + room;\n            appliance.friendlyDescription = deviceName + \" \" + room + \" connected via Z-Way\";\n        } else {\n            friendlyName = deviceName;\n            appliance.friendlyDescription = deviceName + \" connected via Z-Way\";\n        }\n\n        appliance.friendlyName = friendlyName;\n        appliance.modelName = vDev.get(\"deviceType\");\n        appliance.additionalApplianceDetails = {\"device\": vDev.id};\n        return appliance;\n    }, active_devices);\n    \n    return appliances;\n};\n\nAlexa.prototype.createMessageId = function() {\n    var d = Date.now();\n\n    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n        var r = (d + Math.random()*16)%16 | 0;\n        d = Math.floor(d/16);\n        return (c=='x' ? r : (r&0x3|0x8)).toString(16);\n    });\n\n    return uuid;\n};\n\nAlexa.prototype.ISODateString = function (d) {\n    function pad(n) {return n<10 ? '0'+n : n}\n    return d.getUTCFullYear()+'-'\n        + pad(d.getUTCMonth()+1)+'-'\n        + pad(d.getUTCDate())+'T'\n        + pad(d.getUTCHours())+':'\n        + pad(d.getUTCMinutes())+':'\n        + pad(d.getUTCSeconds())+'Z';\n};\n\n// --------------- Public HTTP API -------------------\n\n\nAlexa.prototype.externalAPIAllow = function (name) {\n    var _name = !!name ? (\"Alexa.\" + name) : \"AlexaAPI\";\n\n    ws.allowExternalAccess(_name, this.controller.auth.ROLE.USER);\n    ws.allowExternalAccess(_name + \".callActions\", this.controller.auth.ROLE.USER);\n};\n\nAlexa.prototype.externalAPIRevoke = function (name) {\n    var _name = !!name ? (\"Alexa.\" + name) : \"AlexaAPI\";\n\n    ws.revokeExternalAccess(_name);\n    ws.revokeExternalAccess(_name + \".callActions\");\n};\n\nAlexa.prototype.defineHandlers = function () {\n    var self = this;\n\n    this.AlexaAPI = function () {\n        return {status: 400, body: \"Bad AlexaAPI request \"};\n    };\n\n    this.AlexaAPI.callActions = function (url, request) {\n        console.log(\"Received data from Alexa Skill\");\n        //console.log(\"request:\", JSON.stringify(request, null , 4));\n        if (request.method === \"POST\" && request.body) {\n            reqObj = typeof request.body === \"string\" ? JSON.parse(request.body) : request.body;\n\n            var requestedNamespace = reqObj.header.namespace;\n\n            switch(requestedNamespace) {\n                case self.NAMESPACE_DISCOVERY:\n                    response = self.handleDiscovery(reqObj);\n                    break;\n                case self.NAMESPACE_CONTROL:\n                    response = self.handleControl(reqObj);\n                    break;\n                case self.NAMESPACE_QUERY:\n                    response = self.handleQuery(reqObj);\n                    break;\n                default:\n                    console.log(\"Error: \", \"Unsupported namespace: \" + requestedNamespace);\n                    self.handleUnexpectedInfo(requestedNamespace);\n                    break;\n            }\n            console.log(\"Return Response to Alexa Skill\");\n            //console.log(\"response:\", JSON.stringify(response, null, 4));\n            return response;\n        }\n    };\n};\n\n/**\n* HSV/HSB to RGB color conversion\n*\n* H runs from 0 to 360 degrees\n* S and V run from 0 to 100\n*\n*/\nfunction hsvToRgb(h, s, v) {\n    var r, g, b;\n    var i;\n    var f, p, q, t;\n     \n    // Make sure our arguments stay in-range\n    h = Math.max(0, Math.min(360, h));\n    s = Math.max(0, Math.min(100, s));\n    v = Math.max(0, Math.min(100, v));\n    // We accept saturation and value arguments from 0 to 100 because that's\n    if(s == 0) {\n        // Achromatic (grey)\n        r = g = b = v;\n        return {\n            r:Math.round(r * 255), \n            g:Math.round(g * 255), \n            b:Math.round(b * 255)\n        };\n    }\n     \n    h /= 60; // sector 0 to 5\n    i = Math.floor(h);\n    f = h - i; // factorial part of h\n    p = v * (1 - s);\n    q = v * (1 - s * f);\n    t = v * (1 - s * (1 - f));\n     \n    switch(i) {\n        case 0:\n            r = v;\n            g = t;\n            b = p;\n            break;\n     \n        case 1:\n            r = q;\n            g = v;\n            b = p;\n            break;\n     \n        case 2:\n            r = p;\n            g = v;\n            b = t;\n            break;\n     \n        case 3:\n            r = p;\n            g = q;\n            b = v;\n            break;\n     \n        case 4:\n            r = t;\n            g = p;\n            b = v;\n            break;\n     \n        default: // case 5:\n            r = v;\n            g = p;\n            b = q;\n    }\n     \n    return {\n        r:Math.round(r * 255), \n        g:Math.round(g * 255), \n        b:Math.round(b * 255)\n    };\n}"
  },
  {
    "path": "modules/Alexa/lang/de.json",
    "content": "{\n  \"m_title\":\"Alexa\",\n  \"m_descr\":\"Mit dieser App können Sie ihre SmartHome Geräte und Szenen mit Amazons Echo oder Dot und Alexa per Sprache steuern. <br><br> 1. Modul 'Alexa' herunterladen. <br> 2. Bei <a target='_blank' href='http://alexa.amazon.de'>alexa.amazon.de</a> anmelden.<br>3. Unter 'Skills' den Skill 'SmartHome Popp' suchen und aktivieren. <br>4. In der anschließenden Eingabemaske einfach mit Ihren 'Remote'-Daten anmelden (ID/User + PW).<br>5. Nach erfolgreicher Bestätigung kann das Fenster geschlossen werden und Alexa bietet Ihnen eine automatische Gerätesuche an. Falls dies nicht erscheint, können Sie mit dem Sprachbefehl: 'Alexa – suche Geräte' die suche selbst starten.<br> 6. Nachdem Alexa Ihre Geräte gefunden hat, können Sie diese ab sofort mit dem Sprachbefehl: 'Alexa – #Gerät# einschalten/ausschalten/auf #Wert# dimmen/auf #Wert# setzen' usw. steuern.\"\n}"
  },
  {
    "path": "modules/Alexa/lang/en.json",
    "content": "{\n  \"m_title\":\"Alexa\",\n  \"m_descr\":\"Gives possibility to control your SmartHome devcies and scene with your voice using Amazon's Echo or Dot and Alexa. <br><br> 1. Download App 'Alexa' <br> 2. Sign in to <a target='_blank' href='http://alexa.amazon.com'>alexa.amazon.com</a><br>3. Under 'Skills' find and activate the Skill 'SmartHome Popp' <br>4. In the subsequent input mask simply register with your 'Remote' data (Remote-ID / User + PW)<br>5. After successful confirmation the window can be closed and Alexa offers you an automatic device search. If this does not appear, you can use the language command: 'Alexa - search devices' to start the search.<br> 6. After Alexa has found your devices, they can now be controlled with voice commands, for example: 'Alexa - # device # switch on / off / to # value # dimming / set to # value #'.\"\n}"
  },
  {
    "path": "modules/Alexa/module.json",
    "content": "{\n  \"dependencies\": [],\n  \"singleton\": true,\n  \"category\": \"support_external_dev\",\n  \"author\": \"Z-Wave.Me\",\n  \"homepage\": \"http://razberry.z-wave.me\",\n  \"icon\": \"icon.png\",\n  \"moduleName\":\"Alexa\",\n  \"version\": \"1.1.0\",\n  \"maturity\": \"stable\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n  },\n  \"defaults\": {\n    \"title\" : \"__m_title__\",\n    \"description\": \"__m_descr__\",\n    \"assign_room\": false,\n    \"devices\": []\n  },\n  \"schema\": {},\n  \"options\": {}\n}\n\n"
  },
  {
    "path": "modules/Alexa/patchnotes.txt",
    "content": "v1.0.3\n- improve error handling\n- add  device typ switchRGBW to support RGB bulbs (change color)\nv1.0.2\n- add device type thermostat (set and get temperarture) and doorlock (request only the lockstate)\nv1.0.1\n- Alexa discover only devices with the device typ sensorMultilevel (and probeType temperature), switchBinary, toggleButton and switchMultilevel\n- add support to request temperature of the specific device\n"
  },
  {
    "path": "modules/AutoLock/index.js",
    "content": "/*** AutoLock Z-Way Home Automation module *************************************\n\n Version: 1.2\n (c) Z-Wave.Me, 2017\n\n -----------------------------------------------------------------------------\n Author: Yurkin Vitaliy <aivs@z-wave.me>\n Description: Door/Window Sensor automatically closes lock after delay when door is closed\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\nfunction AutoLock (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tAutoLock.super_.call(this, id, controller);\n\n\t// Create instance variables\n\tthis.timer = null;\n};\n\ninherits(AutoLock, AutomationModule);\n_module = AutoLock;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\nAutoLock.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tAutoLock.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\t\n\t// handler - it is a name of your function\n\tthis.handler = function (vDev) {\n\t\tvar nowSensorStatus = vDev.get(\"metrics:level\");\n\t\t// Clear delay if door opened\n\t\tif (nowSensorStatus === \"on\") {\n\t\t\tclearTimeout(self.timer);\n\t\t\tself.timer = null;\n\t\t}\n\t\t\n\t\t// Close lock if sensor false\n\t\tif (nowSensorStatus === \"off\") {\n\t\t\t// Start Timer\n\t\t\tself.timer = setTimeout(function () {\n\t\t\t\tvar vDevDoorLock = self.controller.devices.get(self.config.DoorLock);\n\t\t\t\tvar doorLockState = vDevDoorLock.get(\"metrics:level\");\n\t\t\t\tvar doorLockDeviceType = vDevDoorLock.get(\"deviceType\");\n\t\t\t\t\n\t\t\t\t// Check lock, if already closed don't send command\n\t\t\t\tif (!(self.config.doNotSendCommand && (doorLockState == \"close\" || doorLockState == \"on\"))) {\n\t\t\t\t\t// Close lock \n\t\t\t\t\tif (doorLockDeviceType == \"doorlock\") {\n\t\t\t\t\t\tself.controller.devices.get(self.config.DoorLock).performCommand(\"close\");\t\n\t\t\t\t\t}\n\t\t\t\t\tif (doorLockDeviceType == \"switchBinary\") {\n\t\t\t\t\t\tself.controller.devices.get(self.config.DoorLock).performCommand(\"on\");\t\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// And clearing out this.timer variable\n\t\t\t\tself.timer = null;\n\t\t\t}, self.config.delay*1000);\n\t\t}\n\t};\n\n\t// Setup metric update event listener\n\tthis.controller.devices.on(this.config.BinarySensor, 'change:metrics:level', this.handler);\n};\n\nAutoLock.prototype.stop = function () {\n\tAutoLock.super_.prototype.stop.call(this);\n\n\tif (this.timer)\n\t\tclearTimeout(this.timer);\n\n\tthis.controller.devices.off(this.config.BinarySensor, 'change:metrics:level', this.handler);\n};\n"
  },
  {
    "path": "modules/AutoLock/lang/de.json",
    "content": "{\n\t\"m_title\":\"Automatisches Schließen einer Tür\",\n\t\"m_descr\":\"Elektronische Türschlösser treiben zumeist Riegelschaltkontakte an. Befindet sich dieser Riegelschaltkontakt in der Standardposition kann die Tür per Türgriff geöffnet und geschlossen werden. Diese App verriegelt automatisch die Tür (d. h. treibt den Riegelschaltkontakt an) wenn eine geöffnete Tür sich schließt. Das Schließen der Tür wird durch einen Türsensor erkannt. Sobald dieser Sensor signalisiert, dass eine Tür schließt, wird das Türschloss nach einer bestimmten Zeit gedreht.  <br><br>Einstellungen:<br><ul><li>Wählen Sie den Türsensor, der die Türstellung erkennt.</li><li>Wählen Sie das zu steuernde Türschloss.</li><li>Wählen Sie den Zeitverzug der Verriegelung nach erkannter Türschließung</li></ul>\",\n\t\"l_dw_sensor\":\"Tür-/Fenstersensor\",\n\t\"l_doorlock\":\"Türverriegelung\",\n\t\"l_delay_sec\":\"Verzögerung in Sekunden\",\n\t\"rl_doNotSendCommand\":\"Don't send Lock command if doorlock already closed\"\n}"
  },
  {
    "path": "modules/AutoLock/lang/en.json",
    "content": "{\n\t\"m_title\":\"Automated Locking of Door\",\n\t\"m_descr\":\"Electronic Doors typically move the dead bold of the door. If the dead bold is in the default position the door can be opened and closed using the door handle.  This app will automatically lock the door (means move the dead bold) when an opened door closes. The closing of the door is detected using a door sensor. Once this sensor signals a closing door the door lock is turned after a defined delay.<br><br>Settings:<br><ul><li>Select the door sensor detecting the position of the door</li><li>Select the door lock to be controlled</li><li>Select a delay between the detected closed door and the looking</li></ul>\",\n\t\"l_dw_sensor\":\"Door/Window Sensor\",\n\t\"l_doorlock\":\"Door Lock\",\n\t\"l_delay_sec\":\"Delay in seconds\",\n\t\"rl_doNotSendCommand\":\"Don't send Lock command if doorlock already closed\"\n}"
  },
  {
    "path": "modules/AutoLock/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Авто закрытие\",\n\t\"m_descr\":\"Датчик открытия двери автоматически закрывает замок при закрытии двери.\",\n\t\"l_dw_sensor\":\"Датчик открытия двери\",\n\t\"l_doorlock\":\"Замок\",\n\t\"l_delay_sec\":\"Задержка на закрытие в секундах\",\n\t\"rl_doNotSendCommand\":\"Не отправлять команду закрытия, если замок уже закрыт\"\n}"
  },
  {
    "path": "modules/AutoLock/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"device_enhancements\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"AutoLock\",\n\t\"version\": \"1.2\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"BinarySensor\": null,\n\t\t\"DoorLock\": null,\n\t\t\"delay\": 5,\n\t\t\"doNotSendCommand\": false\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"BinarySensor\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"DoorLock\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"delay\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"minimum\": 1,\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"doNotSendCommand\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"BinarySensor\": {\n\t\t\t\t\"label\": \"__l_dw_sensor__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t},\n\t\t\t\"DoorLock\": {\n\t\t\t\t\"label\": \"__l_doorlock__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t},\n\t\t\t\"delay\": {\n\t\t\t\t\"label\": \"__l_delay_sec__\",\n\t\t\t\t\"type\": \"integer\"\n\t\t\t},\n\t\t\t\"doNotSendCommand\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_doNotSendCommand__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/AutoOff/index.js",
    "content": "/*** AutoOff Z-Way Home Automation module *************************************\n\n Version: 1.0.3\n (c) Z-Wave.Me, 2019\n\n -----------------------------------------------------------------------------\n Author: Gregory Sitnin <sitnin@z-wave.me>, Poltorak Serguei <ps@z-wave.me>, Vitaliy Yurkin <aivs@z-wave.me>\n Description:\n\t This module listens given VirtualDevice (which MUSt be typed as switch)\n\t level metric update events and switches off device after configured\n\t timeout if this device has been switched on.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction AutoOff (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tAutoOff.super_.call(this, id, controller);\n\n\t// Create instance variables\n\tthis.timer = null;\n};\n\ninherits(AutoOff, AutomationModule);\n\n_module = AutoOff;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nAutoOff.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tAutoOff.super_.prototype.init.call(this, config);\n\n\t// Remember \"this\" for detached callbacks (such as event listener callbacks)\n\tvar self = this;\n\n\tthis.handler = function (vDev) {\n\t\tvar value = vDev.get(\"metrics:level\");\n\t\t\n\t\tif (\"on\" === value || \"open\" === value || (parseInt(value) && value > 0) ) {\n\t\t\t// Device reported \"on\", set (or reset) timer to new timeout\n\t\t\t\n\t\t\tif (self.timer && self.config.ignoreUpdates) {\n\t\t\t\t// We ignore updates and do not restart the timer, keeping the old one running\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (self.timer) {\n\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\tclearTimeout(self.timer);\n\t\t\t\tself.timer = null;\n\t\t\t}\n\t\t\t// Notice: self.config.timeout set in seconds\n\t\t\tself.timer = setTimeout(function () {\n\t\t\t\t// Timeout fired, so we send \"off\" command to the virtual device\n\t\t\t\t// (every switch device should handle it)\n\t\t\t\tif (vDev.get(\"deviceType\") === \"doorlock\") {\n\t\t\t\t\tvDev.performCommand(\"close\");\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tvDev.performCommand(\"off\");\n\t\t\t\t}\n\t\t\t\t// And clearing out this.timer variable\n\t\t\t\tself.timer = null;\n\t\t\t}, self.config.timeout*1000);\n\t\t} else {\n\t\t\t// Turned off\n\t\t\tif (self.timer) {\n\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\tclearTimeout(self.timer);\n\t\t\t\tself.timer = null;\n\t\t\t}\n\t\t}\n\t};\n\n\t// Setup metric update event listener\n\tthis.controller.devices.on(this.config.device, 'change:metrics:level', this.handler);\n};\n\nAutoOff.prototype.stop = function () {\n\tAutoOff.super_.prototype.stop.call(this);\n\n\tif (this.timer){\n\t\tclearTimeout(this.timer);\n\t}\n\t\n\tthis.controller.devices.off(this.config.device, 'change:metrics:level', this.handler);\n};\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n// This module doesn't have any additional methods\n"
  },
  {
    "path": "modules/AutoOff/lang/de.json",
    "content": "{\n\t\"m_title\":\"Automatisiertes Ausschalten\",\n\t\"m_descr\":\"Diese App schaltet ein ausgewähltes Gerät (Schalter, Dimmer, Motorsteuerung) automatisch nach einer bestimmten Zeit ab. Das macht insbesondere bei Geräten Sinn, wie der Beleuchtung im Flur, die nicht zu lang eingeschalten bleiben sollen. Ist es bereits möglich, das Gerät innerhalb der „Timeout-Zeit“ abzuschalten, wird in diesem Fall nichts geschehen. <br><br>Einstellungen:<br><ul><li>Wählen Sie das Gerät, welches ausgeschalten werden soll.</li><li>Wählen Sie die Zeit zum Abschalten.</li></ul>\",\n\t\"l_dev\":\"Gerät:\",\n\t\"l_timeout\":\"Timeout in Sekunden:\",\n\t\"rl_ignoreUpdates\": \"Ignore status update\",\n\t\"h_ignoreUpdates\": \"Do not restart the timer on device status update (on On value received)\"\n}"
  },
  {
    "path": "modules/AutoOff/lang/en.json",
    "content": "{\n\t\"m_title\":\"Automated Switch Off\",\n\t\"m_descr\":\"This app will automatically turn off a selected device (switch, dimmer, motor control) after a defined time. This may make sense for lights in the basements of other devices that shall not be turned on for too long. It is already possible to turn of the selected device within the timeout period. In this case nothing will happen.<br><br>Settings:<br><ul><li>Pick the device to be turned off</li><li>Pick the time out time</li></ul>\",\n\t\"l_dev\":\"Device:\",\n\t\"l_timeout\":\"Timeout in seconds:\",\n\t\"rl_ignoreUpdates\": \"Ignore status update\",\n\t\"h_ignoreUpdates\": \"Do not restart the timer on device status update (on On value received)\"\n}"
  },
  {
    "path": "modules/AutoOff/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Авто выключение\",\n\t\"m_descr\":\"Автоматическое выключение устройства через определенное время.\",\n\t\"l_dev\":\"Устройство, которое должно быть выключено\",\n\t\"l_timeout\":\"Задержка на выключение в секундах\",\n\t\"rl_ignoreUpdates\": \"Игнорировать обновление статуса\",\n\t\"h_ignoreUpdates\": \"Не перезапускать таймер при получении обновлении статуса устройства (значения Вкл)\"\n}"
  },
  {
    "path": "modules/AutoOff/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"device_enhancements\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"AutoOff\",\n\t\"version\": \"1.0.3\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"timeout\": 5,\n\t\"ignoreUpdates\": false,\n\t\t\"device\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"device\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"ignoreUpdates\": {\n\t\t\t\t\"type\": \"boolean\"\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"device\": {\n\t\t\t\t\"label\": \"__l_dev__\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_doorlock:deviceName\"\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"label\": \"__l_timeout__\"\n\t\t\t},\n\t\t\t\"ignoreUpdates\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_ignoreUpdates__\",\n\t\t\t\t\"helper\": \"__h_ignoreUpdates__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/BatteryPolling/index.js",
    "content": "/*** BatteryPolling Z-Way HA module *******************************************\n\nVersion: 2.3.0\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Gregory Sitnin <sitnin@z-wave.me> and Serguei Poltorak <ps@z-wave.me>,\nKarsten Reichel <kar@z-wave.eu>\nDescription:\n\tThis module periodically requests all battery devices for battery level report\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction BatteryPolling (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tBatteryPolling.super_.call(this, id, controller);\n}\n\ninherits(BatteryPolling, AutomationModule);\n\n_module = BatteryPolling;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nBatteryPolling.prototype.init = function (config) {\n\tBatteryPolling.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t// timestamp of last triggered notification\n\tthis.lastTriggered = [];\n\n\t// polling function\n\tthis.onPoll = function () {\n\t\tself.controller.devices.filter(function (el) {\n\t\t\treturn el.get(\"deviceType\") === \"battery\" && (el.id != self.getName() + \"_\" + self.id);\n\t\t}).map(function(el) {\n\t\t\tel.performCommand(\"update\");\n\t\t});\n\t};\n\n\t// create vDev\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: this.getName() + \"_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"battery\",\n\t\t\tmetrics: {\n\t\t\t\tprobeTitle: \"Battery\",\n\t\t\t\tscaleTitle: \"%\",\n\t\t\t\ttitle: self.getInstanceTitle(),\n\t\t\t\ticon: \"battery\"\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: this.onPoll,\n\t\tmoduleId: this.id\n\t});\n\n\tthis.onMetricUpdated = function (vDev) {\t  \n\t\tif (!vDev || vDev.id === self.vDev.id) {\n\t\t\treturn; // prevent infinite loop with updates from itself and allows first fake update\n\t\t}\n\t\t\n\t\tif (vDev.get(\"deviceType\") !== \"battery\") {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\tself.vDev.set(\"metrics:level\", self.minimalBatteryValue());\n\t\tvar now = Math.round(Date.now() / 1000);\n\t\tif (vDev.get(\"metrics:level\") <= self.config.warningLevel && (typeof self.lastTriggered[vDev.id] === 'undefined' || self.lastTriggered[vDev.id] <= (now - 12*60*60))) {\n\t\t\tvar value = vDev.get(\"metrics:title\"),\n\t\t\t\tlangFile = self.loadModuleLang();\n\n\t\t\tself.addNotification(\"device-info\", langFile.warning + value, \"battery\", self.vDev.id);\n\t\t\tself.lastTriggered[vDev.id] = now;\n\t\t}\n\t};\n\t\n\t// Setup event listeners\n\tthis.controller.devices.on(\"change:metrics:level\", self.onMetricUpdated);\n\n\t// set up cron handler\n\tthis.controller.on(\"batteryPolling.poll\", this.onPoll);\n\n\t// Every Day is equal -1 in module.json\n\tvar everyDay = -1;\n\tif (this.config.launchWeekDay == everyDay) {\n\t\t// add cron schedule every day\n\t\tthis.controller.emit(\"cron.addTask\", \"batteryPolling.poll\", {\n\t\t\tminute: 0,\n\t\t\thour: 12,\n\t\t\tweekDay: null,\n\t\t\tday: null,\n\t\t\tmonth: null\n\t\t});\n\t}\n\telse {\n\t\t// add cron schedule every week\n\t\tthis.controller.emit(\"cron.addTask\", \"batteryPolling.poll\", {\n\t\t\tminute: 0,\n\t\t\thour: 12,\n\t\t\tweekDay: this.config.launchWeekDay,\n\t\t\tday: null,\n\t\t\tmonth: null\n\t\t});\n\t}\n\t\n\t// run first time to set up the value\n\tthis.onMetricUpdated();\n};\n\nBatteryPolling.prototype.stop = function () {\n\tBatteryPolling.super_.prototype.stop.call(this);\n\n\tvar self = this;\n\t\n\tthis.controller.devices.remove(this.vDev.id);\n\tthis.controller.devices.off(\"change:metrics:level\", self.onMetricUpdated);\n\tthis.controller.emit(\"cron.removeTask\", \"batteryPolling.poll\");\n\tthis.controller.off(\"batteryPolling.poll\", this.onPoll);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nBatteryPolling.prototype.minimalBatteryValue = function () {\n\tvar self = this,\n\t\tarr;\n   \n\tarr = this.controller.devices.filter(function(vDev) {\n\t\treturn vDev.get(\"deviceType\") === \"battery\" && vDev.id != self.vDev.id;\n\t}).map(function(vDev) {\n\t\treturn vDev.get(\"metrics:level\");\n\t});\n\tarr.push(100);\n\n\treturn Math.min.apply(null, arr);\n}\n"
  },
  {
    "path": "modules/BatteryPolling/lang/de.json",
    "content": "{\n\t\"m_title\":\"Batteriestatus\",\n\t\"m_descr\":\"Die Batteriestandabfrage aktualisiert den Batteriestatus durch wöchentliche Abfrage aller batteriebetriebener Geräte über deren aktuellen Batteriestatus. Sie können den Wochentag und die Warnstufe auswählen, wann dieses Modul Ihnen eine Warnmeldung sendet.\",\n\t\"l_launch_wd\":\"Wochentag, an dem der Batteriestatus abgefragt werden soll:\",\n\t\"every_d\":\"täglich\", \n\t\"mon\":\"Montag\", \n\t\"tue\":\"Dienstag\", \n\t\"wed\":\"Mittwoch\", \n\t\"thu\":\"Donnerstag\", \n\t\"fri\":\"Freitag\", \n\t\"sat\":\"Samstag\", \n\t\"sun\":\"Sonntag\",\n\t\"l_warning_lvl\":\"Benachrichtigungslevel\",\n\t\"h_warning_lvl\":\"Das Modul sendet eine Benachrichtigung, wenn der Batteriestatus eines Gerätes unterhalb dieses Levels fällt.\",\n\t\"warning\":\"Achtung! Das Batterielevel des Gerätes beträgt nur noch: \"\n}"
  },
  {
    "path": "modules/BatteryPolling/lang/en.json",
    "content": "{\n\t\"m_title\":\"Battery Polling\",\n\t\"m_descr\":\"The battery polling will update the battery status by asking all battery-operated device once a week for a battery status update.. You can pick the day of the week and a warning level, when this module will send you a warning note.\",\n\t\"l_launch_wd\":\"Do battery polling on\",\n\t\"every_d\":\"Every Day\", \n\t\"mon\":\"Monday\", \n\t\"tue\":\"Tuesday\", \n\t\"wed\":\"Wednesday\", \n\t\"thu\":\"Thursday\", \n\t\"fri\":\"Friday\", \n\t\"sat\":\"Saturday\", \n\t\"sun\":\"Sunday\",\n\t\"l_warning_lvl\":\"Warning Level\",\n\t\"h_warning_lvl\":\"Warn if device's battery is below this level\",\n\t\"warning\":\"Attention! Device is low battery: \"\n}"
  },
  {
    "path": "modules/BatteryPolling/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Опрос батарей\",\n\t\"m_descr\":\"Оповещение о низком заряде батарей.\",\n\t\"l_launch_wd\":\"Делать опрос заряда батарей\",\n\t\"every_d\":\"Каждый день\", \n\t\"mon\":\"Понедельник\", \n\t\"tue\":\"Вторник\", \n\t\"wed\":\"Среда\", \n\t\"thu\":\"Четверг\", \n\t\"fri\":\"Пятница\", \n\t\"sat\":\"Суббота\", \n\t\"sun\":\"Воскресенье\",\n\t\"l_warning_lvl\":\"Низкий уровень\",\n\t\"h_warning_lvl\":\"Оповестить если заряд любой батареи опустится ниже этого уровня\",\n\t\"warning\":\"Внимание! Батарея разряжена: \"\n}"
  },
  {
    "path": "modules/BatteryPolling/module.json",
    "content": "{\n\t\"singleton\": true,\n\t\"dependencies\": [\"Cron\"],\n\t\"category\": \"basic_gateway_modules\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"BatteryPolling\",\n\t\"version\": \"2.3.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"launchWeekDay\": 0,\n\t\t\"warningLevel\": 20\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"launchWeekDay\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [-1, 1, 2, 3, 4, 5, 6, 0]\n\t\t\t},\n\t\t\t\"warningLevel\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [5, 10, 15, 20]\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"launchWeekDay\": {\n\t\t\t\t\"label\": \"__l_launch_wd__\",\n\t\t\t\t\"optionLabels\": [\"__every_d__\", \"__mon__\", \"__tue__\", \"__wed__\", \"__thu__\", \"__fri__\", \"__sat__\", \"__sun__\"]\n\t\t\t},\n\t\t\t\"warningLevel\": {\n\t\t\t\t\"label\": \"__l_warning_lvl__\",\n\t\t\t\t\"helper\": \"__h_warning_lvl__\",\n\t\t\t\t\"optionLabels\": [\"5%\", \"10%\", \"15%\", \"20%\"]\n\t\t\t}\t\t\t\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/BindDevices/index.js",
    "content": "/*** BindDevices Z-Way HA module *******************************************\n\nVersion: 1.0.3\n(c) Z-Wave.Me, 2018\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tBind actions on one device to others\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction BindDevices (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tBindDevices.super_.call(this, id, controller);\n}\n\ninherits(BindDevices, AutomationModule);\n\n_module = BindDevices;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nBindDevices.prototype.init = function (config) {\n\tBindDevices.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.handlerLevel = function (sDev) {\n\t\tvar that = self,\n\t\t\tactionBinary = null,\n\t\t\tactionMultilevel = null,\n\t\t\tvalue = sDev.get(\"metrics:level\");\n\t\t\n\t\tif (value === 255 || value === true || value === \"on\") {\n\t\t\tactionBinary = \"on\";\n\t\t} else if (value === 0 || value === false || value === \"off\") {\n\t\t\tactionBinary = \"off\";\n\t\t} else {\n\t\t\tactionBinary = \"on\";\n\t\t\tactionMultilevel = value;\n\t\t}\n\t\t\n\t\tself.config.targetDevices.forEach(function(el) {\n\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tif (vDev.get(\"deviceType\") === \"switchBinary\" || vDev.get(\"deviceType\") === \"scene\" || vDev.get(\"deviceType\") === \"switchMultilevel\" && actionMultilevel === null) {\n\t\t\t\t\tvDev.performCommand(actionBinary);\n\t\t\t\t} else if ((vDev.get(\"deviceType\") === \"switchMultilevel\") || (vDev.get(\"deviceType\") === \"thermostat\")) {\n\t\t\t\t\tvDev.performCommand(\"exact\", { level: actionMultilevel });\n\t\t\t\t} else if (vDev.get(\"deviceType\") === \"sensorMultilevel\"){\n\t\t\t\t\tvDev.set(\"metrics:level\", actionMultilevel);\n\t\t\t\t} else if (vDev.get(\"deviceType\") === \"sensorBinary\"){\n\t\t\t\t\tvDev.set(\"metrics:level\", actionBinary);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\tthis.handlerChange = function (sDev) {\n\t\tvar action = sDev.get(\"metrics:change\");\n\t\t\n\t\tself.config.targetDevices.forEach(function(el) {\n\t\t\tvar vDev = self.controller.devices.get(el);\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tif ((vDev.get(\"deviceType\") === \"switchMultilevel\") || (vDev.get(\"deviceType\") === \"thermostat\")) {\n\t\t\t\t\tvDev.performCommand(action);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\t// Setup metric update event listener\n\tself.config.sourceDevices.forEach(function(x) {\n\t\tself.controller.devices.on(x, 'change:metrics:level', self.handlerLevel);\n\t\tself.controller.devices.on(x, 'change:metrics:change', self.handlerChange);\n\t});\n};\n\nBindDevices.prototype.stop = function () {\n\tvar self = this;\n\t\n\tself.config.sourceDevices.forEach(function(x) {\n\t\tself.controller.devices.off(x, 'change:metrics:level', self.handlerLevel);\n\t\tself.controller.devices.off(x, 'change:metrics:change', self.handlerChange);\n\t});\n\n\tBindDevices.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/BindDevices/lang/de.json",
    "content": "{\n\t\"m_title\":\"Assoziation\",\n\t\"m_descr\":\"Ein oder mehrere Geräte werden immer DANN geschaltet, WENN ein gewähltes Ereignis eingetreten ist. Dieses Ereignis kann das Auslösen eines Bewegungsmelders oder Türkontaktes sein aber auch das Umschalten eines anderen Schaltaktors.\",\n\t\"l_event_sources\":\"Wenn\",\n\t\"l_actors\":\"Dann\"\n}"
  },
  {
    "path": "modules/BindDevices/lang/en.json",
    "content": "{\n\t\"m_title\":\"Association\",\n\t\"m_descr\":\"The association is the foundation of automation. A selected action (THEN) is executed automatically at the moment when a certain event (IF) has happen. This app allows defining these relationships.  The (IF) event must be an event that happens at one time. Examples for this are a door that is opened (the door sensor trips) or a button that is pressed. A simple switch is also a reasonable source for an event because this switch can be switched. A temperature sensor is NO event in this regard because this sensor will continuously send temperature and not create an event. The event need to have two defines status of ‘0’ and ‘1’. Every binary sensor or switch button has these states. Status=1 will send a Command Set (1) to the list of selected actuators, Status=0 will send Set (0) to these devices. <br><br>Settings:<br><ul><li>Pick the events that shall trigger. You can select multiple events and all of them will trigger the selected action (connected with Logical OR). If you pick a dimmer or a motor control the change to full 100 % will be considered as the event to trigger.</li><li>Pick the devices that shall be switches depending on the action. Please not that these devices must be able to receive and execute Set(1) and set(0) commands.</li></ul>\",\n\t\"l_event_sources\":\"If\",\n\t\"l_actors\":\"Then\"\n}"
  },
  {
    "path": "modules/BindDevices/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Ассоциации\",\n\t\"m_descr\":\"Прямое ассоциирование устройств друг с другом.\",\n\t\"l_event_sources\":\"Список источников событий\",\n\t\"l_actors\":\"Список исполнителей\"\n}\n"
  },
  {
    "path": "modules/BindDevices/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\": \"BindDevices\",\n\t\"version\": \"1.0.3\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"sourceDevices\": [],\n\t\t\"targetDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"sourceDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId,namespaces:devices_switchControl:deviceId,namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_thermostat:deviceId,namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"targetDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_thermostat:deviceId,namespaces:devices_doorlock:deviceId,namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"sourceDevices\": {\n\t\t\t\t\"label\": \"__l_event_sources__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName,namespaces:devices_switchControl:deviceName,namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_thermostat:deviceName,namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"targetDevices\": {\n\t\t\t\t\"label\": \"__l_actors__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_thermostat:deviceName,namespaces:devices_doorlock:deviceName,namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/Camera/index.js",
    "content": "/*** Camera Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of camera\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Camera (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCamera.super_.call(this, id, controller);\n}\n\ninherits(Camera, AutomationModule);\n\n_module = Camera;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(Camera.prototype, {\n\tinit: function (config) {\n\t\tCamera.super_.prototype.init.call(this, config);\n\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\" || type === \"switchMultilevel\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\tif (config.screenUrl) {\n\t\t\tthis.screen_url = \"/\" + vDevId + \"/screen\";\n\t\t\tws.proxify(this.screen_url, config.screenUrl, config.user, config.password);\n\t\t}\n\n\t\tthis.proxy_url = \"/\" + vDevId + \"/stream\";\n\t\tws.proxify(this.proxy_url, config.url, config.user, config.password);\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: that.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t\tscreenUrl: this.screen_url,\n\t\t\t\t\thasZoomIn: !!config.zoomInUrl,\n\t\t\t\t\thasZoomOut: !!config.zoomOutUrl,\n\t\t\t\t\thasLeft: !!config.leftUrl,\n\t\t\t\t\thasRight: !!config.rightUrl,\n\t\t\t\t\thasUp: !!config.upUrl,\n\t\t\t\t\thasDown: !!config.downUrl,\n\t\t\t\t\thasOpen: !!config.openUrl || !!(config.doorDevices && config.doorDevices.length),\n\t\t\t\t\thasClose: !!config.closeUrl || !!(config.doorDevices && config.doorDevices.length),\n\t\t\t\t\texternalUrl: config.externalUrl\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\n\t\t\t\tif (command == \"zoomIn\") {\n\t\t\t\t\turl = config.zoomInUrl;\n\t\t\t\t} else if (command == \"zoomOut\") {\n\t\t\t\t\turl = config.zoomOutUrl;\n\t\t\t\t} else if (command == \"left\") {\n\t\t\t\t\turl = config.leftUrl;\n\t\t\t\t} else if (command == \"right\") {\n\t\t\t\t\turl = config.rightUrl;\n\t\t\t\t} else if (command == \"up\") {\n\t\t\t\t\turl = config.upUrl;\n\t\t\t\t} else if (command == \"down\") {\n\t\t\t\t\turl = config.downUrl;\n\t\t\t\t} else if (command == \"open\") {\n\t\t\t\t\turl = config.openUrl;\n\t\t\t\t\topener(command);\n\t\t\t\t} else if (command == \"close\") {\n\t\t\t\t\turl = config.closeUrl;\n\t\t\t\t\topener(command);\n\t\t\t\t};\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tCamera.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\tif (this.screen_url) {\n\t\t\tws.proxify(this.screen_url, null);\n\t\t}\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/Camera/lang/de.json",
    "content": "{\n  \"m_title\":\"Web Kamera\",\n  \"m_descr\":\"Dieses Modul konfiguriert die eingebundene Kamera und erstellt ein virtuelles Gerät.\",\n  \"l_cam_url\": \"URL - Kamera\",\n  \"l_screen_url\": \"URL - Screenshot\",\n  \"l_zoomin\": \"URL - Herein zommen\",\n  \"l_zoomout\": \"URL - Heraus zoomen\",\n  \"l_left\": \"URL - Drehung nach links\",\n  \"l_right\": \"URL - Drehung nach rechts\",\n  \"l_up\": \"URL - Drehung nach oben\",\n  \"l_down\": \"URL - Drehung nach unten\",\n  \"l_open\": \"URL - Öffen\",\n  \"l_close\": \"URL - Schließen\",\n  \"l_external_url\": \"URL to open on External URL click\",\n  \"l_user\": \"Benutzername für HTTP Authentifizierung\",\n  \"h_http_auth\": \"Lassen Sie das Feld frei, wenn die Kamera nicht mit einem Passwort geschütztt ist.\",\n  \"l_pw\":\"Passwort für HTTP Authentifiziereung.\",\n  \"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/Camera/lang/en.json",
    "content": "{\n\t\"m_title\":\"Web Camera\",\n\t\"m_descr\":\"This module include configuration for a camera and create camera device.\",\n\t\"l_cam_url\":\"Camera URL\",\n\t\"l_screen_url\": \"Screenshot URL\",\n\t\"l_zoomin\":\"ZoomIn URL\",\n\t\"l_zoomout\":\"ZoomOut URL\",\n\t\"l_left\":\"Left URL\",\n\t\"l_right\":\"Right URL\",\n\t\"l_up\":\"Up URL\",\n\t\"l_down\":\"Down URL\",\n\t\"l_open\":\"Open URL\",\n\t\"l_close\":\"Close URL\",\n\t\"l_external_url\": \"URL to open on External URL click\",\n  \t\"l_user\": \"Username for HTTP authentication\",\n  \t\"l_pw\": \"Password for HTTP authentication\",\n  \t\"h_http_auth\": \"Leave empty if camera is not protected by a password\",\n  \t\"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/Camera/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Web Камера\",\n\t\"m_descr\":\"Этот модуль позволяет настроить управление камерой.\",\n\t\"l_cam_url\":\"URL Камеры\",\n\t\"l_screen_url\": \"URL Screenshot\",\n\t\"l_zoomin\":\"URL Приблизить\",\n\t\"l_zoomout\":\"URL Отдалить\",\n\t\"l_left\":\"URL Влево\",\n\t\"l_right\":\"URL Вправо\",\n\t\"l_up\":\"URL Вверх\",\n\t\"l_down\":\"URL Вниз\",\n\t\"l_open\":\"URL Открыть\",\n\t\"l_close\":\"URL Закрыть\",\n\t\"l_external_url\": \"URL, который открывать по нажатиб на Внешний URL\",\n  \t\"l_user\": \"Имя пользователя\",\n  \t\"l_pw\": \"Пароль\",\n  \t\"h_http_auth\": \"Оставьте это поле пустым, если камера не использует HTTP авторизацию\",\n  \t\"l_door_dev\": \"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/Camera/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"Camera\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"screenUrl\": \"\",\n\t\"zoomInUrl\": \"\",\n\t\"zoomOutUrl\": \"\",\n\t\"leftUrl\": \"\",\n\t\"rightUrl\": \"\",\n\t\"upUrl\": \"\",\n\t\"downUrl\": \"\",\n\t\"openUrl\": \"\",\n\t\"closeUrl\": \"\",\n\t\"externalUrl\": \"\",\n\t\"user\": \"\",\n\t\"password\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"screenUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"zoomInUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"zoomOutUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"leftUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"rightUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"upUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"downUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"openUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"closeUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"externalUrl\": {\n\t\t\t\t\"format\": \"uri\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__l_cam_url__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"screenUrl\": {\n\t\t\t\t\"label\": \"__l_screen_url__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"zoomInUrl\": {\n\t\t\t\t\"label\": \"__l_zoomin__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"zoomOutUrl\": {\n\t\t\t\t\"label\": \"__l_zoomout__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"leftUrl\": {\n\t\t\t\t\"label\": \"__l_left__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"rightUrl\": {\n\t\t\t\t\"label\": \"__l_right__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"upUrl\": {\n\t\t\t\t\"label\": \"__l_up__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"downUrl\": {\n\t\t\t\t\"label\": \"__l_down__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"openUrl\": {\n\t\t\t\t\"label\": \"__l_open__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"closeUrl\": {\n\t\t\t\t\"label\": \"__l_close__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"externalUrl\": {\n\t\t\t\t\"label\": \"__l_external_url__\",\n\t\t\t\t\"type\": \"url\",\n\t\t\t\t\"allowIntranet\": true,\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"label\": \"__l_user__\",\n\t\t\t\t\"helper\": \"__h_http_auth__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__l_pw__\",\n\t\t\t\t\"helper\": \"__h_http_auth__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__l_door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/CloudBackup/Readme.md",
    "content": ""
  },
  {
    "path": "modules/CloudBackup/htdocs/js/postRender.js",
    "content": "function modulePostRender(control) {\n\tvar scheduler = control.childrenByPropertyId['scheduler'];\n\tvar api = control.data.api;\n\tif(scheduler.getValue() == 0) {\n\t\taddButton();\n\t}\n\n\tscheduler.on('change', function() {\n\t\tif(this.getValue() == 0) {\n\t\t\taddButton();\n\t\t} else {\n\t\t\tremoveButton();\n\t\t}\n\t});\n\n\tfunction addButton() {\n\t\tvar $button = $('<a>');\n\t\tvar $i = $('<i>');\n\t\t$button.addClass('btn btn-default btn-sm');\n\t\t$i.addClass('fa fa-cloud-upload');\n\t\t$button.append($i);\n\t\t$button.attr('href', \"http://\"+location.host+api);\n\t\t$button.append('Upload Backup');\n\n\t\t$button.on('click', function(event) {\n\t\t\tevent.preventDefault();\n\t\t\tvar $this = $(this);\n\t\t\tvar url = $this.attr('href');\n\t\t\t$.get(url);\n\t\t});\n\n\t\t$('.cloudBackupScheduler').append($button);\n\t}\n\n\tfunction removeButton() {\n\t\t$('.cloudBackupScheduler').find('a').remove();\n\t}\n}"
  },
  {
    "path": "modules/CloudBackup/index.js",
    "content": "/*** CloudBackup Z-Way HA module *******************************************\n\n Version: 0.1.3 beta\n (c) Z-Wave.Me, 2016\n -----------------------------------------------------------------------------\n Author: Michael Hensche <mh@zwave.eu>\n Description: Gives possibility to upload and store your backups on the remote server.\n\n ******************************************************************************/\n\nfunction CloudBackup (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCloudBackup.super_.call(this, id, controller);\n}\n\ninherits(CloudBackup, AutomationModule);\n\n_module = CloudBackup;\n\nCloudBackup.prototype.init = function(config) {\n\tCloudBackup.super_.prototype.init.call(this, config);\n\n\tthis.backupcreate_url = \"https://service.z-wave.me/cloudbackup/?uri=backupcreate\";\n\tthis.usercreate_url = \"https://service.z-wave.me/cloudbackup/?uri=usercreate\";\n\tthis.userupdate_url = \"https://service.z-wave.me/cloudbackup/?uri=userupdate\";\n\n\tvar self = this,\n\t\tlangFile = self.loadModuleLang();\n\n\t// load remote_id\n\ttry {\n\t\tthis.remoteid = self.controller.getRemoteId();\n\t\tself.config.remoteid = this.remoteid;\n\t} catch(e) {\n\t\tconsole.log(e.message);\n\t\treturn;\n\t}\n\n\tthis.defineHandlers();\n\tthis.externalAPIAllow();\n\tglobal[\"CloudBackupAPI\"] = this.CloudBackupAPI;\n\n\n\tthis.uploadBackup = function() {\n\t\tconsole.log(\"###### start Backup \");\n\t\tvar ret = false;\n\n\t\ttry {\n\t\t\tvar backupJSON = self.controller.createBackup();\n\n\t\t\tvar now = new Date();\n\t\t\t// create a timestamp in format yyyy-MM-dd-HH-mm\n\t\t\tvar ts = now.getFullYear() + \"-\";\n\t\t\tts += (\"0\" + (now.getMonth()+1)).slice(-2) + \"-\";\n\t\t\tts += (\"0\" + now.getDate()).slice(-2) + \"-\";\n\t\t\tts += (\"0\" + now.getHours()).slice(-2) + \"-\";\n\t\t\tts += (\"0\" + now.getMinutes()).slice(-2);\n\n\t\t\tif(!_.isNull(backupJSON)) {\n\t\t\t\tvar data = {\"data\": Base64.encode(JSON.stringify(backupJSON))};\n\n\t\t\t\tvar formElements = [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'remote_id',\n\t\t\t\t\t\tvalue: self.config.remoteid.toString()\n\t\t\t\t\t},{\n\t\t\t\t\t\tname: 'email_report',\n\t\t\t\t\t\tvalue: self.config.email_log.toString()\n\t\t\t\t\t},{\n\t\t\t\t\t\tname: 'file',\n\t\t\t\t\t\tfilename: \"z-way-backup-\" + ts + \".zab\",\n\t\t\t\t\t\ttype: 'application/octet-stream',\n\t\t\t\t\t\tvalue: JSON.stringify(data)\n\t\t\t\t\t}];\n\n\t\t\t\tvar res = formRequest.send(formElements, \"POST\", self.backupcreate_url);\n\n\t\t\t\tif(res.status === -1) { //error e.g. no connection to server\n\t\t\t\t\tself.addNotification(\"error\", res.statusText, \"module\");\n\t\t\t\t} else {\n\t\t\t\t\tif(res.status === 200) {\n\t\t\t\t\t\tret = true;\n\t\t\t\t\t\tself.addNotification(\"info\", res.data.message, \"module\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addNotification(\"error\", res.data.message, \"module\");\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tconsole.log(\"Backup file empty!\");\n\t\t\t}\n\n\t\t} catch(e) {\n\t\t\tconsole.log(e);\n\t\t}\n\t\tconsole.log(\"###### finisch Backup \");\n\t\treturn ret;\n\t};\n\n\tif(self.config.email !== \"\" && !_.isNull(self.config.remoteid) && !self.config.user_active) {\n\t\tconsole.log(\"userCreate\");\n\t\tthis.userCreate();\n\t} else {\n\t\tself.config.user_active = false;\n\t}\n\n\tif(self.config.email !== \"\" && !_.isNull(self.config.remoteid)) {\n\t\tconsole.log(\"userUpdate\");\n\t\tthis.userUpdate();\n\t}\n\n\tif(self.config.scheduler !== \"0\" && self.config.user_active == true) { // manual\n\t\tthis.updateTask();\n\t} else {\n\t\tthis.controller.emit(\"cron.removeTask\", \"CloudBackup.upload\");\n\t}\n\n\t// set up cron handler\n\tself.controller.on(\"CloudBackup.upload\", self.uploadBackup);\n};\n\nCloudBackup.prototype.stop = function() {\n\n\tthis.controller.off(\"CloudBackup.upload\", this.uploadBackup);\n\tthis.controller.emit(\"cron.removeTask\", \"CloudBackup.upload\");\n\n\tdelete global[\"CloudBackupAPI\"];\n\n\n\tCloudBackup.super_.prototype.stop.call(this);\n};\n\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nCloudBackup.prototype.updateTask = function() {\n\tvar self = this;\n\n\tswitch(self.config.scheduler) {\n\t\tcase \"0\": // manual\n\t\t\tself.config.minutes = null;\n\t\t\tself.config.hours = null;\n\t\t\tself.config.weekDays = null;\n\t\t\tself.config.days = null;\n\t\t\tbreak;\n\t\tcase \"1\": // daily\n\t\t\tself.config.weekDays = null;\n\t\t\tself.config.days = null;\n\t\t\tbreak;\n\t\tcase \"2\": // weekly\n\t\t\tself.config.days = null;\n\t\t\tbreak;\n\t\tcase \"3\": // monthly\n\t\t\tself.config.weekDays = null;\n\t\t\tbreak;\n\t};\n\n\tconsole.log(\"### Backuptime ###\");\n\tconsole.log(\"h\", _.isNull(self.config.hours) ? \"null\" : parseInt(self.config.hours));\n\tconsole.log(\"m\", _.isNull(self.config.minutes) ? \"null\" : parseInt(self.config.minutes));\n\tconsole.log(\"wd\", _.isNull(self.config.weekDays) ? \"null\" : parseInt(self.config.weekDays));\n\tconsole.log(\"d\", _.isNull(self.config.days) ? \"null\" : parseInt(self.config.days));\n\tconsole.log(\"##################\");\n\n\tself.controller.emit(\"cron.addTask\", \"CloudBackup.upload\", {\n\t\tminute: _.isNull(self.config.minutes) ? null : parseInt(self.config.minutes),\n\t\thour: _.isNull(self.config.hours) ? null : parseInt(self.config.hours),\n\t\tweekDay: _.isNull(self.config.weekDays) ? null : parseInt(self.config.weekDays),\n\t\tday: _.isNull(self.config.days) ? null : parseInt(self.config.days),\n\t\tmonth: null\n\t});\n};\n\nCloudBackup.prototype.userCreate = function() {\n\tvar self = this;\n\n\tvar obj = {\n\t\turl: this.usercreate_url,\n\t\tmethod: \"POST\",\n\t\tdata: {\n\t\t\tremote_id: self.config.remoteid,\n\t\t\temail: self.config.email\n\t\t}\n\t};\n\n\tvar res = http.request(obj);\n\n\tif(res.status === -1) { //error e.g. no connection to server\n\t\tself.config.service_status = false;\n\t\tself.config.user_active = false;\n\t} else {\n\t\tif(res.status === 200) {\n\t\t\tself.config.user_active = true;\n\t\t} else {\n\t\t\tself.config.user_active = false;\n\t\t}\n\t}\n\n\t/*if(res.data.status === 200) {\n\t\tself.config.user_active = true\n\t\tself.addNotification(\"info\", res.data.message, \"core\");\n\t} else {\n\t\tself.addNotification(\"error\", res.data.message, \"core\");\n\t}*/\n};\n\nCloudBackup.prototype.userUpdate = function() {\n\tvar self = this;\n\n\tvar obj = {\n\t\turl: this.userupdate_url,\n\t\tmethod: \"POST\",\n\t\tdata: {\n\t\t\tremote_id: self.config.remoteid,\n\t\t\temail: self.config.email,\n\t\t\temail_log: self.config.email_log\n\t\t}\n\t};\n\n\tvar res = http.request(obj);\n\n\tif(res.status === -1) { //error e.g. no connection to server\n\t\tconsole.log(\"error\");\n\t\tself.config.service_status = false;\n\t\tself.config.user_active = false;\n\t} else {\n\t\tself.config.service_status = true;\n\n\t\tif(res.status === 200) {\n\t\t\tself.config.user_active = true;\n\t\t} else {\n\t\t\tself.config.user_active = false;\n\t\t}\n\t}\n\t/*if(res.data.status === 200) {\n\t\tconsole.log(res.data.message);\n\t\t//self.addNotification(\"info\", \"User update \"+res.data.message, \"core\");\n\t} else {\n\t\tconsole.log(res.data.message);\n\t\t//self.addNotification(\"error\", res.data.message, \"core\");\n\t}*/\n};\n\n// --------------- Public HTTP API -------------------\n\n\nCloudBackup.prototype.externalAPIAllow = function (name) {\n\tvar _name = !!name ? (\"CloudBackup.\" + name) : \"CloudBackupAPI\";\n\n\tws.allowExternalAccess(_name, this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Backup\", this.controller.auth.ROLE.ADMIN);\n};\n\nCloudBackup.prototype.externalAPIRevoke = function (name) {\n\tvar _name = !!name ? (\"CloudBackup.\" + name) : \"CloudBackupAPI\";\n\n\tws.revokeExternalAccess(_name);\n\tws.revokeExternalAccess(_name + \".Backup\");\n};\n\nCloudBackup.prototype.defineHandlers = function () {\n\tvar self = this;\n\n\tthis.CloudBackupAPI = function () {\n\t\treturn {status: 400, body: \"Bad CloudBackupAPI request \"};\n\t};\n\n\tthis.CloudBackupAPI.Backup = function () {\n\t\tvar ret = {status: 500,\n\t\t\tbody: {\"error\": true}\n\t\t};\n\n\t\tvar state = self.uploadBackup();\n\n\t\tif(state) {\n\t\t\tret.status = 200;\n\t\t\tret.body = {\"error\": false};\n\t\t}\n\t\tconsole.log(JSON.stringify(ret));\n\t\treturn ret;\n\t};\n}"
  },
  {
    "path": "modules/CloudBackup/lang/de.json",
    "content": "{\n  \"m_title\":\"CloudBackup\",\n  \"m_descr\":\"Diese App gibt Ihnen die Möglichkeit, Ihre Backups auf dem Remote-Server hochzuladen und zu speichern.\",\n  \"l_email\":\"E-Mail\",\n  \"l_email_log\":\"E-Mail Benachrichtigung zur Datensicherung\",\n  \"l_no_log\":\"Kein E-Mail Benachrichtigung\",\n  \"l_only_log\":\"E-Mail Benachrichtigung bei fehlgeschlagener Datensicherung\",\n  \"l_log_notification\":\"E-Mail Benachrichtigung bei fehlgeschlagener und erfolgreicher Datensicherung\",\n  \"l_hours\":\"Stunden\",\n  \"l_minutes\":\"Minuten\",\n  \"l_weekDays\":\"Wochentage\",\n  \"l_su\":\"Sonntag\",\n  \"l_mo\":\"Montag\",\n  \"l_tu\":\"Dienstag\",\n  \"l_we\":\"Mittwoch\",\n  \"l_th\":\"Donnerstag\",\n  \"l_fr\":\"Freitag\",\n  \"l_sa\":\"Samstag\",\n  \"l_days\":\"Tage\",\n  \"l_scheduler\":\"Zeitplan\",\n  \"l_daily\":\"Täglich\",\n  \"l_weekly\":\"Wöchentlich\",\n  \"l_monthly\":\"Monatlich\",\n  \"l_manual\":\"Manuell\"\n}"
  },
  {
    "path": "modules/CloudBackup/lang/en.json",
    "content": "{\n  \"m_title\":\"CloudBackup\",\n  \"m_descr\":\"Gives possibility to upload and store your backups on the remote server.\",\n  \"l_email\":\"E-Mail\",\n  \"l_email_log\":\"E-Mail notification\",\n  \"l_no_log\":\"Do not send me log by email\",\n  \"l_only_log\":\"Send me error log only by email\",\n  \"l_log_notification\":\"Send me error log and notifications by email\",\n  \"l_hours\":\"Hours\",\n  \"l_minutes\":\"Minutes\",\n  \"l_weekDays\":\"Weekdays\",\n  \"l_su\":\"Sunday\",\n  \"l_mo\":\"Monday\",\n  \"l_tu\":\"Tuesday\",\n  \"l_we\":\"Wednseday\",\n  \"l_th\":\"Thursday\",\n  \"l_fr\":\"Friday\",\n  \"l_sa\":\"Saturday\",\n  \"l_days\":\"Days\",\n  \"l_scheduler\":\"Scheduler\",\n  \"l_daily\":\"Daily\",\n  \"l_weekly\":\"Weekly\",\n  \"l_monthly\":\"Monthly\",\n  \"l_manual\":\"Manual\"\n}"
  },
  {
    "path": "modules/CloudBackup/module.json",
    "content": "{\n  \"dependencies\": [\n\t\"Cron\"\n  ],\n  \"singleton\": true,\n  \"autoload\": true,\n  \"category\": \"\",\n  \"author\": \"Z-Wave.Me\",\n  \"homepage\": \"http://razberry.z-wave.me\",\n  \"icon\": \"icon.png\",\n  \"moduleName\":\"CloudBackup\",\n  \"version\": \"0.1.3\",\n  \"maturity\": \"beta\",\n  \"repository\": {\n\t\"type\": \"git\",\n\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n  },\n  \"defaults\": {\n\t\"title\": \"__m_title__\",\n\t\"description\": \"__m_descr__\",\n\t\"api\": \"/CloudBackupAPI/Backup\",\n\t\"user_active\": false,\n\t\"service_status\": true,\n\t\"email\": \"\",\n\t\"email_log\": \"0\",\n\t\"remoteid\": null,\n\t\"days\": null,\n\t\"weekDays\": null,\n\t\"hours\": null,\n\t\"minutes\": null,\n\t\"scheduler\": \"0\"\n  },\n  \"schema\" : {\n\t\"type\": \"object\",\n\t\"properties\": {\n\t  \"email\": {\n\t\t\"type\": \"string\",\n\t\t\"format\": \"email\",\n\t\t\"required\": true\n\t  },\n\t  \"email_log\": {\n\t\t\"type\": \"string\",\n\t\t\"enum\": [\"0\",\"1\",\"2\"],\n\t\t\"required\": true\n\t  },\n\t  \"remoteid\": {\n\t\t\"type\": \"integer\",\n\t\t\"readonly\": true,\n\t\t\"required\": true\n\t  },\n\t  \"scheduler\": {\n\t\t\"type\": \"string\",\n\t\t\"enum\": [\"0\", \"1\", \"2\", \"3\"],\n\t\t\"required\": true\n\t  },\n\t  \"hours\": {\n\t\t\"type\": \"string\",\n\t\t\"enum\": [\"00\", \"01\", \"02\", \"03\", \"04\", \"05\", \"06\", \"07\", \"08\", \"09\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"20\", \"21\", \"22\", \"23\"]\n\t  },\n\t  \"minutes\": {\n\t\t\"type\": \"string\",\n\t\t\"enum\": [\"00\", \"01\", \"02\", \"03\", \"04\", \"05\", \"06\", \"07\", \"08\", \"09\", \"10\", \"11\", \"12\", \"13\", \"14\", \"15\", \"16\", \"17\", \"18\", \"19\", \"20\", \"21\", \"22\", \"23\",\"24\",\"25\",\"26\",\"27\",\"28\",\"29\",\"30\",\"31\",\"32\",\"33\",\"34\",\"35\",\"36\",\"37\",\"38\",\"39\",\"40\",\"41\",\"42\",\"43\",\"44\",\"45\",\"46\",\"47\",\"48\",\"49\",\"50\",\"51\",\"52\",\"53\",\"54\",\"55\",\"56\",\"57\",\"58\",\"59\"]\n\t  },\n\t  \"weekDays\": {\n\t\t\"type\": \"string\",\n\t\t\"enum\": [\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]\n\t  },\n\t  \"days\": {\n\t\t\"type\": \"string\",\n\t\t\"enum\": [\"01\",\"02\",\"03\",\"04\",\"05\",\"06\",\"07\",\"08\",\"09\",\"10\",\"11\",\"12\",\"13\",\"14\",\"15\",\"16\",\"17\",\"18\",\"19\",\"20\",\"21\",\"22\",\"23\",\"24\",\"25\",\"26\",\"27\",\"28\",\"29\",\"30\",\"31\"]\n\t  }\n\t},\n\t\"dependencies\": {\n\t  \"scheduler\": [\"remoteid\", \"email\"],\n\t  \"minutes\": [\"scheduler\"],\n\t  \"weekDays\": [\"scheduler\"],\n\t  \"days\": [\"scheduler\"],\n\t  \"hours\": [\"scheduler\"]\n\t}\n  },\n  \"options\": {\n\t\"fields\": {\n\t  \"remoteid\": {\n\t\t\"type\": \"hidden\"\n\t  },\n\t  \"email\": {\n\t\t\"type\": \"hidden\",\n\t\t\"label\": \"__l_email__\"\n\t  },\n\t  \"email_log\": {\n\t\t\"type\": \"hidden\",\n\t\t\"emptySelectFirst\": true,\n\t\t\"label\": \"__l_email_log__\",\n\t\t\"optionLabels\": [\"__l_no_log__\", \"__l_only_log__\", \"__l_log_notification__\"]\n\t  },\n\t  \"scheduler\": {\n\t\t\"type\": \"hidden\",\n\t\t\"emptySelectFirst\": true,\n\t\t\"fieldClass\": \"cloudBackupScheduler\",\n\t\t\"label\": \"__l_scheduler__\",\n\t\t\"optionLabels\": [\"__l_manual__\", \"__l_daily__\", \"__l_weekly__\", \"__l_monthly__\"]\n\t  },\n\t  \"hours\": {\n\t\t\"type\": \"hidden\",\n\t\t\"label\": \"__l_hours__\",\n\t\t\"dependencies\": {\n\t\t  \"scheduler\": [\"1\",\"2\",\"3\"]\n\t\t}\n\t  },\n\t  \"minutes\": {\n\t\t\"type\": \"hidden\",\n\t\t\"label\": \"__l_minutes__\",\n\t\t\"dependencies\": {\n\t\t  \"scheduler\": [\"1\",\"2\",\"3\"]\n\t\t}\n\t  },\n\t  \"weekDays\": {\n\t\t\"type\": \"hidden\",\n\t\t\"optionLabels\": [\"__l_su__\", \"__l_mo__\", \"__l_tu__\", \"__l_we__\", \"__l_th__\", \"__l_fr__\", \"__l_sa__\"],\n\t\t\"label\": \"__l_weekDays__\",\n\t\t\"dependencies\": {\n\t\t  \"scheduler\": [\"2\"]\n\t\t}\n\t  },\n\t  \"days\": {\n\t\t\"type\": \"hidden\",\n\t\t\"label\": \"__l_days__\",\n\t\t\"dependencies\": {\n\t\t  \"scheduler\": [\"3\"]\n\t\t}\n\t  }\n\t}\n  },\n  \"postRender\": \"loadFunction:postRender.js\"\n}\n"
  },
  {
    "path": "modules/CodeDevice/index.js",
    "content": "/*** CodeDevice Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tImplements virtual device based on JavaScript code\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction CodeDevice (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCodeDevice.super_.call(this, id, controller);\n}\n\ninherits(CodeDevice, AutomationModule);\n\n_module = CodeDevice;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCodeDevice.prototype.init = function (config) {\n\tCodeDevice.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\ticon = \"\",\n\t\tlevel = \"\",\n\t\tscaleTitle = \"\",\n\t\tdeviceType = this.config.deviceType;\n\t\tprobeType = \"\"\n\t\t\n\tswitch(deviceType) {\n\t\tcase \"sensorBinary\":\n\t\t\ticon = this.config.iconSensorBinary;\n\t\t\tprobeType = this.config.iconSensorBinary == \"door\" ? \"door-window\" : this.config.iconSensorBinary;\n\t\t\tlevel = \"off\";\n\t\t\tbreak;\n\t\tcase \"sensorMultilevel\":\n\t\t\ticon = this.config.iconSensorMultilevel;\n\t\t\tprobeType = this.config.iconSensorMultilevel;\n\t\t\tscaleTitle = this.config.scale_sensorMultilevel;\n\t\t\tlevel = 0;\n\t\t\tbreak;\n\t\tcase \"switchBinary\":\n\t\t\ticon = \"switch\";\n\t\t\tlevel = \"off\";\n\t\t\tbreak;\n\t\tcase \"switchMultilevel\":\n\t\t\ticon = \"multilevel\";\n\t\t\tlevel = 0;\n\t\t\tbreak;\n\t\tcase \"toggleButton\":\n\t\t\ticon = \"gesture\";\n\t\t\tlevel = \"on\";\n\t\t\tbreak;\n\t}\n\t\n\tvar defaults = {\n\t\tmetrics: {\n\t\t\ttitle: self.getInstanceTitle()\n\t\t}\n\t};\n\t\n\tvar overlay = {\n\t\t\tdeviceType: deviceType,\n\t\t\tprobeType: probeType,\n\t\t\tmetrics: {\n\t\t\t\ticon: icon,\n\t\t\t\tlevel: level,\n\t\t\t\tscaleTitle: scaleTitle\n\t\t\t}\t  \n\t};\n\n\tvar vDev = self.controller.devices.create({\n\t\tdeviceId: \"Code_Device_\" + deviceType + \"_\" + this.id,\n\t\tdefaults: defaults,\n\t\toverlay: overlay,\n\t\thandler: function (command, args) {\n\t\t\tvar vDevType = deviceType;\n\n\t\t\tif (command === \"update\" && (vDevType === \"sensorBinary\" || vDevType === \"sensorMultilevel\" || vDevType === \"switchBinary\" || vDevType === \"switchMultilevel\")) {\n\t\t\t\tself.update(this);\n\t\t\t}\n\n\t\t\tif (command === \"on\" && (vDevType === \"toggleButton\" || vDevType === \"switchBinary\")) {\n\t\t\t\tself.act(this, \"On\", null, (vDevType === \"switchBinary\" ? \"on\" : null));\n\t\t\t}\n\n\n\t\t\tif (command === \"off\" && vDevType === \"switchBinary\") {\n\t\t\t\tself.act(this, \"Off\", null, \"off\");\n\t\t\t}\n\n\t\t\tif ((command === \"off\" || command === \"on\" || command === \"exact\") && vDevType === \"switchMultilevel\") {\n\t\t\t\tvar level = command === \"exact\" ? parseInt(args.level, 10) : (command === \"on\" ? 99 : 0);\n\t\t\t\tself.act(this, \"Level\", level, level);\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\tif (vDev && this.config[\"getter_\" + deviceType] && this.config[\"getterPollInterval_\" + deviceType]) {\n\t\tthis.timer = setInterval(function() {\n\t\t\tself.update(vDev);\n\t\t}, this.config[\"getterPollInterval_\" + deviceType] * 1000);\n\t}\n};\n\nCodeDevice.prototype.stop = function () {\n\tif (this.timer) {\n\t\tclearInterval(this.timer);\n\t}\n\t\n\tthis.controller.devices.remove(\"Code_Device_\" + this.config.deviceType + \"_\" + this.id);\n\t\n\tCodeDevice.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nCodeDevice.prototype.update = function (vDev) {\n\tvar deviceType = this.config.deviceType,\n\t\tgetterCode = this.config[\"getter_\" + deviceType];\n\n\tif (getterCode) {\n\t\tvar newValue = eval(getterCode);\n\t\tif (this.config.skipEventIfSameValue !== true || newValue !== vDev.get(\"metrics:level\")) {\n\t\t\tvDev.set(\"metrics:level\", newValue);\n\t\t}\n\t}\n};\n\nCodeDevice.prototype.act = function (vDev, action, subst, selfValue) {\n\tvar self = this,\n\t\tdeviceType = this.config.deviceType,\n\t\tsetterCode = this.config[\"setter\" + action + \"_\" + deviceType];\n\t\n\tif (!!setterCode) {\n\t\tif (subst != null) {\n\t\t\tsetterCode = setterCode.replace(/%%/g, subst);\n\t\t}\n\t\teval(setterCode);\n\t}\n\t\n\tif ((!setterCode || this.config.updateOnAction === true) && selfValue !== null) {\n\t\tvDev.set(\"metrics:level\", selfValue);\n\t}\n};\n"
  },
  {
    "path": "modules/CodeDevice/lang/de.json",
    "content": "{\n\t\"m_title\":\"Virtuelle Gerät (JavaScript)\",\n\t\"m_descr\":\"Die Anwendung dieser App erfordert solide Kenntnisse in der JavaScript Programmierung. Diese App ermöglicht die Erstellung eines neuen Gerätes basierend auf einigen JavaScript Anweisungen. Das JavaScript kann alle möglichen Daten abfragen und berechnen so lange diese per JavaScript ausführbar sind. Das Gerät kann sowohl ein Sensor sein, welcher lediglich Daten anzeigt, als auch ein Java Script Code ausführender Aktor.<br><br>Einstellungen:<br><ul><li>Choose type of device</li><li>Set the code for actions</li><li>Set the code to get the value</li><li>Set the polling interval</li></ul><br>Beispiel: Die App soll ein Element erstellen, welches wahllos “An” oder “Aus” anzeigt. Der verwendete JavaScript Code lautet: Math.random() > 0.5 ? 'on' : 'off'</br></br>You can create a virtual device without code and update the value using the HTTP API, for example:</br>http://192.168.1.108:8083/JS/Run/controller.devices.get('Code_Device_sensorMultilevel_38').set('metrics:level',50)</br>http://192.168.1.108:8083/JS/Run/controller.devices.get('Code_Device_sensorBinary_39').set('metrics:level','on')\",\n\t\"l_icon\":\"Icon\",\n\t\"l_setterOn_toggleButton\":\"Code für den Befehl 'on'\",\n\t\"h_getter_sensorBinary\":\"Rückgabe der Werte 'on' oder 'off'\",\n\t\"h_getter_sensorMultilevel\":\"Rückgabe einer Zahlenwertes\",\n\t\"l_scale_sensorMultilevel\":\"Sensoreinheit\",\n\t\"l_setterOn_switchBinary\":\"Code für den Befehl 'on'\",\n\t\"h_setterOn_switchBinary\":\"%% steht für 'on'\",\n\t\"l_setterOff_switchBinary\":\"Code für den Befehl 'off'\",\n\t\"h_setterOff_switchBinary\":\"%% steht für 'off'\",\n\t\"h_getter_switchBinary\":\"Rückgabe der Werte 'on' oder 'off'\",\n\t\"l_setterLevel_switchMultilevel\":\"Code für Aktion\",\n\t\"h_setterLevel_switchMultilevel\":\"%% steht für einen Wert von 0 bis 99\",\n\t\"l_getter_value\":\"Code um einen Wert abzufragen\",\n\t\"h_getter_switchMultilevel\":\"Rückgabe eines Wertes von 0 bis 99\",\n\t\"l_getterPollInterval\":\"Abfrageintervall in Sekunden:\",\n\t\"h_getterPollInterval\":\"0 oder eine leere Eingabe deaktivieren die periodische Abfrage (explizite Update-Kommandos werden weiterhin ausgeführt)\",\n\t\"rl_updateOnAction\": \"Update value on action\",\n\t\"h_updateOnAction\": \"On actions (on/off/dimming) update value accordingly before it is polled\",\n\t\"rl_skipEventIfSameValue\": \"Don't send update event if value has not changed\",\n\t\"h_skipEventIfSameValue\": \"If same value is reported, do not send update event. In this case no update listeners will be called.\"\n}"
  },
  {
    "path": "modules/CodeDevice/lang/en.json",
    "content": "{\n\t\"m_title\":\"Virtual Device (JavaScript)\",\n\t\"m_descr\":\"The use of this app requires solid knowledge of JavaScript programming. This app allows creating a new virtual device based on JavaScript code. This JavaScript can poll and calculate any data from anywhere as long as this is doable using JavaScript. The device can be a sensor just showing data but it can also be an actor executing some JavaScript code.<br><br>Settings:<br><ul><li>Choose type of device</li><li>Set the code for actions</li><li>Set the code to get the value</li><li>Set the polling interval</li></ul></br>Example: The app shall create an element showing randomly 'on' or 'off'. The JavaScript Code used is: Math.random() > 0.5 ? 'on' : 'off'</br></br>You can create a virtual device without code and update the value using the HTTP API, for example:</br>http://192.168.1.108:8083/JS/Run/controller.devices.get('Code_Device_sensorMultilevel_38').set('metrics:level',50)</br>http://192.168.1.108:8083/JS/Run/controller.devices.get('Code_Device_sensorBinary_39').set('metrics:level','on')\",\n\t\"l_icon\":\"Icon\",\n\t\"l_setterOn_toggleButton\":\"Code for action On\",\n\t\"h_getter_sensorBinary\":\"Should return 'on' or 'off' values\",\n\t\"h_getter_sensorMultilevel\":\"Should return number\",\n\t\"l_scale_sensorMultilevel\":\"Sensor scale\",\n\t\"l_setterOn_switchBinary\":\"Code for action On\",\n\t\"h_setterOn_switchBinary\":\"%% will represent value 'on'\",\n\t\"l_setterOff_switchBinary\":\"Code for action Off\",\n\t\"h_setterOff_switchBinary\":\"%% will represent value 'off'\",\n\t\"h_getter_switchBinary\":\"Should return 'on' or 'off' value\",\n\t\"l_setterLevel_switchMultilevel\":\"Code for action\",\n\t\"h_setterLevel_switchMultilevel\":\"%% will represent value from 0 to 99\",\n\t\"l_getter_value\":\"Code to get value\",\n\t\"h_getter_switchMultilevel\":\"Should return value from 0 to 99\",\n\t\"l_getterPollInterval\":\"Interval in seconds between polling requests\",\n\t\"h_getterPollInterval\":\"Empty or 0 to disable periodical requests (explicit update command will still initiate request process)\",\n\t\"rl_updateOnAction\": \"Update value on action\",\n\t\"h_updateOnAction\": \"On actions (on/off/dimming) update value accordingly before it is polled\",\n\t\"rl_skipEventIfSameValue\": \"Don't send update event if value has not changed\",\n\t\"h_skipEventIfSameValue\": \"If same value is reported, do not send update event. In this case no update listeners will be called.\"\n}\n"
  },
  {
    "path": "modules/CodeDevice/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Виртуальное устройство (JavaScript)\",\n\t\"m_descr\":\"Использование этого приложения требует базовых знаний программирования на JavaScript. Возможно создать виртуальное устройство исполняющее любой JavaScript код или виртуальный датчик, который периодически опрашивает и вычисляет данные.</br></br>Настройка:<ul><li>Выберите тип устройства</li><li>Задайте код для действий</li><li>Задайте код для получения значения</li><li>Задайте интервал опроса</li></ul></br>Например: Бинарный датчик, который произвольно показывает состояние 'on' или 'off'. Период опроса: 5 секунд. Код для получения значения: Math.random() > 0.5 ? 'on' : 'off'</br></br>Можно создать виртуальное устройство без кода и обновлять значение с помощью HTTP API, например:</br>http://192.168.1.108:8083/JS/Run/controller.devices.get('Code_Device_sensorMultilevel_38').set('metrics:level',50)</br>http://192.168.1.108:8083/JS/Run/controller.devices.get('Code_Device_sensorBinary_39').set('metrics:level','on')\",\n\t\"l_icon\":\"Иконка\",\n\t\"l_setterOn_toggleButton\":\"Код для действия Включить\",\n\t\"h_getter_sensorBinary\":\"Должен вернуть значение 'on' или 'off'\",\n\t\"h_getter_sensorMultilevel\":\"Должен вернуть число\",\n\t\"l_scale_sensorMultilevel\":\"Единица измерения\",\n\t\"l_setterOn_switchBinary\":\"Код для действия Включить\",\n\t\"h_setterOn_switchBinary\":\"Символы %% содержат значение 'on'\",\n\t\"l_setterOff_switchBinary\":\"Код для действия Выключить\",\n\t\"h_setterOff_switchBinary\":\"Символы %% содержат значение 'off'\",\n\t\"h_getter_switchBinary\":\"Должен вернуть значение 'on' или 'off'\",\n\t\"l_setterLevel_switchMultilevel\":\"Код для действия\",\n\t\"h_setterLevel_switchMultilevel\":\"Символы %% содержат значение от 0 до 99\",\n\t\"l_getter_value\":\"Код для получения значения\",\n\t\"h_getter_switchMultilevel\":\"Должен вернуть значение от 0 до 99\",\n\t\"l_getterPollInterval\":\"Интервал в секундах опроса значения\",\n\t\"h_getterPollInterval\":\"Пусто или 0 отключают периодический опрос (запросить значение можно вручную командой update)\",\n\t\"rl_updateOnAction\": \"Менять состояние при действиях\",\n\t\"h_updateOnAction\": \"При действиях с устройством (включение/выключение/диммирование), менять состояние на соответствующее действию, не дожидаясь получения опроса значения.\",\n\t\"rl_skipEventIfSameValue\": \"Не отправлять событие обновления, если значение не поменялось\",\n\t\"h_skipEventIfSameValue\": \"Если получено значение, совпадающее с предыдущим, не обновлять значение. В этом случае не будут вызваны подписчики на события обновления.\"\n}"
  },
  {
    "path": "modules/CodeDevice/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"developers_stuff\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\": \"CodeDevice\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"deviceType\": \"\",\n\t\t\"iconSensorBinary\": \"\",\n\t\t\"iconSensorMultilevel\": \"\",\n\t\t\"setterOn_toggleButton\": \"\",\n\t\t\"getter_sensorBinary\": \"\",\n\t\t\"getterPollInterval_sensorBinary\": 0,\n\t\t\"getter_sensorMultilevel\": \"\",\n\t\t\"getterPollInterval_sensorMultilevel\": 0,\n\t\t\"scale_sensorMultilevel\": \"\",\n\t\t\"setterOn_switchBinary\": \"\",\n\t\t\"setterOff_switchBinary\": \"\",\n\t\t\"getter_switchBinary\": \"\",\n\t\t\"getterPollInterval_switchBinary\": 0,\n\t\t\"setterLevel_switchMultilevel\": \"\",\n\t\t\"getter_switchMultilevel\": \"\",\n\t\t\"getterPollInterval_switchMultilevel\": 0,\n\t\t\"updateOnAction\": false,\n\t\t\"skipEventIfSameValue\": false\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"deviceType\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"toggleButton\", \"sensorBinary\", \"sensorMultilevel\", \"switchBinary\", \"switchMultilevel\"],\n\t\t\t\t\"default\": \"toggleButton\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"iconSensorBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"alarm\", \"motion\", \"smoke\", \"co\", \"flood\",\"cooling\",\"tamper\",\"door\"],\n\t\t\t\t\"default\": \"alarm\", \n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"iconSensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"temperature\", \"luminosity\", \"energy\", \"humidity\", \"barometer\",\"seismic\",\"ultraviolet\",\"acceleration_x\",\"acceleration_y\",\"acceleration_z\"],\n\t\t\t\t\"default\": \"temperature\", \n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterOn_toggleButton\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_sensorBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorBinary\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_sensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorMultilevel\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"scale_sensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterOn_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterOff_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_switchBinary\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterLevel_switchMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_switchMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_switchMultilevel\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"updateOnAction\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"skipEventIfSameValue\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"deviceType\": {\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"iconSensorBinary\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"label\": \"__l_icon__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"iconSensorMultilevel\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"label\": \"__l_icon__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterOn_toggleButton\": {\n\t\t\t\t\"label\": \"__l_setterOn_toggleButton__\",\n\t\t\t\t\"placeholder\": \"somefunction()\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"toggleButton\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_sensorBinary\": {\n\t\t\t\t\"label\": \"__l_getter_value__\",\n\t\t\t\t\"placeholder\": \"somefunction()\",\n\t\t\t\t\"helper\": \"__h_getter_sensorBinary__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorBinary\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_getter_value__\",\n\t\t\t\t\"placeholder\": \"somefunction()\",\n\t\t\t\t\"helper\": \"__h_getter_sensorMultilevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scale_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_scale_sensorMultilevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterOn_switchBinary\": {\n\t\t\t\t\"label\": \"__l_setterOn_switchBinary__\",\n\t\t\t\t\"placeholder\": \"somefunction(%%)\",\n\t\t\t\t\"helper\": \"__h_setterOn_switchBinary__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterOff_switchBinary\": {\n\t\t\t\t\"label\": \"__l_setterOff_switchBinary__\",\n\t\t\t\t\"placeholder\": \"somefunction(%%)\",\n\t\t\t\t\"helper\": \"__h_setterOff_switchBinary__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_switchBinary\": {\n\t\t\t\t\"label\": \"__l_getter_value__\",\n\t\t\t\t\"placeholder\": \"somefunction()\",\n\t\t\t\t\"helper\": \"__h_getter_switchBinary__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_switchBinary\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterLevel_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_setterLevel_switchMultilevel__\",\n\t\t\t\t\"placeholder\": \"somefunction(%%)\",\n\t\t\t\t\"helper\": \"__h_setterLevel_switchMultilevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_getter_value__\",\n\t\t\t\t\"placeholder\": \"somefunction()\",\n\t\t\t\t\"helper\": \"__h_getter_switchMultilevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"updateOnAction\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_updateOnAction__\",\n\t\t\t\t\"helper\": \"__h_updateOnAction__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": [ \"switchBinary\", \"switchMultilevel\"]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"skipEventIfSameValue\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_skipEventIfSameValue__\",\n\t\t\t\t\"helper\": \"__h_skipEventIfSameValue__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/CorrectValue/index.js",
    "content": "/*** CorrectValue Z-Way Home Automation module *************************************\n\n Version: 1.0.0\n (c) Z-Wave.Me, 2017\n\n -----------------------------------------------------------------------------\n Author: Yurkin Vitaliy   <aivs@z-wave.me>\n Description:\n\t Correct value of sensors like temperature, humidity, etc.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction CorrectValue (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCorrectValue.super_.call(this, id, controller);\n};\n\ninherits(CorrectValue, AutomationModule);\n\n_module = CorrectValue;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCorrectValue.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tCorrectValue.super_.prototype.init.call(this, config);\n\n\t// Remember \"this\" for detached callbacks (such as event listener callbacks)\n\tvar self = this;\n\n\tthis.handler = function (vDev) {\n\t\tvar value = parseFloat(vDev.get(\"metrics:level\"));\n\t\tself.vDevNew.set(\"metrics:level\", value + parseFloat(self.config.correctionValue));\n\t};\n\n\tthis.createCorrectedDev = function () {\n\t\tvar sensor = self.controller.devices.get(self.config.device);\n\t\tsensor.set(\"visibility\", !(self.config.hide));\n\n\t\tself.vDevNew = self.controller.devices.create({\n\t\t\t\tdeviceId: self.id+\"_CorrectValue_\"+self.config.correctionValue,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: sensor.get(\"metrics:probeTitle\"),\n\t\t\t\t\t\tscaleTitle: sensor.get(\"metrics:scaleTitle\"),\n\t\t\t\t\t\tlevel: parseFloat(sensor.get(\"metrics:level\")) + parseFloat(self.config.correctionValue),\n\t\t\t\t\t\ticon: sensor.get(\"metrics:icon\"),\n\t\t\t\t\t\ttitle: sensor.get(\"metrics:title\") + \" \" + self.config.correctionValue,\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\tmoduleId: self.id\n\t\t});\n\n\t\t// Setup metric update event listener\n\t\tself.controller.devices.on(self.config.device, 'change:metrics:level', self.handler);\n\t}\n\n\tthis.deviceCreated = function (vDev) {\n\t\tif (vDev.id === self.config.device) {\n\t\t\tself.createCorrectedDev();\n\t\t}\n\t}\n\n\tthis.deviceRemoved = function (vDev) {\n\t\tif (vDev.id === self.controller.devices.get(self.config.device)) {\n\t\t\tself.controller.devices.remove(self.id+\"_Corrected_\"+self.config.correctionValue);\n\t\t}\n\t}\n\n\t// Bind to event \"Added new device\" -- > Bind to new device\n\tthis.controller.devices.on('created', this.deviceCreated);   \n\n\t // Bind to event \"Removed device\" --> Unbind device\n\tthis.controller.devices.on('removed', this.deviceRemoved); \n\n\tif (this.controller.devices.get(this.config.device)) {\n\t\tself.createCorrectedDev();\n\t}\n\n};\n\nCorrectValue.prototype.stop = function () {\n\tCorrectValue.super_.prototype.stop.call(this);\n\tthis.controller.devices.off(this.config.device, 'change:metrics:level', this.handler);\n\tthis.controller.devices.remove(this.id+\"_Corrected_\"+this.config.correctionValue);\n};\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n// This module doesn't have any additional methods\n"
  },
  {
    "path": "modules/CorrectValue/lang/de.json",
    "content": "{\n\t\"m_title\":\"Correct sensor value\",\n\t\"m_descr\":\"If sensor show not real value, you can correct it\",\n\t\"l_dev\":\"Sensor\",\n\t\"l_correctionValue\":\"Correction value\",\n\t\"h_correctionValue\":\"As example, +4 or -3\",\n\t\"rl_hide_original\":\"Hide original sensor\"\n}"
  },
  {
    "path": "modules/CorrectValue/lang/en.json",
    "content": "{\n\t\"m_title\":\"Correct sensor value\",\n\t\"m_descr\":\"If sensor show not real value, you can correct it\",\n\t\"l_dev\":\"Sensor\",\n\t\"l_correctionValue\":\"Correction value\",\n\t\"h_correctionValue\":\"As example, +4 or -3\",\n\t\"rl_hide_original\":\"Hide original sensor\"\n}"
  },
  {
    "path": "modules/CorrectValue/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Корректировка значения датчика\",\n\t\"m_descr\":\"Если датчик отображает не точное значение, то можно задать значение корректировки, как + так и -.\",\n\t\"l_dev\":\"Датчик\",\n\t\"l_correctionValue\":\"Корректировка\",\n\t\"h_correctionValue\":\"Например, +4 или -3\",\n\t\"rl_hide_original\":\"Скрыть оригинальный датчик\"\n}"
  },
  {
    "path": "modules/CorrectValue/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"device_enhancements\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"CorrectValue\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"correctionValue\": 0,\n\t\t\"device\": \"\",\n\t\t\"hide\":true\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"device\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"correctionValue\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"hide\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"device\": {\n\t\t\t\t\"label\": \"__l_dev__\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t},\n\t\t\t\"correctionValue\": {\n\t\t\t\t\"label\": \"__l_correctionValue__\",\n\t\t\t\t\"helper\": \"__h_correctionValue__\"\n\t\t\t},\n\t\t\t\"hide\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_hide_original__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/CounterTriggeringSensor/index.js",
    "content": "/*** Counter triggering binary sensor Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Yurkin Vitaliy <aivs@z-wave.me>\nDescription: The module considers how many times have triggered the sensor. \nUsed in the calculation of water flow.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction CounterTriggeringSensor (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCounterTriggeringSensor.super_.call(this, id, controller);\n}\n\ninherits(CounterTriggeringSensor, AutomationModule);\n_module = CounterTriggeringSensor;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCounterTriggeringSensor.prototype.init = function (config) {\n\tCounterTriggeringSensor.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"CounterTriggeringSensor_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\tmetrics: {\n\t\t\t\tlevel: this.config.initialValue,\n\t\t\t\ticon: \"meter\",\n\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t}\n\t\t},\n\t\toverlay: {\n\t\t\tmetrics: {\n\t\t\t\tscaleTitle: this.config.scaleTitle\n\t\t\t}\n\t\t},\n\t\thandler: function(command, args) {console.log(\"CounterTriggeringSensor_\" + this.id + \" updated\")},\n\t\tmoduleId: this.id\n\t});\n\n\n\t// Plus 1, when binary sensor triggered\n\tthis.handler = function (sensor) {\n\t\tif (sensor.get(\"metrics:level\") === self.config.eventSensor) {\n\t\t\tvar currentValue = parseFloat(self.vDev.get(\"metrics:level\"));\n\t\t\tif (isNaN(currentValue)) {\n\t\t\t\t\tcurrentValue = 0;\n\t\t\t}\n\t\t\tcurrentValue = currentValue + self.config.valueToAdd\n\t\t\tself.vDev.set(\"metrics:level\", currentValue);\n\t\t}\n\t}\n\t// Setup metric update event listener\n\tthis.controller.devices.on(this.config.binarySensor, 'change:metrics:level', this.handler);\n};\n\nCounterTriggeringSensor.prototype.stop = function () {\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tthis.controller.devices.off(this.config.binarySensor, 'change:metrics:level', this.handler);\n\n\tCounterTriggeringSensor.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/CounterTriggeringSensor/lang/de.json",
    "content": "{\n\t\"m_title\":\"Counter triggering binary sensor\",\n\t\"m_descr\":\"The module considers how many times have triggered the sensor. Used in the calculation of water flow.\",\n\t\"l_BinarySensor\":\"Binary sensor\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_EventSensor\":\"Event from sensor\",\n\t\"l_InitialValue\":\"Initial value\",\n\t\"l_ValueToAdd\":\"Value to add\",\n\t\"l_ScaleTitle\":\"Sensoreinheit\"\n}"
  },
  {
    "path": "modules/CounterTriggeringSensor/lang/en.json",
    "content": "{\n\t\"m_title\":\"Counter triggering binary sensor\",\n\t\"m_descr\":\"The module considers how many times have triggered the sensor. Used in the calculation of water flow.\",\n\t\"l_BinarySensor\":\"Binary sensor\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_EventSensor\":\"Event from sensor\",\n\t\"l_InitialValue\":\"Initial value\",\n\t\"l_ValueToAdd\":\"Value to add\",\n\t\"l_ScaleTitle\":\"Sensor scale\"\n}"
  },
  {
    "path": "modules/CounterTriggeringSensor/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Счетчик срабатывания бинарного датчика\",\n\t\"m_descr\":\"Модуль считает сколько раз сработал датчик. Используется в подсчете расхода воды.\",\n\t\"l_BinarySensor\":\"Бинарный датчик\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_EventSensor\":\"Событие датчика\",\n\t\"l_InitialValue\":\"Начальное значение\",\n\t\"l_ValueToAdd\":\"Прибавляемое значение\",\n\t\"l_ScaleTitle\":\"Единица измерения\"\n}"
  },
  {
    "path": "modules/CounterTriggeringSensor/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"CounterTriggeringSensor\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"binarySensor\": null,\n\t\t\"eventSensor\": \"on\",\n\t\t\"initialValue\":\"0.0\",\n\t\t\"valueToAdd\": \"1.0\",\n\t\t\"scaleTitle\": \"L\"\n\t}, \n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"binarySensor\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"eventSensor\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [\"on\", \"off\"]\n\t\t\t},\n\t\t\t\"initialValue\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"valueToAdd\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"scaleTitle\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"binarySensor\": {\n\t\t\t\t\"label\": \"__l_BinarySensor__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t},\n\t\t\t\"eventSensor\": {\n\t\t\t\t\"label\": \"__l_EventSensor__\",\n\t\t\t\t\"optionLabels\": [\"__on__\", \"__off__\"]\n\t\t\t},\n\t\t\t\"initialValue\": {\n\t\t\t\t\"label\": \"__l_InitialValue__\"\n\t\t\t},\n\t\t\t\"valueToAdd\": {\n\t\t\t\t\"label\": \"__l_ValueToAdd__\"\n\t\t\t},\n\t\t\t\"scaleTitle\": {\n\t\t\t\t\"label\": \"__l_ScaleTitle__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/Cron/index.js",
    "content": "/*** Cron ZAutomation module **************************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2013\n-------------------------------------------------------------------------------\nAuthors:\n   Serguei Poltorak <ps@z-wave.me>\n   Gregory Sitnin <sitnin@z-wave.me>\n\nDescription:\n   This modules impements Unix cron like scheduler.\n\nEmits:\n  - [any event asked by other modules]\n\nListens:\n  - cron.addTask\n\t- String: emitted event name\n\t- Object: task schedule\n\t  - Mixed (null = any; [from, to, divider]; Number = exact): minute\n\t  - Mixed: hour\n\t  - Mixed: weekDay\n\t  - Mixed: day\n\t  - Mixed: month\n\t- Mixed (null; Array): eventArguments\n  - cron.removeTask\n\t- String: emitted event name to be removed\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Cron (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCron.super_.call(this, id, controller);\n\n\t// Create instance variables\n\tthis.schedules = {};\n\tthis.timer;\n\tthis.bounds = {\n\t\tminute: {\n\t\t\tfrom: 0,\n\t\t\tto: 59\n\t\t},\n\t\thour: {\n\t\t\tfrom: 0,\n\t\t\tto: 23\n\t\t},\n\t\tday: {\n\t\t\tfrom: 0,\n\t\t\tto: 30\n\t\t},\n\t\tweekDay: {\n\t\t\tfrom: 0,\n\t\t\tto: 6\n\t\t},\n\t\tmonth: {\n\t\t\tfrom: 0,\n\t\t\tto: 11\n\t\t}\n\t};\n\tthis.shift = {\n\t\tminute: 0,\n\t\thour: 0,\n\t\tday: 1,\n\t\tweekDay: 0,\n\t\tmonth: 1\n\t};\n\tthis.lastFired = 0;\n}\n\ninherits(Cron, AutomationModule);\n\n_module = Cron;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCron.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tCron.super_.prototype.init.call(this, config);\n\n\t// Remember \"this\" for detached callbacks (such as event listener callbacks)\n\tvar self = this;\n\n\t// Setup metric update event listener\n\tthis.controller.on('cron.addTask', function (eventName, schedule, eventArgs) {\n\t  if (!self.schedules.hasOwnProperty(eventName)) {\n\t\tself.schedules[eventName] = [];\n\t  }\n\t  var time = {\"time\": schedule};\n\t  self.schedules[eventName].push([self.renderSchedule(schedule), time, eventArgs]);\n\n\t  self.config.schedules = self.schedules;\n\t  // console.log(JSON.stringify(self.renderSchedule(schedule))); // debug !\n\t});\n\n\tthis.controller.on('cron.removeTask', function (eventName) {\n\t  delete self.schedules[eventName];\n\n\t  self.config.schedules = self.schedules;\n\t});\n\n\tthis.timer = setInterval(function () {\n\t\tvar date = new Date();\n\t\tvar timestampMin = Math.floor(date.getTime() / 60000);\n\n\t\tif (self.lastFired === timestampMin)\n\t\t\treturn; // this minute is already handled\n\n\t\tself.lastFired = timestampMin;\n\t\tvar curTime = {\n\t\t\tminute: date.getMinutes(),\n\t\t\thour: date.getHours(),\n\t\t\tday: date.getDate() - 1,\n\t\t\tweekDay: date.getDay(), // NOTE! Sunday is 0. Handle this in the UI!!!! !@#%^&\n\t\t\tmonth: date.getMonth()\n\t\t};\n\n\t\tObject.keys(self.schedules).forEach(function (eventName) {\n\t\t\tvar schedules_arr = self.schedules[eventName];\n\n\t\t\tschedules_arr.forEach(function (schedule_pair) {\n\t\t\t\tvar flag = true;\n\n\t\t\t\tvar keys = [\"minute\", \"hour\", \"day\", \"weekDay\", \"month\"];\n\t\t\t\tfor (var k = 0; k < keys.length; k++) {\n\t\t\t\t\tif (-1 === schedule_pair[0][keys[k]].indexOf(curTime[keys[k]])) {\n\t\t\t\t\t\tflag = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (flag) {\n\t\t\t\t\tself.controller.emit.apply(self.controller, [eventName].concat(schedule_pair[1]));\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}, 1000);\n};\n\nCron.prototype.stop = function () {\n\tCron.super_.prototype.stop.call(this);\n\n\tclearInterval(this.timer);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nCron.prototype.renderTimeRange = function (range, bounds, shift) {\n\tvar r = [], f, t, s;\n\n\tif (range === null) {\n\t\tf = bounds.from;\n\t\tt = bounds.to;\n\t\ts = 1;\n\t} else if (typeof(range) === \"number\") {\n\t\tif (range - shift < bounds.from || range - shift > bounds.to) {\n\t\t\tconsole.log(\"ERROR: value \" + range.toString() + \" is out of range \" + bounds.from.toString() + \"..\" + bounds.to.toString());\n\t\t\treturn [];\n\t\t}\n\t\tf = range - shift;\n\t\tt = range - shift;\n\t\ts = 1;\n\t} else if (typeof(range) === \"object\" && Array.isArray(range) && range.length == 3) {\n\t\tif (range[0] - shift < bounds.from || range[1] - shift > bounds.to || range[0] > range[1]) {\n\t\t\tconsole.log(\"ERROR: value \" + range[0].toString() + \"..\" + range[1].toString() + \" is should not be outside of range \" + bounds.from.toString() + \"..\" + bounds.to.toString());\n\t\t\treturn [];\n\t\t}\n\t\tf = range[0] - shift;\n\t\tt = range[1] - shift;\n\t\ts = range[2];\n\t}\n\n\tfor (var n = f; n <= t; n+=s) {\n\t\tr.push(n);\n\t}\n\n\treturn r;\n};\n\nCron.prototype.renderSchedule = function (schedule) {\n\tvar renderedSchedule = {};\n\n\tvar self = this;\n\n\t[\"minute\", \"hour\", \"day\", \"weekDay\", \"month\"].forEach(function(key) {\n\t\trenderedSchedule[key] = self.renderTimeRange(schedule[key], self.bounds[key], self.shift[key]);\n\t});\n\n\treturn renderedSchedule;\n};\n"
  },
  {
    "path": "modules/Cron/lang/de.json",
    "content": "{\n\t\"m_title\":\"Systemuhr (CRON)\",\n\t\"m_descr\":\"Diese App generiert die ganze Zeit gesteuerte Ereignisse und sollte aus diesem Grund stets aktiviert sein.  In der Verwendung mit diesem Modul kann sehr viel falsch gemacht werden, daher lassen Sie es unberührt, solange es nicht wirklich benötigt wird.\"\n}"
  },
  {
    "path": "modules/Cron/lang/en.json",
    "content": "{\n\t\"m_title\":\"System Clock (CRON)\",\n\t\"m_descr\":\"This app generates all time driven events and should therefore be active all the time. There is nothing to be done right with the module but a lot of things that can be done wrong. This means, don't touch it unless it is really needed.\"\n}\n"
  },
  {
    "path": "modules/Cron/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Cron планировщик\",\n\t\"m_descr\":\"Планировщик используют другие модули.\"\n}"
  },
  {
    "path": "modules/Cron/module.json",
    "content": "{\n\t\"singleton\": true,\n\t\"dependencies\": [],\n\t\"category\": \"basic_gateway_modules\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"Cron\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"schedules\": {}\n\t},\n\t\"schema\": {\n\t},\n\t\"options\": {\n\t}\n}\n"
  },
  {
    "path": "modules/CustomUserCode/index.js",
    "content": "  /*** CustomUserCode ZAutomation module ****************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2013\n\n-------------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tThis module executes custom JS code listed in configuration parameters.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction CustomUserCode (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCustomUserCode.super_.call(this, id, controller);\n}\n\ninherits(CustomUserCode, AutomationModule);\n\n_module = CustomUserCode;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCustomUserCode.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tCustomUserCode.super_.prototype.init.call(this, config);\n\n\t// TODO: executeJS errors are impossible to catch!\n\t//try {\n\t\texecuteJS(this.config.customCode);\n\t//} catch (e) {\n\t//\t  var langFile = this.loadModuleLang(),\n\t//\t\t   values = this.get(\"metrics:title\");\n\t//\t\t   \n\t//\tthis.addNotification(\"warning\", langFile.err_load + values, \"module\");\n\t//}\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n// This module has no additional methods\n"
  },
  {
    "path": "modules/CustomUserCode/lang/de.json",
    "content": "{\n\t\"m_title\":\"Benutzer JavaScript Code\",\n\t\"m_descr\":\"Die Anwendung dieser App erfordert solide Kenntnisse in der JavaScript Programmierung. Der in dieser App zur Verfügung gestellte Code wird ausgeführt, wenn die App geladen wird. Ein Element kann nicht erstellt werden, jedoch ist es möglich, auf die Inhaber der Netzwerkdaten zuzugreifen. Diese App richtet sich ausschließlich an JavaScript Experten.\",\n\t\"l_options\":\"Ihr JavaScript Code:\",\n\t\"err_load\":\"Das Skript konnte nicht geladen werden: \"\n}"
  },
  {
    "path": "modules/CustomUserCode/lang/en.json",
    "content": "{\n\t\"m_title\":\"Load custom JavaScript code\",\n\t\"m_descr\":\"The use of this app requires solid knowledge of JavaScript programming. The code provided in this app will be executed when the app is loaded. There is no way to create an element but its possible to access the Network data holders. This app is for JavaScript professionals only.\",\n\t\"err_load\":\"Failed to load custom user code: \",\n\t\"l_options\":\"Your JavaScript code:\"\n}"
  },
  {
    "path": "modules/CustomUserCode/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Пользовательский JavaScript код\",\n\t\"m_descr\":\"Позволяет загружать пользовательский JavaScript код после загрузки системы.\",\n\t\"err_load\":\"Не удалось загрузить пользовательский JS код: \",\n\t\"l_options\":\"Ваш JavaScript код:\"\n}"
  },
  {
    "path": "modules/CustomUserCode/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"developers_stuff\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"CustomUserCode\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"customCode\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"customCode\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"toolbarSticky\": true,\n\t\t\"fields\": {\n\t\t\t\"customCode\": {\n\t\t\t\t\"type\": \"textarea\",\n\t\t\t\t\"label\": \"__l_options__\",\n\t\t\t\t\"cols\": 40\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/CustomUserCodeLoader/index.js",
    "content": "  /*** CustomUserCodeLoader ZAutomation module ****************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2013\n\n-------------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tThis module executes custom JS code listed in configuration parameters.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction CustomUserCodeLoader (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCustomUserCodeLoader.super_.call(this, id, controller);\n}\n\ninherits(CustomUserCodeLoader, AutomationModule);\n\n_module = CustomUserCodeLoader;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCustomUserCodeLoader.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tCustomUserCodeLoader.super_.prototype.init.call(this, config);\n\n\tthis.config.customCodeFiles.forEach(function (file) {\n\t\tif (!file)\n\t\t\treturn;\n\t\tvar stat = fs.stat(file);\n\t\tif (stat && stat.type === \"file\") {\n\t\t\texecuteFile(file);\n\t\t} else {\n\t\t\tconsole.log(\"File \" + file + \" not found\");\n\t\t}\n\t});\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n// This module has no additional methods\n"
  },
  {
    "path": "modules/CustomUserCodeLoader/lang/de.json",
    "content": "{\n\t\"m_title\":\"Lade JavaScript-Dateien von Benutzer\",\n\t\"m_descr\":\"Die Anwendung dieser App erfordert solide Kenntnisse in der JavaScript Programmierung. Der in der Datei bereitgestellte Code, auf welchen die App Einstellung hinweist, wird ausgeführt, wenn die App geladen wird. Ein Element kann nicht erstellt werden, jedoch ist es möglich, auf die Inhaber der Netzwerkdaten zuzugreifen. Diese App richtet sich ausschließlich an JavaScript Experten.\",\n\t\"customCodeFiles_title\":\"Dateiname\",\n\t\"err_load\":\"JavaScript-Datei konnte nicht geladen werden: \",\n\t\"h_options\":\"Fügt Pfad relativ zum 'automation' Verzeichnis hinzu.\"\n}"
  },
  {
    "path": "modules/CustomUserCodeLoader/lang/en.json",
    "content": "{\n\t\"m_title\":\"Load custom JavaScript file\",\n\t\"m_descr\":\"The use of this app requires solid knowledge of JavaScript programming. The code provided in the file the app setup points to will be executed when the app is loaded. There is no way to create an element but its possible to access the Network data holders. This app is for JavaScript professionals only.\",\n\t\"customCodeFiles_title\":\"File name\",\n\t\"err_load\":\"Failed to load JavaScript file: \",\n\t\"h_options\":\"Add paths to files relative to automation/ folder.\"\n}"
  },
  {
    "path": "modules/CustomUserCodeLoader/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Пользовательский JavaScript файл\",\n\t\"m_descr\":\"Позволяет загружать пользовательские JavaScript файлы из папки automation/ после загрузки системы.\",\n\t\"customCodeFiles_title\":\"Имя файла\",\n\t\"err_load\":\"Не удалось загрузить пользовательский JS файл: \",\n\t\"h_options\":\"Указывайте полный путь до JS файла относительно папки automation/.\"\n}"
  },
  {
    "path": "modules/CustomUserCodeLoader/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"developers_stuff\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"CustomUserCodeLoader\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\"title\": \"__m_title__\",\n\t\"description\": \"__m_descr__\",\n\t\"customCodeFiles\": [ ]\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"customCodeFiles\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"title\": \"__customCodeFiles_title__\",\n\t\t\t\t\t\"type\": \"string\"\t  \n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"customCodeFiles\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"helper\": \"__h_options__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/CustomUserCodeZWay/index.js",
    "content": "  /*** CustomUserCodeZWay ZAutomation module ****************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2015\n\n-------------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tThis module executes custom JS code listed in configuration parameters on Z-Way start/stop.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction CustomUserCodeZWay (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tCustomUserCodeZWay.super_.call(this, id, controller);\n}\n\ninherits(CustomUserCodeZWay, AutomationModule);\n\n_module = CustomUserCodeZWay;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nCustomUserCodeZWay.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tCustomUserCodeZWay.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\t\n\tthis.loaded = false;\n\n\tthis.bindZWay = function (zwayName) {\n\t\tif (zwayName !== self.config.zway) {\n\t\t   return;\n\t\t}\n\n\t\tself.loaded = true;\n\t\n\t\t// TODO: executeJS errors are impossible to catch!\n\t\t//try {\n\t\t\texecuteJS(self.config.customCodeOnLoad);\n\t\t//} catch (e) {\n\t\t//\tvar langFile = this.loadModuleLang();\n\t\t//\t\t   \n\t\t//\tthis.addNotification(\"warning\", langFile.err_load, \"module\");\n\t\t//}\n\t};\n\n\tthis.unbindZWay = function (zwayName) {\n\t\tif (zwayName !== self.config.zway) {\n\t\t\treturn;\n\t\t}\n\n\t\tself.loaded = false;\n\t\n\t\t// TODO: executeJS errors are impossible to catch!\n\t\t//try {\n\t\t\texecuteJS(self.config.customCodeOnUnload);\n\t\t//} catch (e) {\n\t\t//\tvar langFile = this.loadModuleLang();\n\t\t//\t\t   \n\t\t//\tthis.addNotification(\"warning\", langFile.err_load, \"module\");\n\t\t//}\n\t};\n\n\tif (global.ZWave && global.ZWave[this.config.zway]) {\n\t\tthis.bindZWay(this.config.zway);\n\t}\n\tglobal.controller.on(\"ZWave.register\", this.bindZWay);\n\tglobal.controller.on(\"ZWave.unregister\", this.unbindZWay);\n};\n\nCustomUserCodeZWay.prototype.stop = function() {\n\tif (this.loaded === true) {\n\t\tthis.unbindZWay(this.config.zway);\n\t}\n\t\n\tglobal.controller.off(\"ZWave.register\", this.bindZWay);\n\tglobal.controller.off(\"ZWave.unregister\", this.unbindZWay);\n\t\n\tCustomUserCodeZWay.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n// This module has no additional methods\n"
  },
  {
    "path": "modules/CustomUserCodeZWay/lang/de.json",
    "content": "{\n\t\"m_title\":\"Benutzer JavaScript Code für Z-Wave Applikation\",\n\t\"m_descr\":\"Die Anwendung dieser App erfordert solide Kenntnisse in der JavaScript Programmierung. Der in dieser App zur Verfügung gestellte Code wird ausgeführt, wenn die App geladen wird. Ein Element kann nicht erstellt werden, jedoch ist es möglich, auf die Inhaber der Netzwerkdaten zuzugreifen. Diese App richtet sich ausschließlich an JavaScript Experten.\",\n\t\"err_load\":\"Das Skript konnte nicht geladen werden: \"\n\t\"l_choose_zway\":\"Z-Way instance for which execute your code:\",\n\t\"l_customCodeOnLoad\":\"Ihr JavaScript code on Z-Way load:\",\n\t\"l_customCodeOnUnload\":\"Ihr JavaScript code on Z-Way unload (for clear restart of Z-Wave application or on UZB plug/unplug):\"\n}"
  },
  {
    "path": "modules/CustomUserCodeZWay/lang/en.json",
    "content": "{\n\t\"m_title\":\"Load custom JavaScript code for Z-Wave application\",\n\t\"m_descr\":\"The use of this app requires solid knowledge of JavaScript programming. The code provided in this app will be executed when Z-Wave module is loaded. There is no way to create an element but its possible to access the Network data holders. This app is for JavaScript professionals only.\",\n\t\"err_load\":\"Failed to load custom user code: \",\n\t\"l_choose_zway\":\"Z-Way instance for which execute your code:\",\n\t\"l_customCodeOnLoad\":\"Your JavaScript code on Z-Way load:\",\n\t\"l_customCodeOnUnload\":\"Your JavaScript code on Z-Way unload (for clear restart of Z-Wave application or on UZB plug/unplug):\"\n}"
  },
  {
    "path": "modules/CustomUserCodeZWay/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Пользовательский JavaScript код для приложения Z-Wave\",\n\t\"m_descr\":\"Позволяет загружать пользовательский JavaScript код после загрузки приложения Z-Wave.\",\n\t\"err_load\":\"Не удалось загрузить пользовательский JS код: \",\n\t\"l_choose_zway\":\"Z-Way, для которого выполнять скрипт:\",\n\t\"l_customCodeOnLoad\":\"Ваш JavaScript код при загрузке Z-Way:\",\n\t\"l_customCodeOnUnload\":\"Ваш JavaScript код при выгрузке Z-Way (для перезагрузки приложения Z-Wave или при отключении/подключении стика UZB):\"\n}"
  },
  {
    "path": "modules/CustomUserCodeZWay/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"developers_stuff\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"CustomUserCodeZWay\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"zway\": \"\",\n\t\t\"customCodeOnLoad\": \"\",\n\t\t\"customCodeOnUnload\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"zway\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:zways:zwayName\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"customCodeOnLoad\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t},\n\t\t\t\"customCodeOnUnload\": {\n\t\t\t\t\"type\": \"string\"\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"toolbarSticky\": true,\n\t\t\"fields\": {\n\t\t\t\"zway\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"label\": \"__l_choose_zway__\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:zways:zwayName\"\n\t\t\t},\n\t\t\t\"customCodeOnLoad\": {\n\t\t\t\t\"type\": \"textarea\",\n\t\t\t\t\"label\": \"__l_customCodeOnLoad__\",\n\t\t\t\t\"cols\": 40\n\t\t\t},\n\t\t\t\"customCodeOnUnload\": {\n\t\t\t\t\"type\": \"textarea\",\n\t\t\t\t\"label\": \"__l_customCodeOnUnload__\",\n\t\t\t\t\"cols\": 40\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/DecomposeRGB/index.js",
    "content": "/*** DecomposeRGB Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2021\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me> \n\nDescription:\n\tDecompose device RGB in several dimmers\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction DecomposeRGB (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tDecomposeRGB.super_.call(this, id, controller);\n}\n\ninherits(DecomposeRGB, AutomationModule);\n\n_module = DecomposeRGB;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nDecomposeRGB.prototype.init = function (config) {\n\tDecomposeRGB.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tfunction levelToColor(command, args) {\n\t\tswitch (command) {\n\t\t\tcase \"on\":\n\t\t\t\treturn 255;\n\t\t\tcase \"off\":\n\t\t\t\treturn 0;\n\t\t\tcase \"exact\":\n\t\t\t\treturn parseInt(args.level) * 255.0/99.0\n\t\t\tdefault:\n\t\t\t\treturn 0;\n\t\t}\n\t}\n\t\n\tfunction colorToLevel(color) {\n\t\treturn Math.round(color * 99.0 / 255.0);\n\t}\n\t\n\tvar title = this.getInstanceTitle(),\n\t    devId = \"DecomposeRGB_\" + this.id + \"_\",\n\t    defaults = {\n\t\tdeviceType: \"switchMultilevel\",\n\t\tmetrics: {\n\t\t\ticon: 'multilevel',\n\t\t\ttitle: '',\n\t\t\tlevel: 0\n\t\t}\n\t};\n\n\tdefaults.metrics.title = title + ' Red ' + this.id;\n\tthis.vDevR = this.controller.devices.create({\n\t\tdeviceId: devId + \"R\",\n\t\tdefaults: defaults,\n\t\toverlay: {},\n\t\thandler:  function (command, args) {\n\t\t\tself.handleLevel({ red: levelToColor(command, args) });\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\tdefaults.metrics.title = title + 'Green ' + this.id;\n\tthis.vDevG = this.controller.devices.create({\n\t\tdeviceId: devId + \"G\",\n\t\tdefaults: defaults,\n\t\toverlay: {},\n\t\thandler:  function (command, args) {\n\t\t\tself.handleLevel({ green: levelToColor(command, args) });\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\tdefaults.metrics.title = title + 'Blue ' + this.id;\n\tthis.vDevB = this.controller.devices.create({\n\t\tdeviceId: devId + \"B\",\n\t\tdefaults: defaults,\n\t\toverlay: {},\n\t\thandler:  function (command, args) {\n\t\t\tself.handleLevel({ blue: levelToColor(command, args) });\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\tthis.handleLevel = function(colorObject) {\n\t\tvar vDevRGB = self.controller.devices.get(self.config.rgb);\n\t\tvar c = vDevRGB.get('metrics:color');\n\t\tvDevRGB.performCommand(\"exact\", _.extend({ red: c.r, green: c.g, blue: c.b }, colorObject));\n\t};\n\t\n\tthis.handleRGB = function (vDev) {\n\t\tif (vDev.get(\"metrics:level\") === \"off\") {\n\t\t\tself.vDevR.set(\"metrics:level\", 0);\n\t\t\tself.vDevG.set(\"metrics:level\", 0);\n\t\t\tself.vDevB.set(\"metrics:level\", 0);\n\t\t} else {\n\t\t\tself.vDevR.set(\"metrics:level\", colorToLevel(vDev.get(\"metrics:color:r\")));\n\t\t\tself.vDevG.set(\"metrics:level\", colorToLevel(vDev.get(\"metrics:color:g\")));\n\t\t\tself.vDevB.set(\"metrics:level\", colorToLevel(vDev.get(\"metrics:color:b\")));\n\t\t}\n\t};\n\tthis.controller.devices.on(this.config.rgb, \"change:metrics:level\", this.handleRGB);\n};\n\nDecomposeRGB.prototype.stop = function () {\n\tthis.controller.devices.off(this.config.rgb, \"change:metrics:level\", this.handleRGB);\n\n\tthis.handle = null;\n\t\n\tif (this.vDevR) {\n\t\tthis.controller.devices.remove(this.vDevR.id);\n\t\tthis.vDevR = null;\n\t}\n\tif (this.vDevG) {\n\t\tthis.controller.devices.remove(this.vDevG.id);\n\t\tthis.vDevG = null;\n\t}\n\tif (this.vDevB) {\n\t\tthis.controller.devices.remove(this.vDevB.id);\n\t\tthis.vDevB = null;\n\t}\n\n\tDecomposeRGB.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/DecomposeRGB/lang/en.json",
    "content": "{\n\t\"m_title\":\"Decompose RGB on dimmers\",\n\t\"m_descr\":\"Decompose RGB on three different dimmers to control them individually by colors\",\n\t\"l_rgb\":\"RGB device\"\n}\n"
  },
  {
    "path": "modules/DecomposeRGB/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Разложение RGB на диммеры\",\n\t\"m_descr\":\"Раскладывает RGB устройство на три диммера для индивидуального управления каждым цветом\",\n\t\"l_rgb\":\"Устройство RGB\"\n}"
  },
  {
    "path": "modules/DecomposeRGB/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"legacy_products_workaround\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"DecomposeRGB\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"rgb\": null\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"rgb\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchRGBW:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"rgb\": {\n\t\t\t\t\"label\": \"__l_rgb__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchRGBW:deviceName\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/DelayedScene/index.js",
    "content": "/*** DelayedScene Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tImplements light scene based on virtual devices of type dimmer, switch or anothe scene\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction DelayedScene (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tDelayedScene.super_.call(this, id, controller);\n}\n\ninherits(DelayedScene, AutomationModule);\n\n_module = DelayedScene;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nDelayedScene.prototype.init = function (config) {\n\tDelayedScene.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.timer = null;\n\t\n\tthis.timerHandler = this.handler;\n\n\tthis.triggerHandler = function() {\n\t\tif (self.config.singleTimer && self.timer) {\t\n\t\t\tclearTimeout(self.timer);\n\t\t}\n\t\tself.timer = setTimeout(function() {\n\t\t\tself.timerHandler();\n\t\t}, self.config.delay * 1000);\n\t\t// we do not care about clearing setTimouts in non-singleTimer mode. Just emptying handler if need.\n\t\t// If someone knows how to track many handlers and remove them from a list upon fire - you are welcome to improve the code.\n\t};\n\n\tthis.controller.devices.on(this.config.triggerScene, \"change:metrics:level\", this.triggerHandler);\n};\n\nDelayedScene.prototype.stop = function () {\t\n\tthis.controller.devices.off(this.config.triggerScene, \"change:metrics:level\", this.triggerHandler);\n\n\tif (this.timer) {\n\t\tclearTimeout(this.timer);\n\t}\n\t\n\tthis.timerHandler = function () {}; // this is to clear actions on all remaining setTimouts without clearing them.\n\t// We are emtying not the prototype, but function on instance\n\n\tDelayedScene.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nDelayedScene.prototype.handler = function() {\n\tvar vDev = this.controller.devices.get(this.config.delayedScene);\n\tif (vDev) {\n\t\tvDev.performCommand(\"on\");\n\t}\n};"
  },
  {
    "path": "modules/DelayedScene/lang/de.json",
    "content": "{\n\t\"m_title\":\"Verzögerte Aktion\",\n\t\"m_descr\":\"Diese App kann nach einer gewissen Verzögerungszeit auf eine bereits ausgelöste Szene eine weitere Szene auslösen.Zur Ausführung bedarf die App mindestens zweier Szenen (App Lichtszene): der auslösenden sowie der auszulösenden Szene. Die Verzögerungszeit zwischen beider Szenen kann individuell eingestellt werden.<br><br>Einstellungen:<br><ul><li>Wählen Sie die Szene, die eine weitere Szene auslösen soll.</li><li>Wählen Sie die Szene, die durch die Erste ausgelöst werden soll.</li><li>Definieren Sie die zeitliche Verzögerung in Sekunden zwischen beiden Szenen.</i></ul>\",\n\t\"r_l_options\":\"Starte den Timer neu, wenn eine Szene/Aktion ausgelöst wird.\",\n\t\"l_triggerScene\":\"Szene/Aktion die den Timer startet.\",\n\t\"l_delayedScene\":\"Verzögerte Szene/Aktion:\",\n\t\"l_delay\":\"Verzögerung in Sekunden:\"\n}"
  },
  {
    "path": "modules/DelayedScene/lang/en.json",
    "content": "{\n\t\"m_title\":\"Delayed Action\",\n\t\"m_descr\":\"This app can trigger one scene after a defined delay after another scene was triggered. The app requires at least two scenes (app Light Scene) to function: The triggering scene and the triggered scene. The delay between the two scenes can be defines too.<br><br>Settings:<br><ul><li>Select the scene that shall trigger another scene</li><li>Select the scene that shall be triggered by the first scene</li><li>Define the delay in Seconds between the two scenes</li></ul>\",\n\t\"r_l_options\":\"Restart timer on trigger instead of starting new timer\",\n\t\"l_triggerScene\":\"Scene that trigger timer start\",\n\t\"l_delayedScene\":\"Delayed scene:\",\n\t\"l_delay\":\"Delay in seconds:\"\n}"
  },
  {
    "path": "modules/DelayedScene/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Отложенная сцена\",\n\t\"m_descr\":\"Запуск сцен с задержкой.\",\n\t\"r_l_options\":\"Перезапустить таймер при срабатывании, вместо запуска нового таймера\",\n\t\"l_triggerScene\":\"Сцена, которая запускается при старте таймера\",\n\t\"l_delayedScene\":\"Отложенная сцена:\",\n\t\"l_delay\":\"Задержка в секундах:\"\n}"
  },
  {
    "path": "modules/DelayedScene/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\": \"DelayedScene\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"singleTimer\": true,\n\t\t\"triggerScene\": \"\",\n\t\t\"delayedScene\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"singleTimer\": {\n\t\t\t\t\"type\": \"boolean\"\n\t\t\t},\n\t\t\t\"triggerScene\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"delayedScene\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"delay\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"minimum\": 1\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"singleTimer\": {\n\t\t\t\t\"label\": \"\",\n\t\t\t\t\"rightLabel\": \"__r_l_options__\"\n\t\t\t},\n\t\t\t\"triggerScene\": {\n\t\t\t\t\"label\": \"__l_triggerScene__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t},\n\t\t\t\"delayedScene\": {\n\t\t\t\t\"label\": \"__l_delayedScene__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t},\n\t\t\t\"delay\": {\n\t\t\t\t\"label\": \"__l_delay__\",\n\t\t\t\t\"type\": \"integer\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/DeviceHistory/index.js",
    "content": "/*** DeviceHistory Z-Way HA module *******************************************\n\n Version: 2.0.0\n (c) Z-Wave.Me, 2015\n -----------------------------------------------------------------------------\n Author: Niels Roche <nir@zwave.eu>\n Description:\n Creates a module that stores 24h data of specific devices.\n ******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction DeviceHistory (id, controller) {\n\t// Call supervarructor first (AutomationModule)\n\tDeviceHistory.super_.call(this, id, controller);\n\n\t// define excluded device types\n\tthis.devTypes = ['sensorMultilevel'];\n\tthis.langFile = this.loadModuleLang();\n\n\tthis.history = {};\n\tthis.allDevices = [];\n\tthis.initial = true;\n\tthis.registeredVDevIds = [];\n\tthis.storedDevHistories = [];\n\n\tthis.exclSensors = this.controller.instances.filter(function (instance){\n\t\treturn instance.moduleId === 'SensorsPolling' && instance.active === 'true';\n\t});\n}\n\ninherits(DeviceHistory, AutomationModule);\n\n_module = DeviceHistory;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(DeviceHistory.prototype, {\n\tinit: function (config) {\n\t\tDeviceHistory.super_.prototype.init.call(this, config);\n\n\t\tvar self = this;\n\n\t\tthis.defineHandlers();\n\t\tthis.externalAPIAllow();\n\t\tglobal[\"HistoryAPI\"] = this.HistoryAPI;\n\n\t\t// set history of excluded devices to false\n\t\tthis.config.devices.forEach(function (devId) {\n\t\t\tvar vDevd = self.controller.devices.get(devId);\n\n\t\t\tif (vDevd && vDevd.get('hasHistory') === true) {\n\t\t\t\tvDevd.set('hasHistory', false, {silent: true});\n\t\t\t}\n\t\t});\n\n\t\tthis.initializeDevices();\n\n\t\t// try to restore old histories\n\t\tvar oldHistory = loadObject('history');\n\n\t\tif(!!oldHistory || (_.isArray(oldHistory) && oldHistory.length > 0)) {\n\t\t\toldHistory.forEach(function(history){\n\t\t\t\tif (self.registeredVDevIds.indexOf(history.id) > -1 && self.devTypes.indexOf(history.dT) > -1) {\n\t\t\t\t\tself.history[history.id].set(history.mH);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tsaveObject('history', null, true);\n\t\t\toldHistory = undefined;\n\t\t} else {\n\t\t\toldHistory = undefined;\n\t\t}\n\n\t\tthis.assignDeviceListeners();\n\n\t\t// cleanup storage content list after 30 secs\n\t\tsetTimeout(function(){\n\t\t\t// run first time to setting up histories\n\t\t\tself.setupHistories();\n\t\t}, 30000);\n\t},\n\tstop: function () {\n\t\tvar self = this;\n\n\t\t// remove eventhandlers\n\t\tthis.config.allRegisteredDevices.forEach(function(vDevId) {\n\t\t\tvar vDev = self.controller.devices.get(vDevId);\n\n\t\t\tif(vDev && vDev.get(\"hasHistory\") === true){\n\t\t\t\tvDev.set(\"hasHistory\", false,{ silent: true });\n\t\t\t}\n\n\t\t\tself.removeHistory(vDev);\n\t\t});\n\n\t\tthis.controller.devices.off('created', self.assignHistory);\n\t\tthis.controller.devices.off('removed', this.removeHistory);\n\n\t\tthis.externalAPIRevoke();\n\t\tdelete global[\"HistoryAPI\"];\n\n\n\t\tDeviceHistory.super_.prototype.stop.call(this);\n\t},\n\t// ----------------------------------------------------------------------------\n\t// --- Module methods\n\t// ----------------------------------------------------------------------------\n\tsetHistory: function (vdevId) {\n\n\t\tthis.history[vdevId] = new LimitedArray(\n\t\t\tloadObject('history_' + vdevId) || [],\n\t\t\tfunction (arr) {\n\t\t\t\tsaveObject('history_' + vdevId, arr, true);\n\t\t\t},\n\t\t\t100, // check it every 100 entries\n\t\t\t0, // save unlimited entries, since anyway it is clead based on time limit\n\t\t\tfunction (devHistory){\n\t\t\t\tvar now = Math.floor(Date.now() / 1000);\n\t\t\t\treturn devHistory.id >= (now - 86400);\n\t\t\t}\n\t\t);\n\t},\n\tinitializeDevices: function (){\n\t\tvar self = this;\n\n\t\tthis.config.allRegisteredDevices = this.updateDevList();\n\n\t\t//save into config\n\t\tthis.saveConfig();\n\n\t\t// store whole history data on storage\n\t\tthis.storeData = function(dev) {\n\t\t\ttry {\n\t\t\t\tvar change = {\n\t\t\t\t\tid: Math.round(Date.now() / 1000),\n\t\t\t\t\tl: +dev.get(\"metrics:level\")\n\t\t\t\t};\n\n\t\t\t\tself.history[dev.id].push(change);\n\n\t\t\t} catch(e) {\n\t\t\t\tself.addNotification('error', self.langFile.err_store_history + dev.get('metrics:title') + \" ERROR: \" + e.toString(), 'module');\n\t\t\t}\n\t\t};\n\n\t\t_.forEach(this.config.allRegisteredDevices, function(vdevId){\n\t\t\tvar vDev = self.controller.devices.get(vdevId);\n\n\t\t\t// create new LimitedArray for\n\t\t\tself.setHistory(vdevId);\n\n\t\t\t// set hasHistory true\n\t\t\tif(vDev && vDev.get(\"hasHistory\") === false){\n\t\t\t\tvDev.set(\"hasHistory\", true,{ silent: true });\n\t\t\t}\n\n\t\t\tself.controller.devices.off(vdevId, 'change:metrics:level', self.storeData);\n\t\t\tself.controller.devices.on(vdevId, 'change:metrics:level', self.storeData);\n\t\t});\n\t},\n\tassignDeviceListeners: function () {\n\t\tvar self = this;\n\n\t\tthis.assignHistory = function (vDev) {\n\t\t\tif (vDev && vDev.id &&\n\t\t\t\tvDev.get('permanently_hidden') === false &&\t\t\t  \t\t\t\t\t\t// only none permanently_hidden devices\n\t\t\t\t_.unique(self.config.devices).indexOf(vDev.id) === -1 &&\t  \t\t\t\t// in module excluded devices\n\t\t\t\tself.devTypes.indexOf(vDev.get('deviceType')) > -1 &&\t\t\t\t\t\t// allowed device types\n\t\t\t\tself.exclSensors.indexOf(vDev.id) === -1) {\t\t\t\t\t\t\t\t\t// excluded sensors\n\n\t\t\t\t// add to registered vDev list\n\t\t\t\tself.config.allRegisteredDevices.push(vDev.id);\n\n\t\t\t\t//save into config\n\t\t\t\tself.saveConfig();\n\n\t\t\t\t// set LimitedArray for history\n\t\t\t\tself.setHistory(vDev.id);\n\n\t\t\t\tself.addNotification('info', self.langFile.info_add_history + vDev.get('metrics:title'), 'module');\n\n\t\t\t\t//assign level listener\n\t\t\t\tself.controller.devices.off(vDev.id, 'change:metrics:level', self.storeData);\n\t\t\t\tself.controller.devices.on(vDev.id, 'change:metrics:level', self.storeData);\n\n\t\t\t\tif (vDev && vDev.get('hasHistory') === false) {\n\t\t\t\t\tvDev.set('hasHistory', true, {silent: true});\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tthis.removeHistory = function (vDev) {\n\n\t\t\tif (vDev && self.config.allRegisteredDevices.indexOf(vDev.id) > -1) {\n\t\t\t\t// remove history array\n\t\t\t\tif (self.history[vDev.id]) {\n\t\t\t\t\tself.history[vDev.id].finalize();\n\t\t\t\t\tsaveObject(\"history_\"+vDev.id, null, true);\n\t\t\t\t\tdelete self.history[vDev.id];\n\t\t\t\t}\n\n\t\t\t\tself.addNotification('info', self.langFile.info_remove_history + vDev.get('metrics:title'), 'module');\n\n\t\t\t\tself.controller.devices.off(vDev.id, 'change:metrics:level', self.storeData);\n\n\t\t\t\t// remove from registry\n\t\t\t\tself.config.allRegisteredDevices = self.config.allRegisteredDevices.filter(function(devId){\n\t\t\t\t\treturn devId !== vDev.id;\n\t\t\t\t});\n\n\t\t\t\t// unassign history\n\t\t\t\tif (vDev && vDev.get('hasHistory') === true) {\n\t\t\t\t\tvDev.set('hasHistory', false, {silent: true});\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t// assign listener to new vdev\n\t\tthis.controller.devices.on('created', this.assignHistory);\n\t\tthis.controller.devices.on('removed', this.removeHistory);\n\t},\n\t// return list of registered vDev IDs\n\tupdateDevList: function () {\n\t\tvar self = this;\n\n\t\treturn this.controller.devices.filter(function(dev){\n\t\t\treturn  dev.get('permanently_hidden') === false &&\t\t\t  \t\t\t\t\t\t// only none permanently_hidden devices\n\t\t\t\t_.unique(self.config.devices).indexOf(dev.id) === -1 &&\t  \t\t\t\t\t// in module excluded devices\n\t\t\t\tself.devTypes.indexOf(dev.get('deviceType')) > -1 &&\t\t\t\t\t\t// allowed device types\n\t\t\t\tself.exclSensors.indexOf(dev.id) === -1;\t\t\t\t\t\t\t\t\t// excluded sensors\n\t\t}).map(function(vdev) {\n\t\t\treturn vdev.id;\n\t\t});\n\t},\n\t// setting up device histories\n\tsetupHistories: function(){\n\t\tvar self = this,\n\t\t\tstoredDevHistories = [];\n\n\t\t// cleanup first after all virtual devices are created\n\t\tif(__storageContent) {\n\n\t\t\t_.forEach(__storageContent, function (name) {\n\t\t\t\tif (name.indexOf('history_') > -1) {\n\t\t\t\t\tstoredDevHistories.push(name.substring(8));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tstoredDevHistories.forEach(function(historyFileName){\n\t\t\t\tif (!self.history[historyFileName]) {\n\t\t\t\t\tself.addNotification('info', historyFileName + self.langFile.info_transformation, 'module');\n\t\t\t\t\tsaveObject('history_' + historyFileName, null, true);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\t// --------------- Public HTTP API -------------------\n\texternalAPIAllow: function () {\n\t\tws.allowExternalAccess('HistoryAPI', this.controller.auth.ROLE.USER);\n\t\tws.allowExternalAccess('HistoryAPI.Get', this.controller.auth.ROLE.USER);\n\t\tws.allowExternalAccess('HistoryAPI.Delete', this.controller.auth.ROLE.USER);\n\t},\n\texternalAPIRevoke: function () {\n\t\tws.revokeExternalAccess('HistoryAPI');\n\t\tws.revokeExternalAccess('HistoryAPI.Get');\n\t\tws.revokeExternalAccess('HistoryAPI.Delete');\n\t},\n\tdefineHandlers: function () {\n\t\tvar self = this;\n\n\t\tthis.HistoryAPI = function() {\n\t\t\treturn { status: 400, body: \"Bad HistoryAPI request \" };\n\t\t};\n\n\t\tthis.HistoryAPI.Get = function (url, request) {\n\t\t\tvar q = request.query || null,\n\t\t\t\tsince = parseInt(url.substring(1), 10) || 0,\n\t\t\t\titems = q && q.hasOwnProperty('show') ? parseInt(q.show, 10) : 0,\n\t\t\t\tdevId = q && q.hasOwnProperty('id') ? q.id : null,\n\t\t\t\tnow = Math.floor(Date.now() / 1000),\n\t\t\t\tbody = {\n\t\t\t\t\tupdateTime: now\n\t\t\t\t};\n\t\t\tvar sec = 0;\n\t\t\tvar entries = [];\n\t\t\tvar averageEntries = [];\n\n\t\t\tif (devId && self.history[devId]) {\n\t\t\t\tvar hist = self.history[devId].get();\n\n\t\t\t\t// create output with n (= show) values - 1440, 288, 96, 48, 24, 12, 6\n\t\t\t\tif (items > 0 && items <= 1440) {\n\t\t\t\t\tsec = 86400 / items; // calculate seconds of range\n\n\t\t\t\t\t// calculate averaged value of all meta values between 'sec' range\n\t\t\t\t\tfor (var i = 0; i < items; i++) {\n\t\t\t\t\t\tvar from = Math.floor(now - sec * (items - i));\n\t\t\t\t\t\tvar to = Math.floor(now - sec * (items - (i + 1)));\n\n\t\t\t\t\t\t// filter values between from and to\n\t\t\t\t\t\tvar range = hist.filter(function (metric) {\n\t\t\t\t\t\t\treturn metric.id >= from && metric.id <= to;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tvar l = null;\n\t\t\t\t\t\t// calculate level\n\t\t\t\t\t\tif (range.length > 0) {\n\t\t\t\t\t\t\tl = range.reduce(function (acc, cur) {\n\t\t\t\t\t\t\t\treturn +cur.l + acc;\n\t\t\t\t\t\t\t}, 0) / range.length;\n\t\t\t\t\t\t\tif (l === +l && l !== (l | 0)) { // round to one position after '.'\n\t\t\t\t\t\t\t\tl = +l.toPrecision(3);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// push new averaged entry to\n\n\t\t\t\t\t\taverageEntries.push({\n\t\t\t\t\t\t\tid: to,\n\t\t\t\t\t\t\tl: l\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tentries = averageEntries;\n\t\t\t\t} else {\n\t\t\t\t\tentries = hist;\n\t\t\t\t}\n\n\t\t\t\t// filter meta entries by since\n\t\t\t\tbody.history = since > 0 ? entries.filter(function (metric) {\n\t\t\t\t\treturn metric.id >= since;\n\t\t\t\t}) : entries;\n\t\t\t\tbody.code = 200;\n\t\t\t} else if (devId && !self.history[devId]) {\n\t\t\t\tbody.code = 404;\n\t\t\t\tbody.message = 'Not Found.';\n\n\t\t\t} else {\n\t\t\t\tbody.histories = {};\n\t\t\t\tbody.code = 200;\n\t\t\t\tself.config.allRegisteredDevices.forEach(function (vDevId) {\n\t\t\t\t\tbody.histories[vDevId] = _.filter(self.history[vDevId].get(), function (entry) {\n\t\t\t\t\t\treturn entry.id >= since;\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn self.prepareHTTPResponse(body);\n\t\t};\n\n\t\tthis.HistoryAPI.Delete = function(url, request) {\n\t\t\tvar q = request.query || null,\n\t\t\t\tvDevId = q && q.hasOwnProperty('id')? q.id : null,\n\t\t\t\tbody = {\n\t\t\t\t\tupdateTime: Math.floor(Date.now() / 1000)\n\t\t\t\t};\n\n\t\t\tif (vDevId && self.history[vDevId]) {\n\t\t\t\tself.history[vDevId].set([]);\n\n\t\t\t\tvar vdev = self.controller.devices.get(vDevId);\n\n\t\t\t\tself.addNotification('info', self.langFile.info_clear_id_history + vdev? vdev.get('metrics:title') : vDevId, 'module');\n\n\t\t\t\tbody.code = 201;\n\n\t\t\t} else if (vDevId && !self.history[vDevId]) {\n\t\t\t\tbody.code = 404;\n\t\t\t\tbody.message = 'Not Found.';\n\n\t\t\t} else {\n\n\t\t\t\tself.addNotification('info', self.langFile.info_clear_all_histories, 'module');\n\n\t\t\t\tself.config.allRegisteredDevices.forEach(function(devId){\n\t\t\t\t\tif(self.history[devId]) {\n\t\t\t\t\t\tself.history[devId].set([]);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tbody.code = 201;\n\t\t\t}\n\n\t\t\treturn self.prepareHTTPResponse(body);\n\t\t};\n\t}\n});\n"
  },
  {
    "path": "modules/DeviceHistory/lang/de.json",
    "content": "{\n\t\"m_title\":\"24 Stunden Gerätehistorie\",\n\t\"m_descr\":\"Diese App fügt jedem Sensor und Aktor ein kleines Icon bei. Klickt man auf dieses Icon, öffnet sich ein Splash-Fenster mit einer Graphik, die den Status der vergangenen 24 Stunden aufzeigt. Bitte beachten Sie, dass diese Anzeige nur der Schnellinformation dient. Es werden lediglich Durchschnittswerte angezeigt. Ein kurzes Einschalten des Lichtes könnte möglicherweise in dieser Chronik nicht wider gespiegelt werden. Trotz alledem bietet es eine schöne und schnelle Möglichkeit, sich über den Sensorstatus der letzten 24 Stunden zu informieren. Wenn Sie sich die Daten Ihres Smart Home präzisier aufzeigen lassen wollen, sollten Sie die App „Sensor logging“ zusammen mit einem Service oder einer Software durch dritte Dienstleister anwenden.<br><br>Einstellungen: Sie können eine Geräteliste bestimmen, die nicht erfasst ist. Bitte beachten Sie, dass ein Gerät, welches bereits vom Sendeabruf der Sensor Polling App ausgeschlossen ist, ohnehin nicht aufgezeichnet werden kann.\",\n\t\"l_devices\":\"Speichere keine History für folgende Geräte:\",\n\t\"h_devices\":\"Bei gleichzeitiger Verwendung der App 'Periodische Sensorabfrage' ist folgendes zu beachten: Ein dort von der Abfrage ausgeschlossenes Gerät kann keine Historie erzeugen.\",\n\t\"err_store_history\":\"Fehler beim Speichern der Historie von Gerät: \",\n\t\"info_add_history\":\"Historie zum Gerät hinzugefügt: \",\n\t\"info_remove_history\":\"Historie vom Gerät entfernt: \",\n\t\"info_clear_id_history\":\"Historieneinträge vom Gerät gelöscht: \",\n\t\"info_clear_all_histories\":\"Historieneinträge aller Geräte gelöscht.\",\n\t\"info_transformation\":\" keine Historie gefunden. Historie wird gelöscht ...\"\n}"
  },
  {
    "path": "modules/DeviceHistory/lang/en.json",
    "content": "{\n\t\"m_title\":\"24 Hours Device History\",\n\t\"m_descr\":\"This app adds a little icon to every sensor and actor. Clicking on this icon opens a splash window with a graph showing the status of the last 24 hours. Please note that this is display is for quick information only. Only average values are shown so that a short turning on of a light may not even reflected in this history. Nevertheless it’s a nice and quick way to get an idea about the status of a sensor for the last 24 hours. If you like to record data about your smart home more precisely you should use the App “Sensor logging” together with some third party service or software.<br><br>Settings: You can define a list of devices that are not recorded. Please note that a device already excluded from polling in the Sensor Polling App can not be recorded anyway.\",\n\t\"l_devices\":\"Do not track devices marked below:\",\n\t\"h_devices\":\"With simultaneous use of the app 'Periodical Sensor Polling', note the following: One there from the polling excluded device cannot create a history.\",\n\t\"err_store_history\":\"Cannot store history of device: \",\n\t\"info_add_history\":\"History added to device: \",\n\t\"info_remove_history\":\"History removed for device: \",\n\t\"info_clear_id_history\":\"History entries cleared of device: \",\n\t\"info_clear_all_histories\":\"History entries of all devices cleared.\",\n\t\"info_transformation\":\" not assigned to history. History will be removed ...\"\n}"
  },
  {
    "path": "modules/DeviceHistory/module.json",
    "content": "{\n\t\"singleton\" : true,\n\t\"dependencies\": [\"Cron\"],\n\t\"category\" : \"device_enhancements\",\n\t\"author\" : \"Z-Wave.Me\",\n\t\"homepage\" : \"http://razberry.z-wave.me\",\n\t\"icon\" : \"icon.png\",\n\t\"moduleName\":\"DeviceHistory\",\n\t\"version\" : \"2.0.0\",\n\t\"maturity\" : \"stable\",\n\t\"repository\" : {\n\t\t\"type\" : \"git\",\n\t\t\"source\" : \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\" : {\n\t\t\"title\" : \"__m_title__\",\n\t\t\"description\" : \"__m_descr__\",\n\t\t\"devices\": [],\n\t\t\"allRegisteredDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"properties\": {\n\t\t\t\"devices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\":\"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"devices\": {\n\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"helper\": \"__h_devices__\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/DeviceHistory/patchnotes.txt",
    "content": "v1.3.0\n- remove support of virtual devices with binary states, because SHUI view has changed and makes it unecessary\n- minor refactoring\n\nv1.2.1\n- type switchControl added\n- bugfix: preselecting virtual devices to add history\n- minor refactoring\n\nv1.2.0\n- special handling of type toggleButton added - is 0 by default and 1 if triggerd - so if toggle was triggered during history interval it wil set a point on 0.5\n- refactoring\n- hash entries removed\n- language keys added\n- set maturity to stable\n"
  },
  {
    "path": "modules/DummyDevice/index.js",
    "content": "/*** DummyDevice Z-Way HA module *******************************************\n\nVersion: 1.2.0\n(c) Z-Wave.Me, 2022\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Ray Glendenning <ray.glendenning@gmail.com>\nDescription:\n\tCreates a Dummy device\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction DummyDevice (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tDummyDevice.super_.call(this, id, controller);\n}\n\ninherits(DummyDevice, AutomationModule);\n\n_module = DummyDevice;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nDummyDevice.prototype.init = function (config) {\n\tDummyDevice.super_.prototype.init.call(this, config);\n\n\tvar lastLevel = loadObject(\"DummyDevice_\" + this.id + \"_level\");\n\n\tvar self = this,\n\t\tdeviceType,\n\t\tprobeType,\n\t\ticon,\n\t\tlevel,\n\t\tconfigType = this.config.deviceType;\n\t\t\n\tswitch(configType) {\n\t\tcase \"switchBinary\":\n\t\t\tdeviceType = \"switchBinary\";\n\t\t\tprobeType = \"switch\";\n\t\t\ticon = \"switch\";\n\t\t\tlevel = lastLevel || \"off\";\n\t\t\tbreak;\n\t\tcase \"switchBinarySiren\":\n\t\t\tdeviceType = \"switchBinary\";\n\t\t\tprobeType = \"siren\"\n\t\t\ticon = \"siren\";\n\t\t\tlevel = lastLevel || \"off\";\n\t\t\tbreak;\n\t\tcase \"switchBinaryValve\":\n\t\t\tdeviceType = \"switchBinary\";\n\t\t\tprobeType = \"valve\"\n\t\t\ticon = \"valve\";\n\t\t\tlevel = lastLevel || \"off\";\n\t\t\tbreak;\n\t\tcase \"doorlock\":\n\t\t\tdeviceType = \"doorlock\";\n\t\t\tprobeType = \"\";\n\t\t\ticon = \"door\";\n\t\t\tlevel = lastLevel || \"close\";\n\t\t\tbreak;\n\t\tcase \"switchMultilevel\":\n\t\t\tdeviceType = \"switchMultilevel\";\n\t\t\tprobeType = \"\";\n\t\t\ticon = \"multilevel\";\n\t\t\tlevel = lastLevel || 0;\n\t\t\tbreak;\n\t\tcase \"switchMultilevelMotor\":\n\t\t\tdeviceType = \"switchMultilevel\"\n\t\t\tprobeType = \"motor\"\n\t\t\ticon = \"blinds\";\n\t\t\tlevel = lastLevel || 0;\n\t\t\tbreak;\n\t}\n\t\n\tvar defaults = {\n\t\tmetrics: {\n\t\t\ttitle: self.getInstanceTitle(),\n\t\t\ticon: icon, // here to allow changing icon to custom one\n\t\t\tlevel: level // here to restore last value\n\t\t}\n\t};\n \n\tvar overlay = {\n\t\t\tdeviceType: deviceType, // here to allow changing type\n\t\t\tprobeType: probeType\n\t};\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: this.getName() + \"_\" + this.id,\n\t\tdefaults: defaults,\n\t\toverlay: overlay,\n\t\thandler: function(command, args) {\n\t\t\t\n\t\t\tif (command != 'update') {\n\t\t\t\tvar level = command;\n\t\t\t\t\n\t\t\t\tif (this.get('deviceType') === \"switchMultilevel\") {\n\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\tlevel = 99;\n\t\t\t\t\t} else if (command === \"off\") {\n\t\t\t\t\t\tlevel = 0;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlevel = parseInt(args.level, 10);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.set(\"metrics:level\", level);\n\t\t\t\tsaveObject(this.id + \"_level\" , level); // not critical, allow lazy save\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n};\n\nDummyDevice.prototype.stop = function () {\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tDummyDevice.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/DummyDevice/lang/de.json",
    "content": "{\n\t\"m_title\":\"Gerätattrappe\",\n\t\"m_descr\":\"Wie der Name verrät, erstellt diese App ein virtuelles Gerät, welches nur auf der UI existiert, jedoch mit keiner physischen Hardware verknüpft ist. Das kann zur Einstellung bestimmter Szenen oder zum Austesten mancher Situationen sinnvoll sein.<br><br>Einstellungen:<br><ul><li> Sie können bestimmen, ob Ihr Dummy Gerät als Binärschaltung oder als Multilevel-Schaltung auftreten soll (Dimmer, Motorsteuerung).</li></ul>\",\n\t\"l_options\":\"Wählen Sie einen Gerätetyp:\"\n}"
  },
  {
    "path": "modules/DummyDevice/lang/en.json",
    "content": "{\n\t\"m_title\":\"Dummy Device\",\n\t\"m_descr\":\"As the name suggests this app creates a virtual device that just exists on the UI but does not link to any physical hardware. This may be useful for setting up certain scenes or to debug certain situations.<br><brSettings:<br><ul><li> You can define if your dummy device shall appear as binary switch or as multilevel l switch (dimmer, motor control).</li></ul>\",\n\t\"l_options\":\"Select device type\"\n}"
  },
  {
    "path": "modules/DummyDevice/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Устройство пустышка\",\n\t\"m_descr\":\"Устройство пустышку можно использовать например, как флаг, обозначающий режимы: 'На охране' и 'Снят с охраны'.\",\n\t\"l_options\":\"Выберите тип устройства\"\n}"
  },
  {
    "path": "modules/DummyDevice/module.json",
    "content": "{\n\t\"singleton\" : false,\n\t\"dependencies\": [],\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"DummyDevice\",\n\t\"version\": \"1.2.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\" : {\n\t\t\"title\" : \"__m_title__\",\n\t\t\"description\" : \"__m_descr__\",\n\t\t\"deviceType\" : \"switchBinary\"\n\t},\n\t\"schema\" : {\n\t\t\"type\" : \"object\",\n\t\t\"properties\" : {\n\t\t\t\"deviceType\" : {\n\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\"enum\" : [\"switchBinary\", \"switchMultilevel\", \"doorlock\", \"switchMultilevelMotor\", \"switchBinarySiren\", \"switchBinaryValve\"],\n\t\t\t\t\"default\" : \"switchBinary\",\n\t\t\t\t\"required\" : true\n\t\t\t}\n\t\t}\n\t},\n\t\"options\" : {\n\t\t\"fields\" : {\n\t\t\t\"deviceType\" : {\n\t\t\t\t\"label\" : \"__l_options__\",\n\t\t\t\t\"type\" : \"select\",\n\t\t\t\t\"optionLabels\" : [\"Binary switch\", \"Multilevel switch\", \"Door lock\", \"Blinds\", \"Siren\", \"Water valve\"]\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/EasyScripting/htdocs/js/compile.sh",
    "content": "#!/bin/bash\n\ncompileJS() {\n\tlocal IFILE=$1\n\tlocal OFILE=$2\n\tlocal OPT_LEVEL=$3\n\tURL=$(wget -q https://closure-compiler.appspot.com/compile --post-data 'output_format=json&output_info=compiled_code&output_info=warnings&output_info=errors&output_info=statistics&compilation_level='${OPT_LEVEL}'&warning_level=verbose&output_file_name='${OFILE}'.js&js_code='$(hexdump -v -e '/1 \"%02x\"' ${IFILE}.js | sed 's/\\(..\\)/%\\1/g') -O - | python -c \"import sys, json; print json.load(sys.stdin)['outputFilePath']\")\n\twget -q https://closure-compiler.appspot.com/${URL} -O ${OFILE}.js\n}\n\ncompileJS postRender-with-comments postRender SIMPLE_OPTIMIZATIONS\n"
  },
  {
    "path": "modules/EasyScripting/htdocs/js/postRender-with-comments.js",
    "content": "function modulePostRender(control) {\n\t// advanced code editor is available only on Chome\n\tif (!window.chrome) {\n\t\t$(\".alpaca-field.alpaca-field-textarea textarea\").parent().prepend($('<div></div>').text('__h_unsupported__'));\n\t\treturn;\n\t}\n\n\t// detect cursor position on screen\n\t// https://openbase.io/js/textarea-caret\n\tfunction getCaretCoordinates(element, position, options) {\n\t\t// We'll copy the properties below into the mirror div.\n\t\t// Note that some browsers, such as Firefox, do not concatenate properties\n\t\t// into their shorthand (e.g. padding-top, padding-bottom etc. -> padding),\n\t\t// so we have to list every single property explicitly.\n\t\tvar properties = [\n\t\t\t'direction',  // RTL support\n\t\t\t'boxSizing',\n\t\t\t'width',  // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does\n\t\t\t'height',\n\t\t\t'overflowX',\n\t\t\t'overflowY',  // copy the scrollbar for IE\n\n\t\t\t'borderTopWidth',\n\t\t\t'borderRightWidth',\n\t\t\t'borderBottomWidth',\n\t\t\t'borderLeftWidth',\n\t\t\t'borderStyle',\n\n\t\t\t'paddingTop',\n\t\t\t'paddingRight',\n\t\t\t'paddingBottom',\n\t\t\t'paddingLeft',\n\n\t\t\t// https://developer.mozilla.org/en-US/docs/Web/CSS/font\n\t\t\t'fontStyle',\n\t\t\t'fontVariant',\n\t\t\t'fontWeight',\n\t\t\t'fontStretch',\n\t\t\t'fontSize',\n\t\t\t'fontSizeAdjust',\n\t\t\t'lineHeight',\n\t\t\t'fontFamily',\n\n\t\t\t'textAlign',\n\t\t\t'textTransform',\n\t\t\t'textIndent',\n\t\t\t'textDecoration',  // might not make a difference, but better be safe\n\n\t\t\t'letterSpacing',\n\t\t\t'wordSpacing',\n\n\t\t\t'tabSize',\n\t\t\t'MozTabSize'\n\t\t];\n\n\t\tvar isFirefox = window.mozInnerScreenX != null;\n\n\t\t// The mirror div will replicate the textarea's style\n\t\tvar div = document.createElement('div');\n\t\tdiv.id = 'input-textarea-caret-position-mirror-div';\n\t\tdocument.body.appendChild(div);\n\n\t\tvar style = div.style;\n\t\tvar computed = window.getComputedStyle ? window.getComputedStyle(element) : element.currentStyle;  // currentStyle for IE < 9\n\n\t\t// Default textarea styles\n\t\tstyle.whiteSpace = 'pre-wrap';\n\t\tstyle.wordWrap = 'break-word';  // only for textarea-s\n\n\t\t// Position off-screen\n\t\tstyle.position = 'absolute';  // required to return coordinates properly\n\t\tstyle.visibility = 'hidden';  // not 'display: none' because we want rendering\n\n\t\t// Transfer the element's properties to the div\n\t\tproperties.forEach(function (prop) {\n\t\t\tstyle[prop] = computed[prop];\n\t\t});\n\n\t\tif (isFirefox) {\n\t\t// Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275\n\t\tif (element.scrollHeight > parseInt(computed.height))\n\t\t\tstyle.overflowY = 'scroll';\n\t\t} else {\n\t\t\tstyle.overflow = 'hidden';  // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll'\n\t\t}\n\n\t\tdiv.textContent = element.value.substring(0, position);\n\t\t// The second special handling for input type=\"text\" vs textarea:\n\t\t// spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037\n\n\n\t\tvar span = document.createElement('span');\n\t\t// Wrapping must be replicated *exactly*, including when a long word gets\n\t\t// onto the next line, with whitespace at the end of the line before (#7).\n\t\t// The *only* reliable way to do that is to copy the *entire* rest of the\n\t\t// textarea's content into the <span> created at the caret position.\n\t\t// For inputs, just '.' would be enough, but no need to bother.\n\t\tspan.textContent = element.value.substring(position) || '.';  // || because a completely empty faux span doesn't render at all\n\t\tdiv.appendChild(span);\n\n\t\tvar coordinates = {\n\t\t\ttop: span.offsetTop + parseInt(computed['borderTopWidth']),\n\t\t\tleft: span.offsetLeft + parseInt(computed['borderLeftWidth']),\n\t\t\theight: parseInt(computed['lineHeight'])\n\t\t};\n\n\t\tdocument.body.removeChild(div);\n\n\t\treturn coordinates;\n\t}\n\n\t// syntax highlight\n\t$(\".alpaca-field.alpaca-field-textarea textarea\").addClass('editor allow-tabs').wrap(\n\t\t$('<div></div>').addClass('scroller')\n\t).parent().append(\n\t\t$('<pre></pre>').append(\n\t\t\t$('<code></code>').addClass('syntax-highight javascript')\n\t\t)\n\t).wrap(\n\t\t$('<div></div>').addClass('highlight-editor-holder')\n\t).parent().prepend(\n\t\t$('<ul></ul>').addClass('toolbar')\n\t);\n\n\t// menu handling\n\tfunction modalBackground(id) {\n\t\tvar suffix = '-modal';\n\t\t$('#' + id + suffix).remove();\n\t\treturn $('<div></div>')\n\t\t\t.attr('id', id + suffix)\n\t\t\t.attr('role', 'menu-modal')\n\t\t\t.addClass('dropdown-menu-modal')\n\t\t\t.click(function(event) {\n\t\t\t\t$(this).css({\n\t\t\t\t\t'display': 'none'\n\t\t\t\t});\n\t\t\t\tvar id = $(this).attr('id');\n\t\t\t\tid = id.substr(0, id.length - suffix.length);\n\t\t\t\t$('#' + id).css({\n\t\t\t\t\t'display': 'none'\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tfunction modalMenu(id) {\n\t\t$('#' + id).remove();\n\t\treturn $('<ul></ul>')\n\t\t\t.attr('id', id)\n\t\t\t.attr('role', 'menu')\n\t\t\t.addClass('dropdown-menu');\n\t}\n\n\tfunction menu(id) {\n\t\t\t$('body')\n\t\t\t.append(modalBackground(id + '-menu'))\n\t\t\t.append(modalMenu(id + '-menu'));\n\t}\n\n\tfunction menuOpen(menu_id, pos) {\n\t\t$('#' + menu_id + '-menu').css({\n\t\t\tposition: \"fixed\",\n\t\t\tdisplay: \"block\",\n\t\t\tleft: pos.left + 'px',\n\t\t\ttop: pos.top + 'px'\n\t\t});\n\t\t$('#' + menu_id + '-menu-modal').css({\n\t\t\t'display': 'block'\n\t\t});\n\t}\n\n\tfunction menuAttach(el, menu_id, openon) {\n\t\treturn el\n\t\t\t.attr('id', menu_id)\n\t\t\t.attr('context', menu_id + '-menu')\n\t\t\t.attr('openon', openon)\n\t\t\t.bind(openon, function(event) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tvar pos = this.getBoundingClientRect();\n\t\t\t\tmenuOpen(menu_id, {\n\t\t\t\t\tleft: openon === 'mouseover' ? pos.right : event.clientX,\n\t\t\t\t\ttop: openon === 'mouseover' ? pos.top : event.clientY\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tfunction menuItemAdd(menu_id, item_id, text, action) {\n\t\t\t$('#' + menu_id + '-menu').append(\n\t\t\t\t$('<li></li>')\n\t\t\t\t\t.append(\n\t\t\t\t\t\t$('<a></a>')\n\t\t\t\t\t\t\t.text(text)\n\t\t\t\t\t\t\t.click(function() {\n\t\t\t\t\t\t\t\tmenuClose(this);\n\t\t\t\t\t\t\t\taction(this);\n\t\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\t.attr('id', menu_id + '-menu-item-' + item_id)\n\t\t\t);\n\t}\n\n\tfunction menuClose(item) {\n\t\tvar menuName = item + '-menu';\n\t\tif (typeof item !== \"string\") {\n\t\t\tmenuName = $(item).closest('[role=\"menu\"]').attr('id');\n\t\t}\n\n\t\t$('#' + menuName).css({\n\t\t\t'display': 'none'\n\t\t});\n\t\t$('#' + menuName + '-modal').css({\n\t\t\t'display': 'none'\n\t\t});\n\t}\n\n\tfunction menuItemAddText(menu_id, text, data, textarea) {\n\t\t$('#' + menu_id + '-menu').append(\n\t\t\t$('<li></li>')\n\t\t\t\t.append(\n\t\t\t\t\t$('<a></a>')\n\t\t\t\t\t\t.text(text)\n\t\t\t\t\t\t.click(function() {\n\t\t\t\t\t\t\t\tmenuClose(this);\n\t\t\t\t\t\t\t\ttextareaTextAt(data, textarea);\n\t\t\t\t\t\t})\n\t\t\t\t)\n\t\t);\n\t}\n\n\tfunction menuItemAddDelimiter(menu_id) {\n\t\t$('#' + menu_id + '-menu').append($('<li></li>').addClass('divider'));\n\t}\n\n\tfunction toolbarMenuAdd(menu_id, icon, name) {\n\t\t$('.highlight-editor-holder .toolbar').append(\n\t\t\t\tmenuAttach(\n\t\t\t\t\t$('<li></li>')\n\t\t\t\t\t\t.append(\n\t\t\t\t\t\t\t$('<a></a>').append(\n\t\t\t\t\t\t\t\t$('<i> ' + name +'</i>').addClass('fas ' + icon)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t),\n\t\t\t\t\tmenu_id,\n\t\t\t\t\t'click'\n\t\t\t\t)\n\t\t);\n\t\tmenu(menu_id);\n\t}\n\n\t// fill toolbar with menus\n\n\ttoolbarMenuAdd('easy-scripting-devices-events', 'fa-play', '__m_events__');\n\ttoolbarMenuAdd('easy-scripting-devices-objects', 'fa-lightbulb', '__m_devices__');\n\ttoolbarMenuAdd('easy-scripting-syntax', 'fa-code', '__m_expressions__');\n\n\t// fill menu with devices\n\t$.ajax('/ZAutomation/api/v1/devices')\n\t\t.done(function (response) {\n\t\t\tresponse.data.devices.sort(function(a, b) {\n\t\t\t\tif (a.metrics.title === b.metrics.title) return (a.id < b.id) ? -1 : 1;\n\t\t\t\treturn (a.metrics.title < b.metrics.title) ? -1 : 1;\n\n\t\t\t}).forEach(function(dev) {\n\t\t\t\t// events\n\t\t\t\tmenuItemAdd(\"easy-scripting-devices-events\", dev.id, dev.metrics.title + ' (' + dev.id + ')', function() {\n\t\t\t\t\ttextareaTextAtTop('### ' + dev.id + ' // ' + dev.metrics.title + '\\n');\n\t\t\t\t});\n\t\t\t\tmenuItemAdd(\"easy-scripting-devices-objects\", dev.id, dev.metrics.title + ' (' + dev.id + ')', function() {\n\t\t\t\t\ttextareaTextAt('vdev(\"' + dev.id + '\")');\n\t\t\t\t});\n\t\t\t});\n\t\t})\n\t\t.fail(function () {\n\t\t\talert('no devices');\n\t\t});\n\n\t// special characters\n\tvar exprBool = '\\u229c',\n\t    exprVal = '\\u2299',\n\t    expression = '\\u2026',\n\t    placeHolders = [exprBool, exprVal, expression];\n\n\tvar textArea = $(\".alpaca-field.alpaca-field-textarea textarea\");\n\n\tmenu('easy-scripting-syntax');\n\tmenuItemAddText('easy-scripting-syntax', '__m_if__', 'if (' + exprBool + ') {\\n  ' + expression + '\\n}');\n\tmenuItemAddText('easy-scripting-syntax', '__m_for_loop__', 'for (var i = 0; i < ' + exprVal + '; i++) {\\n  ' + expression + '\\n}');\n\tmenuItemAddText('easy-scripting-syntax', '__m_while_loop__', 'while (' + exprBool + ') {\\n  ' + expression + '\\n}');\n\tmenuItemAddDelimiter('easy-scripting-syntax');\n\tmenuItemAddText('easy-scripting-syntax', '__m_or__', '' + exprBool + ' || ' + exprBool + '');\n\tmenuItemAddText('easy-scripting-syntax', '__m_and__', '' + exprBool + ' && ' + exprBool + '');\n\tmenuItemAddDelimiter('easy-scripting-syntax');\n\tmenuItemAddText('easy-scripting-syntax', '__m_http_request__', 'http.request({method: \"GET\", async: true, url: ' + exprVal + '});');\n\tmenuItemAddText('easy-scripting-syntax', '__m_set_timeout__', 'setTimer(\"' + expression + '\", function() {\\n  ' + expression + '\\n}, ' + exprVal + ')');\n\tmenuItemAddText('easy-scripting-syntax', '__m_remove_timeout__', 'stopTimer(\"' + expression + '\")');\n\n\tmenu('easy-scripting-device-methods');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_turn_on__', 'on()');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_turn_off__', 'off()');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_turn_set__', 'set(' + exprVal + ')');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_update__', 'update()');\n\tmenuItemAddDelimiter('easy-scripting-device-methods');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_is_on__', 'value() === \"on\"');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_is_off__', 'value() === \"off\"');\n\tmenuItemAddText('easy-scripting-device-methods', '__m_equals__', 'value() === ' + exprVal);\n\tmenuItemAddText('easy-scripting-device-methods', '__m_ne__', 'value() !== ' + exprVal);\n\tmenuItemAddText('easy-scripting-device-methods', '__m_gt__', 'value() > ' + exprVal);\n\tmenuItemAddText('easy-scripting-device-methods', '__m_ge__', 'value() >= ' + exprVal);\n\tmenuItemAddText('easy-scripting-device-methods', '__m_lt__', 'value() < ' + exprVal);\n\tmenuItemAddText('easy-scripting-device-methods', '__m_le__', 'value() <= ' + exprVal);\n\tmenuItemAddText('easy-scripting-device-methods', '__m_value__', 'value()');\n\n\t// TextArea functions\n\n\t// find current ident\n\tfunction getSpaces() {\n\t\tvar textAreaDOM = textArea.get(0),\n\t\t    start = textAreaDOM.selectionStart;\n\n\t\tvar textToPosition = textArea.val().substr(0, start),\n\t\t    ident = '',\n\t\t    ch,\n\t\t    i = 1;\n\n\t\twhile ((ch = textToPosition.substr(-i, 1)) === ' ' || ch === '\\t') {\n\t\t\ti++;\n\t\t\tident = ch + ident;\n\t\t}\n\n\t\treturn ident;\n\t}\n\n\tfunction getIdent() {\n\t\tvar textAreaDOM = textArea.get(0),\n\t\t    start = textAreaDOM.selectionStart;\n\n\t\tvar lastNL = textAreaDOM.value.substr(0, start).lastIndexOf('\\n') + 1;\n\t\t// works with -1 as well\n\n\t\tvar line = textAreaDOM.value.substr(lastNL, start - lastNL),\n\t\t    ident = '',\n\t\t    i = 0;\n\n\t\twhile ((ch = line.substr(i, 1)) === ' ' || ch === '\\t') {\n\t\t\ti++;\n\t\t\tident += ch;\n\t\t}\n\n\t\tif (line.substr(line.length - 1, 1) === '{') {\n\t\t\tident += '  ';\n\t\t}\n\n\t\treturn ident;\n\t}\n\n\t// add text in textarea to cursor position or intead of selection\n\tfunction textareaTextAt(data) {\n\t\tvar textAreaDOM = textArea.get(0),\n\t\t\tstart = textAreaDOM.selectionStart;\n\n\t\t// add ident to the string\n\t\tdata = data.split('\\n').map(function(line, j) { return (j === 0 ? '' : getSpaces()) + line; }).join('\\n');\n\n\t\t// add at position\n\t\tif (textArea.setRangeText) {\n\t\t\t// if setRangeText function is supported by current browser\n\t\t\ttextArea.setRangeText(data);\n\t\t} else {\n\t\t\ttextArea.focus();\n\t\t\tdocument.execCommand('insertText', false, data);\n\t\t}\n\n\t\tfunction indexOfPlaceholder(string) {\n\t\t\tfor (var i = 0; i < placeHolders.length; i++) {\n\t\t\t\tvar j = string.indexOf(placeHolders[i]);\n\t\t\t\tif (j !== -1) return j;\n\t\t\t}\n\t\t\treturn -1;\n\t\t}\n\n\t\t// select first placeholder to fill if placeholder was in data\n\t\tvar ii = indexOfPlaceholder(data);\n\t\tif (ii !== -1) {\n\t\t\ttextAreaDOM.selectionStart = ii + start;\n\t\t\ttextAreaDOM.selectionEnd = textAreaDOM.selectionStart + 1;\n\t\t}\n\n\t\t// trigger event for code highlighter\n\t\ttextArea.blur();\n\t\ttextArea.focus();\n\t}\n\n\t// add text in textarea to cursor position or intead of selection\n\tfunction textareaTextAtTop(data) {\n\t\t// trimEnd and addind \\n is to trigger event for code highlighter\n\t\ttextArea.val(data + textArea.val().trimEnd());\n\t\ttextareaTextAt('\\n');\n\t}\n\n\t$(textArea).click(function() {\n\t\tif (this.selectionStart === this.selectionEnd && placeHolders.indexOf(this.value.substr(this.selectionStart, 1)) !== -1) {\n\t\t\tthis.selectionEnd = this.selectionStart + 1;\n\t\t} else if (this.selectionStart === this.selectionEnd && placeHolders.indexOf(this.value.substr(this.selectionStart - 1, 1)) !== -1) {\n\t\t\tthis.selectionEnd = this.selectionStart;\n\t\t\tthis.selectionStart--;\n\t\t}\n\t});\n\n\t$(textArea).keypress(function(e) {\n\t\tif (e.key === '.') {\n\t\t\t// check that before is vdev(\"...\")\n\t\t\tif (this.value.substr(0, this.selectionStart).match(/.*vdev\\(\"[\\w-]+\"\\)$/)) {\n\t\t\t\t// get cursor position\n\t\t\t\tvar pos = getCaretCoordinates(this, this.selectionEnd),\n\t\t\t\t    thisPos = this.getBoundingClientRect();\n\t\t\t\tpos.top += thisPos.top + 10; // add small shift\n\t\t\t\tpos.left += thisPos.left + 10;\n\t\t\t\tmenuOpen('easy-scripting-device-methods', pos);\n\t\t\t}\n\t\t} else if (e.key === 'Enter') {\n\t\t\tvar ident = getIdent();\n\t\t\tsetTimeout(function() {\n\t\t\t\t\ttextareaTextAt(ident);\n\t\t\t}, 0);\n\t\t} else {\n\t\t\tmenuClose('easy-scripting-device-methods');\n\t\t}\n\t});\n\n\t// highlight description\n\n\tdocument.querySelectorAll('pre code').forEach(function(block) {\n\t\thljs.highlightElement(block);\n\t});\n\n\t// trigger highlight\n\n\ttextareaTextAtTop('');\n}\n"
  },
  {
    "path": "modules/EasyScripting/htdocs/js/postRender.js",
    "content": "function modulePostRender(C){function y(a,b,c){var e=null!=window.mozInnerScreenX;c=document.createElement(\"div\");c.id=\"input-textarea-caret-position-mirror-div\";document.body.appendChild(c);var f=c.style,g=window.getComputedStyle?window.getComputedStyle(a):a.currentStyle;f.whiteSpace=\"pre-wrap\";f.wordWrap=\"break-word\";f.position=\"absolute\";f.visibility=\"hidden\";\"direction boxSizing width height overflowX overflowY borderTopWidth borderRightWidth borderBottomWidth borderLeftWidth borderStyle paddingTop paddingRight paddingBottom paddingLeft fontStyle fontVariant fontWeight fontStretch fontSize fontSizeAdjust lineHeight fontFamily textAlign textTransform textIndent textDecoration letterSpacing wordSpacing tabSize MozTabSize\".split(\" \").forEach(function(k){f[k]=\ng[k]});e?a.scrollHeight>parseInt(g.height)&&(f.overflowY=\"scroll\"):f.overflow=\"hidden\";c.textContent=a.value.substring(0,b);e=document.createElement(\"span\");e.textContent=a.value.substring(b)||\".\";c.appendChild(e);a={top:e.offsetTop+parseInt(g.borderTopWidth),left:e.offsetLeft+parseInt(g.borderLeftWidth),height:parseInt(g.lineHeight)};document.body.removeChild(c);return a}function z(a){$(\"#\"+a+\"-modal\").remove();return $(\"<div></div>\").attr(\"id\",a+\"-modal\").attr(\"role\",\"menu-modal\").addClass(\"dropdown-menu-modal\").click(function(b){$(this).css({display:\"none\"});\nb=$(this).attr(\"id\");b=b.substr(0,b.length-6);$(\"#\"+b).css({display:\"none\"})})}function n(a){var b=$(\"body\").append(z(a+\"-menu\")),c=b.append;a+=\"-menu\";$(\"#\"+a).remove();a=$(\"<ul></ul>\").attr(\"id\",a).attr(\"role\",\"menu\").addClass(\"dropdown-menu\");c.call(b,a)}function u(a,b){$(\"#\"+a+\"-menu\").css({position:\"fixed\",display:\"block\",left:b.left+\"px\",top:b.top+\"px\"});$(\"#\"+a+\"-menu-modal\").css({display:\"block\"})}function A(a,b,c){return a.attr(\"id\",b).attr(\"context\",b+\"-menu\").attr(\"openon\",c).bind(c,function(e){e.preventDefault();\nvar f=this.getBoundingClientRect();u(b,{left:\"mouseover\"===c?f.right:e.clientX,top:\"mouseover\"===c?f.top:e.clientY})})}function v(a,b,c,e){$(\"#\"+a+\"-menu\").append($(\"<li></li>\").append($(\"<a></a>\").text(c).click(function(){p(this);e(this)})).attr(\"id\",a+\"-menu-item-\"+b))}function p(a){var b=a+\"-menu\";\"string\"!==typeof a&&(b=$(a).closest('[role=\"menu\"]').attr(\"id\"));$(\"#\"+b).css({display:\"none\"});$(\"#\"+b+\"-modal\").css({display:\"none\"})}function d(a,b,c,e){$(\"#\"+a+\"-menu\").append($(\"<li></li>\").append($(\"<a></a>\").text(b).click(function(){p(this);\nl(c,e)})))}function q(a){$(\"#\"+a+\"-menu\").append($(\"<li></li>\").addClass(\"divider\"))}function r(a,b,c){$(\".highlight-editor-holder .toolbar\").append(A($(\"<li></li>\").append($(\"<a></a>\").append($(\"<i> \"+c+\"</i>\").addClass(\"fas \"+b))),a,\"click\"));n(a)}function B(){var a=h.get(0),b=a.selectionStart,c=a.value.substr(0,b).lastIndexOf(\"\\n\")+1;a=a.value.substr(c,b-c);b=\"\";for(c=0;\" \"===(ch=a.substr(c,1))||\"\\t\"===ch;)c++,b+=ch;\"{\"===a.substr(a.length-1,1)&&(b+=\"  \");return b}function l(a){var b=h.get(0),\nc=b.selectionStart;a=a.split(\"\\n\").map(function(e,f){if(0===f)var g=\"\";else{var k=h.get(0).selectionStart;k=h.val().substr(0,k);for(var t=\"\",w=1;\" \"===(g=k.substr(-w,1))||\"\\t\"===g;)w++,t=g+t;g=t}return g+e}).join(\"\\n\");h.setRangeText?h.setRangeText(a):(h.focus(),document.execCommand(\"insertText\",!1,a));a=function(e){for(var f=0;f<m.length;f++){var g=e.indexOf(m[f]);if(-1!==g)return g}return-1}(a);-1!==a&&(b.selectionStart=a+c,b.selectionEnd=b.selectionStart+1);h.blur();h.focus()}function x(a){h.val(a+\nh.val().trimEnd());l(\"\\n\")}if(window.chrome){$(\".alpaca-field.alpaca-field-textarea textarea\").addClass(\"editor allow-tabs\").wrap($(\"<div></div>\").addClass(\"scroller\")).parent().append($(\"<pre></pre>\").append($(\"<code></code>\").addClass(\"syntax-highight javascript\"))).wrap($(\"<div></div>\").addClass(\"highlight-editor-holder\")).parent().prepend($(\"<ul></ul>\").addClass(\"toolbar\"));r(\"easy-scripting-devices-events\",\"fa-play\",\"__m_events__\");r(\"easy-scripting-devices-objects\",\"fa-lightbulb\",\"__m_devices__\");\nr(\"easy-scripting-syntax\",\"fa-code\",\"__m_expressions__\");$.ajax(\"/ZAutomation/api/v1/devices\").done(function(a){a.data.devices.sort(function(b,c){return b.metrics.title===c.metrics.title?b.id<c.id?-1:1:b.metrics.title<c.metrics.title?-1:1}).forEach(function(b){v(\"easy-scripting-devices-events\",b.id,b.metrics.title+\" (\"+b.id+\")\",function(){x(\"### \"+b.id+\" // \"+b.metrics.title+\"\\n\")});v(\"easy-scripting-devices-objects\",b.id,b.metrics.title+\" (\"+b.id+\")\",function(){l('vdev(\"'+b.id+'\")')})})}).fail(function(){alert(\"no devices\")});\nvar m=[\"\\u229c\",\"\\u2299\",\"\\u2026\"],h=$(\".alpaca-field.alpaca-field-textarea textarea\");n(\"easy-scripting-syntax\");d(\"easy-scripting-syntax\",\"__m_if__\",\"if (\\u229c) {\\n  \\u2026\\n}\");d(\"easy-scripting-syntax\",\"__m_for_loop__\",\"for (var i = 0; i < \\u2299; i++) {\\n  \\u2026\\n}\");d(\"easy-scripting-syntax\",\"__m_while_loop__\",\"while (\\u229c) {\\n  \\u2026\\n}\");q(\"easy-scripting-syntax\");d(\"easy-scripting-syntax\",\"__m_or__\",\"\\u229c || \\u229c\");d(\"easy-scripting-syntax\",\"__m_and__\",\"\\u229c && \\u229c\");q(\"easy-scripting-syntax\");\nd(\"easy-scripting-syntax\",\"__m_http_request__\",'http.request({method: \"GET\", async: true, url: \\u2299});');d(\"easy-scripting-syntax\",\"__m_set_timeout__\",'setTimer(\"\\u2026\", function() {\\n  \\u2026\\n}, \\u2299)');d(\"easy-scripting-syntax\",\"__m_remove_timeout__\",'stopTimer(\"\\u2026\")');n(\"easy-scripting-device-methods\");d(\"easy-scripting-device-methods\",\"__m_turn_on__\",\"on()\");d(\"easy-scripting-device-methods\",\"__m_turn_off__\",\"off()\");d(\"easy-scripting-device-methods\",\"__m_turn_set__\",\"set(\\u2299)\");\nd(\"easy-scripting-device-methods\",\"__m_update__\",\"update()\");q(\"easy-scripting-device-methods\");d(\"easy-scripting-device-methods\",\"__m_is_on__\",'value() === \"on\"');d(\"easy-scripting-device-methods\",\"__m_is_off__\",'value() === \"off\"');d(\"easy-scripting-device-methods\",\"__m_equals__\",\"value() === \\u2299\");d(\"easy-scripting-device-methods\",\"__m_ne__\",\"value() !== \\u2299\");d(\"easy-scripting-device-methods\",\"__m_gt__\",\"value() > \\u2299\");d(\"easy-scripting-device-methods\",\"__m_ge__\",\"value() >= \\u2299\");\nd(\"easy-scripting-device-methods\",\"__m_lt__\",\"value() < \\u2299\");d(\"easy-scripting-device-methods\",\"__m_le__\",\"value() <= \\u2299\");d(\"easy-scripting-device-methods\",\"__m_value__\",\"value()\");$(h).click(function(){this.selectionStart===this.selectionEnd&&-1!==m.indexOf(this.value.substr(this.selectionStart,1))?this.selectionEnd=this.selectionStart+1:this.selectionStart===this.selectionEnd&&-1!==m.indexOf(this.value.substr(this.selectionStart-1,1))&&(this.selectionEnd=this.selectionStart,this.selectionStart--)});\n$(h).keypress(function(a){if(\".\"===a.key){if(this.value.substr(0,this.selectionStart).match(/.*vdev\\(\"[\\w-]+\"\\)$/)){a=y(this,this.selectionEnd);var b=this.getBoundingClientRect();a.top+=b.top+10;a.left+=b.left+10;u(\"easy-scripting-device-methods\",a)}}else if(\"Enter\"===a.key){var c=B();setTimeout(function(){l(c)},0)}else p(\"easy-scripting-device-methods\")});document.querySelectorAll(\"pre code\").forEach(function(a){hljs.highlightElement(a)});x(\"\")}else $(\".alpaca-field.alpaca-field-textarea textarea\").parent().prepend($(\"<div></div>\").text(\"__h_unsupported__\"))}\n;\n"
  },
  {
    "path": "modules/EasyScripting/index.js",
    "content": "/*** EasyScripting Z-Way HA module *******************************************\n\n(c) Z-Wave.Me, 2021\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Yurkin Vitaliy <aivs@z-wave.me>\nDescription:\n\tEasy Scripting language for home automation scripts\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction EasyScripting (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tEasyScripting.super_.call(this, id, controller);\n}\n\ninherits(EasyScripting, AutomationModule);\n\n_module = EasyScripting;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nEasyScripting.prototype.init = function (config) {\n\tEasyScripting.super_.prototype.init.call(this, config);\n\n\t// make sure to hide all local variables in script execution\n\tvar self = this;\n\t\n\t// helpers in script\n\tthis.setHelpers();\n\t\n\t// extract events and the code\n\tthis.code = this.config.script.split('\\n').filter(function(s) { return !s.match(/^###/); }).join('\\n');\n\tthis.events = this.config.script.split('\\n').filter(function(s) { return s.match(/^###/); }).map(function(s) { return s.match(/^###\\W*([\\w-]*)\\W*/)[1]; });\n\t\n\ttry {\n\t\teval('this.script = function(global, vdev, setTimer, stopTimer, on, off) { \"use strict\";' + this.code + '};');\n\t} catch (e) {\n\t\tthis.addNotification(\"error\", e.toString(), \"module\");\n\t\treturn;\n\t}\n\t\n\tthis.onEvent = function(trigger) {\n\t\tif (self.running) {\n\t\t\tself.addNotification(\"error\", \"Loop detected\", \"module\");\n\t\t\treturn;\n\t\t}\n\t\t\n\t\ttry {\n\t\t\tself.running = true;\n\t\t\tself.trigger = trigger;\n\t\t\t\n\t\t\t// make sure to hide outer scope variables and global variables\n\t\t\tvar _script = self.script;\n\t\t\t(function(global, self, vdev, setTimer, stopTimer) {\n\t\t\t\t_script(global, vdev, setTimer, stopTimer, \"on\", \"off\");\n\t\t\t})(EasyScripting.globals, undefined, self.vDevHelper, self.setTimer, self.stopTimer);\n\t\t} finally {\n\t\t\tself.running = false;\n\t\t}\n\t};\n\n\t// event handlers for each vDevId\n\tself.eventHandlers = [];\n\n\tthis.events.forEach(function(vDevId) {\n\t\ttry {\n\t\t\tvar onEvent = self.eventHandlers[vDevId];\n\t\t\tif (!onEvent) {\n\t\t\t\tonEvent = function() { self.onEvent(vDevId); };\n\t\t\t\tself.eventHandlers[vDevId] = onEvent;\n\t\t\t}\n\t\t\tself.controller.devices.on(vDevId, \"change:metrics:level\", onEvent);\n\t\t} catch(e) {\n\t\t\tself.addNotification(\"error\", e.toString(), \"module\");\n\t\t}\n\t});\n};\n\nEasyScripting.prototype.stop = function () {\n\tEasyScripting.super_.prototype.stop.call(this);\n\t\n\tvar self = this;\n\t\n\tthis.events.forEach(function(vDevId) {\n\t\ttry {\n\t\t\tvar onEvent = self.eventHandlers[vDevId];\n\t\t\tif (onEvent)\n\t\t\t\tself.controller.devices.off(vDevId, \"change:metrics:level\", onEvent);\n\t\t} catch(e) {\n\t\t}\n\t});\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nEasyScripting.prototype.setHelpers = function() {\n\tvar self = this;\n\t\n\tvar constr = this.constructor;\n\t\n\t// glabal.xxx in scrpits\n\t// create one static propery for globals\n\tif (!constr.globals) {\n\t\tconstr.globals = {};\n\t\tconstr.timers = {};\n\t}\n\t\n\t// Timers\n\t\n\tthis.setTimer = function(name, func, timeout) {\n\t\tself.stopTimer(name);\n\t\tconstr.timers[name] = setTimeout(func, timeout*1000);\n\t};\n\tthis.stopTimer = function(name) {\n\t\tif (constr.timers[name]) {\n\t\t\tclearTimeout(constr.timers[name]);\n\t\t}\n\t};\n\t\n\t// VDev\n\t\n\tvar vDevWrapper = function(vDevId) {\n\t\tthis.dev = self.controller.devices.get(vDevId);\n\t};\n\t\n\tvDevWrapper.prototype.on = function() {\n\t\tthis.dev.performCommand(\"on\");\n\t};\n\t\n\tvDevWrapper.prototype.off = function() {\n\t\tthis.dev.performCommand(\"off\");\n\t};\n\t\n\tvDevWrapper.prototype.update = function() {\n\t\tthis.dev.performCommand(\"update\");\n\t};\n\t\n\tvDevWrapper.prototype.set = function(level) {\n\t\tthis.dev.performCommand(\"exact\", { level: level });\n\t};\n\t\n\tvDevWrapper.prototype.value = function() {\n\t\treturn this.dev.get(\"metrics:level\");\n\t};\n\t\n\tvDevWrapper.prototype.open = function() {\n\t\tthis.dev.performCommand(\"open\");\n\t};\n\n\tvDevWrapper.prototype.close = function() {\n\t\tthis.dev.performCommand(\"close\");\n\t};\n\n\tvDevWrapper.prototype.up = function() {\n\t\tthis.dev.performCommand(\"up\");\n\t};\n\n\tvDevWrapper.prototype.down = function() {\n\t\tthis.dev.performCommand(\"down\");\n\t};\n\n\tvDevWrapper.prototype.max = function() {\n\t\tthis.dev.performCommand(\"max\");\n\t};\n\n\tvDevWrapper.prototype.min = function() {\n\t\tthis.dev.performCommand(\"min\");\n\t};\n\n\tvDevWrapper.prototype.stop = function() {\n\t\tthis.dev.performCommand(\"stop\");\n\t};\n\n\tvDevWrapper.prototype.startUp = function() {\n\t\tthis.dev.performCommand(\"startUp\");\n\t};\n\n\tvDevWrapper.prototype.startDown = function() {\n\t\tthis.dev.performCommand(\"startDown\");\n\t};\n\n\t// export to local instance\n\tthis.vDevHelper = function(vDevId) {\n\t\treturn new vDevWrapper(vDevId);\n\t}\n};\n\n"
  },
  {
    "path": "modules/EasyScripting/lang/en.json",
    "content": "{\n\t\"m_title\":\"Easy Scripting\",\n\t\"m_descr\":\"Examples how to easy make automation on JavaScript (ECMA5).<br><br><b>Directive to run the script when the device state changes (there may be several):</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_6-1-48<br>### ZWayVDev_zway_4-1-37</code></pre><br><b>Turn on/off device:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").on()<br>vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").off()</code></pre><br><b>Set device level:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">vdev(\\\\\\\"ZWayVDev_zway_5-1-38\\\\\\\").set(55)</code></pre><br><b>Get device value:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">var sensorValue = vdev(\\\\\\\"ZWayVDev_zway_6-1-48\\\\\\\").value()</code></pre><br><b>Device that started the script:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">selt.trigger</code></pre><br><b>Get the value of the device that started the script:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">var sensorValue = vdev(selt.trigger).value()</code></pre><br><b>Global variables for interaction between different applications. Create global variable:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">if (isNaN(global.myVar)) {global.myVar = 0}</code></pre><br><b>Set global variable:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">global.myVar = 10</code></pre><br><b>Send HTTP request:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">var req = {method: \\\\\\\"GET\\\\\\\", async: true}<br>req.url = \\\\\\\"http://192.168.1.108/19-1\\\\\\\"<br>http.request(req)</code></pre><br><b>On/Off according on the sensor value,<br>If-Then-Else expression:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_6-1-48<br>if (vdev(\\\\\\\"ZWayVDev_zway_6-1-48\\\\\\\").value() == \\\\\\\"on\\\\\\\") {<br>    vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").on()<br>}<br>else {<br>    vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").off()<br>}<br></code></pre><br><b>HTTP request according on the sensor value,<br>If-Then-Else expression:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_6-1-48<br>var req = {method: \\\\\\\"GET\\\\\\\", async: true}<br>if (vdev(\\\\\\\"ZWayVDev_zway_6-1-48\\\\\\\").value() == \\\\\\\"on\\\\\\\") {<br>    req.url = \\\\\\\"http://192.168.1.108/on\\\\\\\"<br>}<br>else {<br>    req.url = \\\\\\\"http://192.168.1.108/off\\\\\\\"<br>}<br>http.request(req)</code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\"></pre><br><b>Perform any action after the expiration of time (time is set in seconds)</b><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_4-1-37<br>setTimer(\\\\\\\"myTimer\\\\\\\", function() {<br>    vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").on()<br>}, 50)</code></pre><br><b>Cancel timer (function will not be executed)</b><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">stopTimer(\\\\\\\"myTimer\\\\\\\")</code></pre><br><b>List of supported commands:</b><pre>on, off, update, set, value, open, close, up, down ,max, min, stop, startUp, startDown</pre><br>Don't do infinite or slow loops!\",\n\t\"h_script\":\"The JavaScript (ECMA5) programming language is used for writing scripts.\",\n\t\"m_events\":\"Events\",\n\t\"m_devices\":\"Devices\",\n\t\"m_expressions\":\"Expressions\",\n\t\"m_if\":\"If then\",\n\t\"m_for_loop\":\"Loop from-to\",\n\t\"m_while_loop\":\"Loop while\",\n\t\"m_or\":\"Or\",\n\t\"m_and\":\"And\",\n\t\"m_http_request\":\"HTTP request\",\n\t\"m_set_timeout\":\"Set timer\",\n\t\"m_remove_timeout\": \"Remove timer\",\n\t\"m_turn_on\":\"turn on\",\n\t\"m_turn_off\":\"turn Off\",\n\t\"m_turn_set\":\"set to value\",\n\t\"m_update\": \"request value update\",\n\t\"m_value\":\"value\",\n\t\"m_is_on\":\"is on\",\n\t\"m_is_off\":\"is off\",\n\t\"m_equals\":\"equal to\",\n\t\"m_ne\":\"not equal to\",\n\t\"m_gt\":\"greater than\",\n\t\"m_ge\":\"greater than or equal to\",\n\t\"m_lt\":\"less than\",\n\t\"m_le\":\"less than or equal to\",\n\t\"h_unsupported\":\"Unfortunatelly only Google Chrome supports advanced code editor. You can still use this app without pretty code editor.\"\n}\n"
  },
  {
    "path": "modules/EasyScripting/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Простые Скрипты\",\n\t\"m_descr\":\"Примеры, как просто писать скрипты автоматизации на JavaScript (ECMA5).<br><br><b>В начале определяем устройства, при изменении состояния которых будет запускаться скрипт (может быть несколько):</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_6-1-48<br>### ZWayVDev_zway_4-1-37</code></pre></pre><br><b>Включить/выключить устройство:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").on()<br>vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").off()</code></pre><br><b>Установить уровень:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">vdev(\\\\\\\"ZWayVDev_zway_5-1-38\\\\\\\").set(55)</code></pre><br><b>Получить значение:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">var sensorValue = vdev(\\\\\\\"ZWayVDev_zway_6-1-48\\\\\\\").value()</code></pre><br><b>Устройство, которое запустило скрипт:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">selt.trigger</code></pre><br><b>Получить значение устройства, которое запустило скрипт:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">var sensorValue = vdev(selt.trigger).value()</code></pre><br><b>Глобальные переменные для взаимодействия между разными приложениями. Создать глобальную переменную:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">if (isNaN(global.myVar)) {global.myVar = 0}</code></pre><br><b>Задать глобальную переменную:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">global.myVar = 10</code></pre><br><b>Отправить HTTP запрос:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">var req = {method: \\\\\\\"GET\\\\\\\", async: true}<br>req.url = \\\\\\\"http://192.168.1.108/19-1\\\\\\\"<br>http.request(req)</code></pre><br><b>Включить/выключить устройство в зависимости от состояния датчика,<br>Если-Тогда-Иначе выражение:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_6-1-48<br>if (vdev(\\\\\\\"ZWayVDev_zway_6-1-48\\\\\\\").value() == \\\\\\\"on\\\\\\\") {<br>    vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").on()<br>}<br>else {<br>    vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").off()<br>}</code></pre><br><b>Отправить HTTP запрос в зависимости от состояния датчика,<br>Если-Тогда-Иначе выражение:</b><br><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_6-1-48<br>var req = {method: \\\\\\\"GET\\\\\\\", async: true}<br>if (vdev(\\\\\\\"ZWayVDev_zway_6-1-48\\\\\\\").value() == \\\\\\\"on\\\\\\\") {<br>    req.url = \\\\\\\"http://192.168.1.108/on\\\\\\\"<br>}<br>else {<br>    req.url = \\\\\\\"http://192.168.1.108/off\\\\\\\"<br>}<br>http.request(req)</code></pre><br><b>Выполнить какое либо действие по истечении времени (время задается в секундах)</b><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">### ZWayVDev_zway_4-1-37<br>setTimer(\\\\\\\"myTimer\\\\\\\", function() {<br>    vdev(\\\\\\\"ZWayVDev_zway_4-1-37\\\\\\\").on()<br>}, 50)</code></pre><br><b>Отменить таймер (функция не будет выполнена)</b><pre><code class=\\\\\\\"syntax-highight javascript hljs\\\\\\\">stopTimer(\\\\\\\"myTimer\\\\\\\")</code></pre><br><b>Список поддерживаемых команд:</b><pre>on, off, update, set, value, open, close, up, down ,max, min, stop, startUp, startDown</pre><br>Не делайте бесконечные или медленные циклы!\",\n\t\"h_script\":\"Для написания скриптов используется язык программирование JavaScript (ECMA5).\",\n\t\"m_events\":\"События\",\n\t\"m_devices\":\"Устройства\",\n\t\"m_expressions\":\"Выражения\",\n\t\"m_if\":\"Если, то\",\n\t\"m_for_loop\":\"Цикл от и до\",\n\t\"m_while_loop\":\"Цикл пока\",\n\t\"m_or\":\"ИЛИ\",\n\t\"m_and\":\"И\",\n\t\"m_http_request\":\"HTTP запрос\",\n\t\"m_set_timeout\":\"Установить таймер\",\n\t\"m_remove_timeout\": \"Удалить таймер\",\n\t\"m_turn_on\":\"включить\",\n\t\"m_turn_off\":\"выключить\",\n\t\"m_turn_set\":\"установить значение\",\n\t\"m_update\": \"запросить обновление значения\",\n\t\"m_value\":\"значение\",\n\t\"m_is_on\":\"включено\",\n\t\"m_is_off\":\"выключено\",\n\t\"m_equals\":\"равно\",\n\t\"m_ne\":\"не равно\",\n\t\"m_gt\":\"больше\",\n\t\"m_ge\":\"больше или равно\",\n\t\"m_lt\":\"меньше\",\n\t\"m_le\":\"меньше или равно\",\n\t\"h_unsupported\":\"К сожалению продвинутые функции редактора кода поддерживаются только в Google Chrome. Вы можете использовать данное приложение без продвинутого редактора кода.\"\n}\n"
  },
  {
    "path": "modules/EasyScripting/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"developers_stuff\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"EasyScripting\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"script\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"script\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"script\": {\n\t\t\t\t\"type\": \"textarea\",\n\t\t\t\t\"helper\": \"__h_script__\"\n\t\t\t}\n\t\t}\n\t},\n\t\"postRender\": \"loadFunction:postRender.js\"\n}\n"
  },
  {
    "path": "modules/EdimaxSP1101/index.js",
    "content": "/*** EdimaxSP1101 Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Karsten Reichel <kar@zwave.eu>\nDescription:\n\tThis module allows to switch the Edimax SP-1101 plug.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\n\nfunction EdimaxSP1101 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tEdimaxSP1101.super_.call(this, id, controller);\n}\n\ninherits(EdimaxSP1101, AutomationModule);\n\n_module = EdimaxSP1101;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nEdimaxSP1101.prototype.init = function (config) {\n\tEdimaxSP1101.super_.prototype.init.call(this, config);\n\t\t\n\t\tvDevId = 'EdimaxSP1101_' + this.id;\n\n\t\tthis.url = 'http://admin:1234@' + config.url + ':10000/smartplug.cgi';\n\n\t\tthis.xml = '<?xml version=\"1.0\" encoding=\"utf-8\"?><SMARTPLUG id=\"edimax\"><CMD id=\"setup\"><Device.System.Power.State>${state}</Device.System.Power.State></CMD></SMARTPLUG>';\t\t\n\t\t\t\n\t\tvar self = this;\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: 'switch',\n\t\t\t\t\tlevel: 'off', \n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t},\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tdeviceType: 'switchBinary'\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tif (command != 'update') {\n\t\t\t\t\tvar data = self.xml.replace('${state}',command.toUpperCase());\t\t\t\t\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\t\turl: self.url,\n\t\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\t\tdata: data,\n\t\t\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\t\t\tself.vDev.set('metrics:level', command);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terror: function(response) {\n\t\t\t\t\t\t\t\tconsole.log('EdimaxSP1101 - ERROR: ' + response.statusText); \n\t\t\t\t\t\t\t} \n\t\t\t\t\t\t});\n\t\t\t\t}\t\t\t\t\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n};\n\nEdimaxSP1101.prototype.stop = function () {\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tEdimaxSP1101.super_.prototype.stop.call(this);\n};\n"
  },
  {
    "path": "modules/EdimaxSP1101/lang/de.json",
    "content": "{\n\t\"m_title\":\"Edimax SP-1101\",\n\t\"m_descr\":\"Diese App ermöglicht Ihnen die Steuerung Ihrer Edimax SP-1101 WLAN Steckdose. Geben Sie dazu einfach die IP-Adresse der komplett eingerichteten WLAN Steckdose an.\",\n\t\"ip\":\"IP-Adresse des Schalters\",\n\t\"h_ip\":\"Beispielformat: '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/EdimaxSP1101/lang/en.json",
    "content": "{\n\t\"m_title\":\"Edimax SP-1101\",\n\t\"m_descr\":\"This app allows you to control your Edimax SP-1101 WLAN plugs. Simply enter the IP address of the completely configured WLAN plug.\",\n\t\"ip\":\"Plug IP URL\",\n\t\"h_ip\":\"in the format '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/EdimaxSP1101/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"wifiplug\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://www.edimax.com/\",\n    \"state\": null,\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"EdimaxSP1101\",\n    \"version\": \"1.0.0\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n            \"type\": \"git\",\n            \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n\t\"url\": \"\"\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"url\": {\n                \"required\": true\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"url\": {\n                \"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",                \n                \"required\": true\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/EdimaxSP2101/index.js",
    "content": "/*** EdimaxSP2101 Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Karsten Reichel <kar@zwave.eu>\nDescription:\n\tThis module allows to switch the Edimax SP-2101 plug.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\n\nfunction EdimaxSP2101 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tEdimaxSP2101.super_.call(this, id, controller);\n}\n\ninherits(EdimaxSP2101, AutomationModule);\n\n_module = EdimaxSP2101;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nEdimaxSP2101.prototype.init = function (config) {\n\tEdimaxSP2101.super_.prototype.init.call(this, config);\n\t\t\n\t\tvDevId = 'EdimaxSP2101_' + this.id;\n\n\t\tthis.url = 'http://admin:1234@' + config.url + ':10000/smartplug.cgi';\n\n\t\tthis.xml = '<?xml version=\"1.0\" encoding=\"utf-8\"?><SMARTPLUG id=\"edimax\"><CMD id=\"setup\"><Device.System.Power.State>${state}</Device.System.Power.State></CMD></SMARTPLUG>';\t\t\n\t\t\t\n\t\tvar self = this;\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: 'switch',\n\t\t\t\t\tlevel: 'off', \n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t},\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tdeviceType: 'switchBinary'\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tif (command != 'update') {\n\t\t\t\t\tvar data = self.xml.replace('${state}',command.toUpperCase());\t\t\t\t\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\t\turl: self.url,\n\t\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\t\tdata: data,\n\t\t\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\t\t\tself.vDev.set('metrics:level', command);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\terror: function(response) {\n\t\t\t\t\t\t\t\tconsole.log('EdimaxSP2101 - ERROR: ' + response.statusText); \n\t\t\t\t\t\t\t} \n\t\t\t\t\t\t});\n\t\t\t\t}\t\t\t\t\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n};\n\nEdimaxSP2101.prototype.stop = function () {\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tEdimaxSP2101.super_.prototype.stop.call(this);\n};\n"
  },
  {
    "path": "modules/EdimaxSP2101/lang/de.json",
    "content": "{\n\t\"m_title\":\"Edimax SP-2101\",\n\t\"m_descr\":\"Diese App ermöglicht Ihnen die Steuerung Ihrer Edimax SP-2101 WLAN Steckdose. Geben Sie dazu einfach die IP-Adresse der komplett eingerichteten WLAN Steckdose an.\",\n\t\"ip\":\"IP-Adresse des Schalters\",\n\t\"h_ip\":\"Beispielformat: '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/EdimaxSP2101/lang/en.json",
    "content": "{\n\t\"m_title\":\"Edimax SP-2101\",\n\t\"m_descr\":\"This app allows you to control your Edimax SP-2101 WLAN plugs. Simply enter the IP address of the completely configured WLAN plug.\",\n\t\"ip\":\"Plug IP URL\",\n\t\"h_ip\":\"in the format '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/EdimaxSP2101/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"wifiplug\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://www.edimax.com/\",\n    \"state\": null,\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"EdimaxSP2101\",\n    \"version\": \"1.0.0\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n            \"type\": \"git\",\n            \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n\t\"url\": \"\"\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"url\": {\n                \"required\": true\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"url\": {\n                \"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",                \n                \"required\": true\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/EnOcean/index.js",
    "content": "/*** EnOcean Binding module ********************************************************\n\nVersion: 1.0.0\n-------------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>\nCopyright: (c) Z-Wave.Me, 2015\n\n******************************************************************************/\n\nfunction EnOcean (id, controller) {\n\n\t// if called without \"new\", return list of loaded EnOcean instances\n\tif (!(this instanceof EnOcean))\n\t\treturn EnOcean.list();\n\n\tEnOcean.super_.call(this, id, controller);\n\n\tthis.ENOCEAN_DEVICE_CHANGE_TYPES = {\n\t\t\"DeviceAdded\": 0x01,\n\t\t\"DeviceRemoved\": 0x02,\n\t\t\"DeviceProfileChanged\": 0x04,\n\t\t\"ZDDXSaved\": 0x100,\n\t\t\"EnumerateExisting\": 0x200\n\t};\n\n\tthis.ZWAY_DATA_CHANGE_TYPE = {\n\t\t\"Updated\": 0x01,\t   // Value updated or child created\n\t\t\"Invalidated\": 0x02,   // Value invalidated\n\t\t\"Deleted\": 0x03,\t   // Data holder deleted - callback is called last time before being deleted\n\t\t\"ChildCreated\": 0x04,  // New direct child node created\n\n\t\t// ORed flags\n\t\t\"PhantomUpdate\": 0x40, // Data holder updated with same value (only updateTime changed)\n\t\t\"ChildEvent\": 0x80\t // Event from child node\n\t};\n}\n\n// Module inheritance and setup\n\ninherits(EnOcean, AutomationModule);\n\n_module = EnOcean;\n\nObject.defineProperty(EnOcean, \"list\", {\n\tvalue: function () {\n\t\treturn Object.keys(EnOcean);\n\t},\n\tenumerable: false,\n\twritable: false,  \n\tconfigurable: false \n});\nws.allowExternalAccess(\"EnOcean.list\", controller.auth.ROLE.ADMIN);\n\nEnOcean.prototype.init = function (config) {\n\tEnOcean.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\t\n\tthis.startBinding();\n\tif (!this.zeno) {\n\t\treturn;\n\t}\n\n\tthis.controller.on(\"EnOcean.dataBind\", this._dataBind);\n\tthis.controller.on(\"EnOcean.dataUnbind\", this.dataUnbind);\n\n\tthis.controller.emit(\"EnOcean.register\", this.config.name);\n};\n\nEnOcean.prototype.startBinding = function () {\n\tvar self = this,\n\t\tlangFile = self.loadModuleLang();\n\n\ttry {\n\t\tthis.zeno = new EnoceanBinding(this.config.name, this.config.port, {\n\t\t\tconfigFolder: this.config.config || 'config',\n\t\t\tterminationCallback: function() {\n\t\t\t\tself.terminating.call(self);\n\t\t\t}\n\t\t});\n\t\t\n\t\ttry {\n\t\t\tthis.zeno.discover();\n\t\t} catch (e1) {\n\t\t\tthis.zeno.stop();\n\t\t\tthrow e1;\n\t\t}\n\t} catch(e) {\n\t\tthis.addNotification(\"critical\", langFile.err_binding_start + e.toString(), \"enocean\");\n\t\tthis.zeno = null;\n\t\treturn;\n\t}\n\n\tthis.fastAccess = false;\n\tif (!global.zeno) {\n\t\t// this is the first zeno - make fast shortcut\n\t\tthis.fastAccess = true;\n\t}\n\n\tglobal.EnOcean[this.config.name] = {\n\t\t\"zeno\": this.zeno,\n\t\t\"port\": this.config.port,\n\t\t\"fastAccess\": this.fastAccess\n\t};\n\n\tthis.stopped = false;\n\t\n\tif (this.config.enableAPI !== false) {\n\t\tthis.defineHandlers();\n\t}\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIAllow();\n\t\t}\n\t\tglobal[\"zeno\"] = this.zeno; // global variable\n\t\tglobal[\"EnOceanAPI\"] = this.EnOceanAPI;\n\t}\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIAllow(this.config.name);\n\t}\n\t_.extend(global[\"EnOcean\"][this.config.name], this.EnOceanAPI);\n\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStart();\n\t}\n\t\n\t// save data every hour for hot start\n\tthis.saveDataXMLTimer = setInterval(function() {\n\t\tself.zeno.devices.SaveData();\n\t}, 3600 * 1000);\n\t\n\t// unregister function\n\tthis.zeno.unregisterDevice = function(name) {\n\t\tdelete self.zeno.devices[name];\n\t};\n};\n\nEnOcean.prototype.stop = function () {\n\tconsole.log(\"--- EnOcean.stop()\");\n\tEnOcean.super_.prototype.stop.call(this);\n\n\tthis.stopBinding();\n\n\tthis.controller.off(\"EnOcean.dataBind\", this._dataBind);\n\tthis.controller.off(\"EnOcean.dataUnbind\", this.dataUnbind);\n};\n\nEnOcean.prototype.stopBinding = function () {\n\tthis.controller.emit(\"EnOcean.unregister\", this.config.name);\n\t\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStop();\n\t}\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIRevoke();\n\t\t}\n\t\tif (global.zeno) {\n\t\t\tdelete global[\"zeno\"];\n\t\t\tdelete global[\"EnOceanAPI\"];\n\t\t}\n\t}\n\t\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIRevoke(this.config.name);\n\t}\n\tif (global.EnOcean) {\n\t\tdelete global.EnOcean[this.config.name];\n\t}\n\n\tif (this.saveDataXMLTimer) {\n\t\tclearInterval(this.saveDataXMLTimer);\n\t\tthis.saveDataXMLTimer = undefined;\n\t}\n\n\tthis.stopped = true;\n\tif (this.zeno) {\n\t\ttry {\n\t\t\tthis.zeno.stop();\n\t\t} catch(e) {\n\t\t\t// EnOcean has already gone\n\t\t}\n\t\tthis.zeno = null;\n\t}\n};\n\nEnOcean.prototype.terminating = function () {\n\tif (!this.stopped) {\n\t\tconsole.log(\"Terminating EnOcean binding\");\n\t\tthis.stopBinding();\n\n\t\tvar self = this;\n\t\tsetTimeout(function() {\n\t\t\t// retry open after 5 seconds\n\t\t\tconsole.log(\"Restarting EnOcean binding\");\n\t\t\tself.startBinding();\n\t\t}, 5000);\n\t}\n};\n\n\n// --------------- Public HTTP API -------------------\n\n\nEnOcean.prototype.externalAPIAllow = function (name) {\n\tvar _name = !!name ? (\"EnOcean.\" + name) : \"EnOceanAPI\";\n\n\tws.allowExternalAccess(_name, this.config.publicAPI ? this.controller.auth.ROLE.ADMIN : this.controller.auth.ROLE.ANONYMOUS);\n\tws.allowExternalAccess(_name + \".Run\", this.config.publicAPI ? this.controller.auth.ROLE.ADMIN : this.controller.auth.ROLE.ANONYMOUS);\n\tws.allowExternalAccess(_name + \".Data\", this.config.publicAPI ? this.controller.auth.ROLE.ADMIN : this.controller.auth.ROLE.ANONYMOUS);\n};\n\nEnOcean.prototype.externalAPIRevoke = function (name) {\n\tvar _name = !!name ? (\"EnOcean.\" + name) : \"EnOceanAPI\";\n\n\tws.revokeExternalAccess(_name);\n\tws.revokeExternalAccess(_name + \".Run\");\n\tws.revokeExternalAccess(_name + \".Data\");\n};\n\nEnOcean.prototype.defineHandlers = function () {\n\tvar zeno = this.zeno;\n\n\tthis.EnOceanAPI = function() {\n\t\treturn { status: 400, body: \"Bad EnOceanAPI request \" };\n\t};\n\n\tthis.EnOceanAPI.Run = function(url) {\n\t\turl = \"with(zeno) { \" + url.substring(1) + \" }\";\n\t\ttry {\n\t\t\tvar r = eval(url);\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: r\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn { status: 500, body: e.toString() };\n\t\t}\n\t};\n\n\tthis.EnOceanAPI.Data = function(url) {\n\t\tvar timestamp = parseInt(url.substring(1), 10) || 0;\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zeno.data(timestamp)\n\t\t};\n\t};\n};\n\n\n// ------------- Data Binding --------------\n\nEnOcean.prototype._dataBind = function(dataBindings, zenoName, nodeId, path, func, type) {\n\tif (zenoName === this.config.name && self.zeno) {\n\t\tthis.dataBind(dataBindings, this.zeno, nodeId, path, func, type);\n\t}\n};\n\nEnOcean.prototype.dataBind = function(dataBindings, zeno, nodeId, path, func, type) {\n\t// two prototypes:\n\t//  (dataBindings, zeno, nodeId, path, func)\n\t//  (dataBindings, zeno,         path, func) // bind to controller data\n\t\n\tvar pathArr = [],\n\t\tdata = null,\n\t\tctrlBind = is_function(path);\n\n\tif (ctrlBind) {\n\t\tvar t = path;\n\t\tpath = nodeId;\n\t\tfunc = t;\n\t\tnodeId = undefined;\n\t\tdata = zeno.controller.data;\n\t} else {\n\t\tdata = zeno.devices[nodeId].data;\n\t}\n\n\tif (path) {\n\t\tpathArr = path.split(\".\");\n\t}\n\n\tif (!func) {\n\t\tconsole.log(\"Function passed to dataBind is undefined\");\n\t\treturn;\n\t}\n\n\twhile (pathArr.length) {\n\t\tdata = data[pathArr.shift()];\n\t\tif (!data) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (data) {\n\t\tif (ctrlBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zeno\": zeno,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, false)\n\t\t\t});\n\t\t} else {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zeno\": zeno,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, nodeId, false)\n\t\t\t});\n\t\t\tif (type === \"value\") {\n\t\t\t\tfunc.call(data, this.ZWAY_DATA_CHANGE_TYPE.Updated);\n\t\t\t}\n\t\t}\n\t} else {\n\t \tconsole.log(\"Can not find data path:\", nodeId, path);\n\t}\n};\n\nEnOcean.prototype.dataUnbind = function(dataBindings) {\n\tdataBindings.forEach(function (item) {\n\t\tvar ctrlBind = !(\"nodeId\" in item),\n\t\t\tdevBind = (\"nodeId\" in item);\n\n\t\tif (item.zeno && item.zeno.isRunning() && (ctrlBind || item.zeno.devices[item.nodeId])) {\n\t\t\tvar data = ctrlBind ? item.zeno.controller.data : item.zeno.devices[item.nodeId].data,\n\t\t\t\tpathArr = item.path ? item.path.split(\".\") : [];\n\n\t\t\twhile (pathArr.length) {\n\t\t\t\tdata = data[pathArr.shift()];\n\t\t\t\tif (!data) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data) {\n\t\t\t\tdata.unbind(item.func);\n\t\t\t} else {\n\t\t\t\tconsole.log(\"Can not find data path:\", item.nodeId, item.path);\n\t\t\t}\n\t\t}\n\t});\n\tdataBindings = null;\n};\n\n\n// ----------------- Devices Creator ---------------\n\nEnOcean.prototype.gateDevicesStart = function () {\n\n\tvar self = this;\n\n\tthis.gateDataBinding = [];\n\n\t// Bind to all future CommandClasses changes\n\tthis.gateBinding = this.zeno.bind(function (type, nodeId) {\n\t\tif (type === self.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceRemoved\"] || type === self.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceProfileChanged\"]) {\n\t\t\tself.removeProfile(nodeId);\n\t\t}\n\t\tif (type === self.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceAdded\"] && self.zeno.devices[nodeId].data.funcId !== null && self.zeno.devices[nodeId].data.typeId !== null || type === self.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceProfileChanged\"]) {\n\t\t\tself.parseProfile(nodeId);\n\t\t}\n\t\tif (type === self.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceAdded\"]) {\n\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, \"channels\", function(type) {\n\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Updated\"]) {\n\t\t\t\t\tself.parseGenericProfile(nodeId);\n\t\t\t\t}\n\t\t\t}, \"value\");\n\t\t}\n\t}, this.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceAdded\"] | this.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceRemoved\"] | this.ENOCEAN_DEVICE_CHANGE_TYPES[\"DeviceProfileChanged\"] | this.ENOCEAN_DEVICE_CHANGE_TYPES[\"EnumerateExisting\"]);\n\n\tthis.dataBind(this.gateDataBinding, this.zeno, \"lastExcludedDevice\", function(type) {\n\t\tif (this.value) {\n\t\t\tself.cleanupProfile(this.value);\n\t\t}\n\t}, \"\");\n};\n\nEnOcean.prototype.gateDevicesStop = function () {\n\tvar self = this;\n\t\n\t// delete devices\n\tthis.controller.devices.map(function (el) {\n\t\treturn el.id;\n\t}).filter(function(el) {\n\t\treturn el.indexOf(\"ZEnoVDev_\" + self.config.name + \"_\") === 0;\n\t}).forEach(function(el) {\n\t\tself.controller.devices.remove(el);\n\t});\n\t\n\t// releasing bindings\n\ttry {\n\t\tif (this.gateDataBinding) {\n\t\t\tthis.dataUnbind(this.gateDataBinding);\n\t\t}\n\t\tif (this.zeno) {\n\t\t\tthis.zeno.unbind(this.gateBinding);\n\t\t}\n\t} catch(e) {\n\t\t// EnOcean already gone, skip deallocation\n\t\t//this.zeno = null;\n\t}\n};\n\nEnOcean.prototype.removeProfile = function (nodeId) {\n\tvar self = this;\n\t\n\t// delete devices\n\tthis.vDevByNodeId(nodeId).forEach(function(el) {\n\t\tself.controller.devices.remove(el);\n\t});\n};\n\nEnOcean.prototype.cleanupProfile = function (nodeId) {\n\tvar self = this;\n\t\n\t// delete and cleanup devices\n\tthis.vDevByNodeId(nodeId).forEach(function(el) {\n\t\tself.controller.devices.remove(el);\n\t\tself.controller.devices.cleanup(el);\n\t});\n};\n\nEnOcean.prototype.vDevByNodeId = function (nodeId) {\n\tvar self = this;\n\t\n\treturn this.controller.devices.filter(function(el) {\n\t\treturn el.id.indexOf(\"ZEnoVDev_\" + self.config.name + \"_\" + nodeId + '_') === 0;\n\t}).map(function(el) {\n\t\treturn el.id;\n\t}).concat(\n\t\tObject.keys(self.controller.vdevInfo).filter(function(__id) {\n\t\t\treturn __id.indexOf(\"ZEnoVDev_\" + self.config.name + \"_\" + nodeId + '_') === 0;\n\t\t})\n\t);\n};\n\n// EnOcean Equipment Profiles (EEP)\nEnOcean.prototype.parseProfile = function (nodeId) {\n\tvar self = this,\n\t\tdeviceData = this.zeno.devices[nodeId].data,\n\t\tvDevIdPrefix = \"ZEnoVDev_\" + this.config.name + \"_\" + nodeId + \"_\";\n\t\t// vDev is not in this scope, but in {} scope for each type of device to allow reuse it without closures\n\n\ttry {\n\t\tfunction matchDevice(rorg, funcId, typeId) {\n\t\t\t// deviceData is defined in outer scope\n\t\t\treturn deviceData.rorg.value === rorg && deviceData.funcId.value === funcId && deviceData.typeId.value === typeId;\n\t\t}\n\n\t\t// below vDevIdPrefix and nodeId comes from this scope\n\t\t\n\t\tfunction binarySensor(dh, type, title, withTimeout, handler) {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + type)) return;\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + type,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: type,\n\t\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\t\ticon: type,\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ttitle: title\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, dh, function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar val = this.value;\n\t\t\t\t\t\tif (handler) {\n\t\t\t\t\t\t\tval = handler(val);\n\t\t\t\t\t\t\tif (val === null) return; // don't hanlde if null\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvDev.set(\"metrics:level\", val ? \"on\" : \"off\");\n\t\t\t\t\t\tif (withTimeout && val) {\n\t\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t}, 1000);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\n\t\tfunction multilevelSensor(dh, type, scale, title) {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + type)) return;\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + type,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: type,\n\t\t\t\t\t\tscaleTitle: scale,\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ticon: type,\n\t\t\t\t\t\ttitle: title\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, dh, function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\n\t\tfunction rockerSwitch() {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + \"switch\" + \"_left\") || self.controller.devices.get(vDevIdPrefix + \"switch\" + \"_right\")) return;\n\t\t\t\n\t\t\tvar vDevL = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + \"switch\" + \"_left\",\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: \"switchControl\",\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ticon: '',\n\t\t\t\t\t\ttitle: 'Left Rocker',\n\t\t\t\t\t\tchange: ''\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t}),\n\t\t\tvDevR = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + \"switch\" + \"_right\",\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: \"switchControl\",\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ticon: '',\n\t\t\t\t\t\ttitle: 'Right Rocker',\n\t\t\t\t\t\tchange: ''\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"on\" || command === \"off\") {\n\t\t\t\t\t\tthis.set(\"metrics:level\", command);\n\t\t\t\t\t}\n\t\t\t\t\tif (command === \"upstart\" || command === \"upstop\" || command === \"downstart\" || command === \"downstop\") {\n\t\t\t\t\t\tthis.set(\"metrics:change\", command);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t}),\n\t\t\tdt = 500, // in ms\n\t\t\ttimer = -1,\n\t\t\tleftPressed = false, rightPressed = false, leftUp = false, rightUp = false; // memorize pressed status\n\t\t\t\n\t\t\tif (vDevL && vDevR) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, \"energyBow\", function(type) {\n\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\t\t\t\t\t\n\t\t\t\t\tif (deviceData.energyBow.value) {\n\t\t\t\t\t\tleftPressed = deviceData.value1.value < 2 || deviceData.secondAction.value && deviceData.value2.value < 2;\n\t\t\t\t\t\tleftUp = deviceData.value1.value === 1 || deviceData.secondAction.value && deviceData.value2.value === 1;\n\t\t\t\t\t\trightPressed = deviceData.value1.value >= 2 || deviceData.secondAction.value && deviceData.value2.value >= 2;\n\t\t\t\t\t\trightUp = deviceData.value1.value === 3 || deviceData.secondAction.value && deviceData.value2.value === 3;\n\t\t\t\t\t\t\n\t\t\t\t\t\ttimer = setTimeout(function () {\n\t\t\t\t\t\t\t// timeout fired - this is a hold\n\t\t\t\t\t\t\ttry{\n\t\t\t\t\t\t\t\tif (leftPressed) {\n\t\t\t\t\t\t\t\t\tvDevL.set(\"metrics:change\", leftUp ? \"upstart\" : \"downstart\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (rightPressed) {\n\t\t\t\t\t\t\t\t\tvDevR.set(\"metrics:change\", rightUp ? \"upstart\" : \"downstart\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\ttimer = -1; \n\t\t\t\t\t\t}, dt);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar isHold = true;\n\t\t\t\t\t\tif (timer !== -1) {\n\t\t\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\t\t\ttimer = -1;\n\t\t\t\t\t\t\tisHold = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (isHold) {\n\t\t\t\t\t\t\t\t// release was long after press - this is a release\n\t\t\t\t\t\t\t\tif (leftPressed) {\n\t\t\t\t\t\t\t\t\tvDevL.set(\"metrics:change\", leftUp ? \"upstop\" : \"downstop\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (rightPressed) {\n\t\t\t\t\t\t\t\t\tvDevR.set(\"metrics:change\", rightUp ? \"upstop\" : \"downstop\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// release was short after press - this is a click\n\t\t\t\t\t\t\t\tif (leftPressed) {\n\t\t\t\t\t\t\t\t\tvDevL.set(\"metrics:level\", leftUp ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (rightPressed) {\n\t\t\t\t\t\t\t\t\tvDevR.set(\"metrics:level\", rightUp ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\t\t\t\t}, \"\");\n\t\t\t}\n\t\t}\n\n\t\tfunction thermostat(dh, type, scale, title) {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + type)) return;\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + type,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: \"thermostat\",\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tscaleTitle: scale, // TODO!!! Check if F scale is defined in EnOcean\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\tmin: 5,\n\t\t\t\t\t\tmax: 40,\n\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\ttitle: title\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tthis.set(\"metrics:level\", args.level);\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, dh, function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\n\t\tfunction binarySwitch(dh, type, title, valToVDev, vDevToVal) {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + type)) return;\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + type,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'switch',\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ttitle: title\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"on\" || command === \"off\") {\n\t\t\t\t\t\tif (vDevToVal) {\n\t\t\t\t\t\t\tself.zeno.devices[nodeId].data[dh].value = vDevToVal(command);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.zeno.devices[nodeId].data[dh].value = command === \"on\" ? true : false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvDev.set(\"metrics:level\", command);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, dh, function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (valToVDev) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", valToVDev(this.value));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\n\t\tif (matchDevice(0xf6, 0x02, 0x01)) {\n\t\t\t// Rocker\n\t\t\trockerSwitch();\n\t\t}\n\n\t\tif (matchDevice(0xd5, 0x00, 0x01)) {\n\t\t\t// Door\n\t\t\tbinarySensor(\"contact\", \"door\", \"Door Sensor\");\n\t\t}\n\t\t\n\t\tif (matchDevice(0xf6, 0x10, 0x00)) {\n\t\t\t// Window\n\t\t\tbinarySensor(\"open\", \"window\", \"Window Open Sensor\");\n\t\t\tbinarySensor(\"tilt\", \"window_tilt\", \"Window Tilt Sensor\");\n\t\t}\n\t\t\n\t\tif (matchDevice(0xf6, 0x10, 0x01)) {\n\t\t\t// Window\n\t\t\tbinarySensor(\"open\", \"window\", \"Window Open Sensor\");\n\t\t\tbinarySensor(\"tilt\", \"window_tilt\", \"Window Tilt Sensor\");\n\t\t}\n\t\t\n\t\tif (matchDevice(0xa5, 0x04, 0x01)) {\n\t\t\t// Tempretature & Humidity\n\t\t\tmultilevelSensor(\"humidity\", \"humidity\", '%', \"Humidity Sensor\");\n\t\t\tif (deviceData.TSensor.value) {\n\t\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t\t}\n\t\t}\n\n\t\tif (matchDevice(0xa5, 0x06, 0x01)) {\n\t\t\t// Luminance\n\t\t\tmultilevelSensor(\"illumination\" + deviceData.rangeSelect.value.toString(), \"luminance\", 'lux', \"Luminance\");\n\t\t}\n\n\t\tif (matchDevice(0xa5, 0x02, 0x05)) {\n\t\t\t// Tempretature\n\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t}\n\n\t\tif (matchDevice(0xa5, 0x07, 0x03)) {\n\t\t\t// Motion, Luminance and Supply Voltage\n\t\t\tmultilevelSensor(\"illumination\", \"luminance\", 'lux', \"Luminance\");\n\t\t\tmultilevelSensor(\"voltage\", \"voltage\", 'V', \"Supply Voltage\");\n\t\t\tbinarySensor(\"pir\", \"motion\", \"Motion Sensor\", true);\n\t\t}\n\t\t\n\t\tif (matchDevice(0xa5, 0x08, 0x01)) {\n\t\t\t// Motion, Luminance and Temperature Sensor\n\t\t\tmultilevelSensor(\"illumination\", \"luminance\", 'lux', \"Luminance\");\n\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t\tmultilevelSensor(\"voltage\", \"voltage\", 'V', \"Supply Voltage\");\n\t\t\tbinarySensor(\"pir\", \"motion\", \"Motion Sensor\", true);\n\t\t\tbinarySensor(\"occupancy\", \"general_purpose\", \"Occupancy button\");\n\t\t}\n\t\t\n\t\tif (matchDevice(0xa5, 0x09, 0x04)) {\n\t\t\t// CO2 & Tempretature & Humidity\n\t\t\tmultilevelSensor(\"concentration\", \"co\", 'ppm', \"CO2 Sensor\");\n\t\t\tif (deviceData.HSensor.value) {\n\t\t\t\tmultilevelSensor(\"humidity\", \"humidity\", '%', \"Humidity Sensor\");\n\t\t\t\t\t\t}\n\t\t\tif (deviceData.TSensor.value) {\n\t\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t\t}\n\t\t}\n\n\t\tif (matchDevice(0xa5, 0x10, 0x03)) {\n\t\t\t// Temperature Sensor, Set Point Control\n\t\t\tthermostat(\"setpoint\", \"heat\", '°C', \"Set Point Control\");\n\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t}\n\n\t\tif (matchDevice(0xa5, 0x10, 0x05)) {\n\t\t\t// Temperature Sensor, Set Point and Occupancy Control\n\t\t\tthermostat(\"setpoint\", \"heat\", '°C', \"Set Point Control\");\n\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t\tbinarySensor(\"occupancy\", \"motion\", \"Motion Sensor\");\n\t\t}\n\n\t\tif (matchDevice(0xa5, 0x10, 0x0a)) {\n\t\t\t// Temperature Sensor, Set Point Adjust and Single Input\n\t\t\tthermostat(\"setpoint\", \"heat\", '°C', \"Set Point Control\");\n\t\t\tmultilevelSensor(\"temperature\", \"temperature\", '°C', \"Temperature Sensor\");\n\t\t\tbinarySensor(\"contact\", \"door\", \"Door Sensor\");\n\t\t}\n\t\t\n\t\tif (matchDevice(0xd2, 0x06, 0x10)) {\n\t\t\t// Door\n\t\t\tbinarySensor(\"windowOpen\", \"door\", \"Door Sensor\");\n\t\t\tbinarySensor(\"preAlarm\", \"motion\", \"Pre Alarm\");\n\t\t\tbinarySensor(\"alarm\", \"alarm\", \"Alarm\");\n\t\t\tbinarySensor(\"preAlarmEnabled\", \"config1\", \"Pre Alarm\");\n\t\t\tbinarySwitch(\"setPreAlarm\", \"config2\", \"Set Pre Alarm\");\n\t\t\tbinarySwitch(\"setAlarm\", \"config3\", \"Set Alarm\");\n\t\t}\n\t\t\n\t\tif (matchDevice(0xd2, 0x06, 0x11)) {\n\t\t\t// Door\n\t\t\tbinarySensor(\"windowOpen\", \"door\", \"Door Sensor\");\n\t\t\tbinarySensor(\"windowTilt\", \"window_tilt\", \"Tilt Sensor\", undefined, function(val) {\n\t\t\t\tswitch(val) {\n\t\t\t\t\tcase 0: return false; // treat unknow as non-tilted\n\t\t\t\t\tcase 1: return true;\n\t\t\t\t\tcase 2: return false;\n\t\t\t\t\tcase 3: return null; // reserved - don't handle\n\t\t\t\t}\n\t\t\t});\n\t\t\tbinarySensor(\"preAlarm\", \"motion\", \"Pre Alarm\");\n\t\t\tbinarySensor(\"alarm\", \"alarm\", \"Alarm\");\n\t\t\tbinarySensor(\"preAlarmEnabled\", \"config1\", \"Pre Alarm\");\n\t\t\tbinarySwitch(\"setPreAlarm\", \"config2\", \"Set Pre Alarm\");\n\t\t\tbinarySwitch(\"setAlarm\", \"config3\", \"Set Alarm\");\n\t\t\tbinarySwitch(\"setPIRSensitivity\", \"config4\", \"Set PIR Sensitivity\", function(val) { return (val === 2) ? \"off\" : \"on\"; }, function(command) { return (command === \"off\") ? 2 : 1; });\n\t\t}\n\t\t\n\t\tif (matchDevice(0xd2, 0x06, 0xff)) {\n\t\t\t// Door // TODO(Rehau Smart Guard XT development sample - to be removed after Aug 2021)\n\t\t\tbinarySensor(\"windowOpen\", \"door\", \"Door Sensor\");\n\t\t\tbinarySensor(\"windowTilt\", \"window_tilt\", \"Tilt Sensor\");\n\t\t\tbinarySensor(\"preAlarm\", \"motion\", \"Pre Alarm\");\n\t\t\tbinarySensor(\"alarm\", \"alarm\", \"Alarm\");\n\t\t\tbinarySensor(\"preAlarmEnabled\", \"config1\", \"Pre Alarm\");\n\t\t\tbinarySwitch(\"setPreAlarm\", \"config2\", \"Set Pre Alarm\");\n\t\t\tbinarySwitch(\"setAlarm\", \"config3\", \"Set Alarm\");\n\t\t}\n\t\t\n\t\t// save ZDDX\n\t\tself.zeno.devices.SaveData();\n\t\t\n\t\t// handling of Signal Telegrams\n\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, null, function(type) {\n\t\t\tif (self.zeno.devices[nodeId] && self.zeno.devices[nodeId].data[\"battery\"] && !self.controller.devices.get(vDevIdPrefix + \"battery\")) {\n\t\t\t\tmultilevelSensor(\"battery\", \"battery\", '%', \"Battery level\");\n\t\t\t\tself.zeno.devices.SaveData(); // save ZDDX\n\t\t\t}\n\t\t}, \"value\");\n\t} catch (e) {\n\t\tvar langFile = this.loadModuleLang(),\n\t\t\tvalues = nodeId + \": \" + e.toString();\n\t\t\t\n\t\tthis.addNotification(\"error\", langFile.err_dev_create + values, \"core\");\n\t\tconsole.log(e.stack);\n\t}\n};\n\n// Enocean Generic Profile (GP)\nEnOcean.prototype.parseGenericProfile = function (nodeId) {\n\tvar self = this,\n\t\tdeviceData = this.zeno.devices[nodeId].data,\n\t\tvDevIdPrefix = \"ZEnoVDev_\" + this.config.name + \"_\" + nodeId + \"_\";\n\t\t// vDev is not in this scope, but in {} scope for each type of device to allow reuse it without closures\n\n\ttry {\n\t\tif (deviceData.rorg.value != 0xb0) return;\n\t\t\n\t\tfunction binarySensorGP(o, type, title) {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + type + \"_\" + o)) return;\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + type + \"_\" + o,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\tprobeTitle: type,\n\t\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\t\ticon: type,\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ttitle: title\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, \"channels.\" + o + \".level\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\t\n\t\tfunction binarySwitchGP(o, i, type, title) {\n\t\t\tif (self.controller.devices.get(vDevIdPrefix + type + \"_\" + o + \"_\" + i)) return;\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevIdPrefix + type + \"_\" + o + \"_\" + i,\n\t\t\t\tdefaults: {\n\t\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\t\ttechnology: \"EnOcean\",\n\t\t\t\t\tbindingName: self.config.name,\n\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'switch',\n\t\t\t\t\t\tlevel: '',\n\t\t\t\t\t\ttitle: title\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"on\" || command === \"off\") {\n\t\t\t\t\t\tself.zeno.devices[nodeId].data.channels[i].level.value = command === \"on\" ? true : false;\n\t\t\t\t\t\t// check if it reports back // vDev.set(\"metrics:level\", command);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zeno, nodeId, \"channels.\" + o + \".level\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\n\t\tif (deviceData.manufacturerId.value == 0x02d && deviceData.productId.value == 0x08) {\n\t\t\t// Afriso siren\n\t\t\tbinarySwitchGP(\"o1\", \"i1\", \"switch\", \"Siren\");\n\t\t\tbinarySwitchGP(\"o2\", \"i2\", \"switch\", \"Arm Status\");\n\t\t\tbinarySensorGP(\"o3\", \"alarm\", \"Power status\");\n\t\t}\n\t\t\n\t\t// save ZDDX\n\t\tself.zeno.devices.SaveData();\n\t} catch (e) {\n\t\tvar langFile = this.loadModuleLang(),\n\t\t\tvalues = nodeId + \": \" + e.toString();\n\t\t\t\n\t\tthis.addNotification(\"error\", langFile.err_dev_create + values, \"core\");\n\t\tconsole.log(e.stack);\n\t}\n};\n"
  },
  {
    "path": "modules/EnOcean/lang/de.json",
    "content": "{\n\t\"m_title\":\"EnOcean Netzwerksteuerung\",\n\t\"m_descr\":\"Ermöglicht die Nutzung von EnOcean Geräten, die mit dem Gateway verbunden sind\",\n\t\"l_port\":\"Serieller Port der verwendet werden soll:\",\n\t\"l_name\":\"Interner Name\",\n\t\"h_name\":\"Dies sollte ein valider JS key String sein. Achtung! Nur ändern, wenn Sie wissen was Sie tun.\",\n\t\"rl_enableAPI\":\"Enable EnOcean API\",\n\t\"h_enableAPI\":\"Handler HTTP requests to /EnOceanAPI/* and /EnOcean/<internal zway name>/*\",\n\t\"rl_publicAPI\":\"Allow public access to EnOcean API\",\n\t\"h_publicAPI\":\"Do not ask for authentication to access EnOcean API\",\n\t\"rl_createVDev\":\"Create virtual devices in Home Automation engine\",\n\t\"h_createVDev\":\"Without this EnOcean devices will be visible only in Expert UI and via EnOcean API\",\n\t\"l_config\":\"Pfad zum Ordner /config\",\n\t\"h_change_sth\":\"Achtung! Nur ändern, wenn Sie wissen was Sie tun.\",\n\t\"err_binding_start\":\"Fehler beim Starten der EnOcean Bindung: \",\n\t\"err_dev_create\":\"vDev konnte mit den folgenden Daten nicht erstellt werden: \"\n}"
  },
  {
    "path": "modules/EnOcean/lang/en.json",
    "content": "{\n\t\"m_title\":\"EnOcean Network Access\",\n\t\"m_descr\":\"Allows accessing EnOcean devices from attached EnOcean transceiver.\",\n\t\"l_port\":\"Serial port to EnOcean dongle\",\n\t\"l_name\":\"Internal name\",\n\t\"h_name\":\"Should be a valid JS key string. Don't change unless you know what you are doing\",\n\t\"rl_enableAPI\":\"Enable EnOcean API\",\n\t\"h_enableAPI\":\"Handler HTTP requests to /EnOcean/* and /EnOcean/<internal zway name>/*\",\n\t\"rl_publicAPI\":\"Allow public access to EnOcean API\",\n\t\"h_publicAPI\":\"Do not ask for authentication to access EnOcean API\",\n\t\"rl_createVDev\":\"Create virtual devices in Home Automation engine\",\n\t\"h_createVDev\":\"Without this EnOcean devices will be visible only in Expert UI and via EnOcean API\",\n\t\"l_config\":\"Path to config folder\",\n\t\"h_change_sth\":\"Don't change unless you know what you are doing\",\n\t\"err_binding_start\":\"Cannot start EnOcean binding: \",\n\t\"err_dev_create\":\"Cannot create vDev based on: \"\n}"
  },
  {
    "path": "modules/EnOcean/lang/ru.json",
    "content": "{\n\t\"m_title\":\"EnOcean движок\",\n\t\"m_descr\":\"Активация EnOcean движка.\",\n\t\"l_port\":\"Порт для EnOcean платы/стика\",\n\t\"l_name\":\"Внутреннее имя\",\n\t\"h_name\":\"Должно быть допустимой JS строкой. Не изменяйте, если не знаете, что делаете\",\n\t\"rl_enableAPI\":\"Включить EnOcean API\",\n\t\"h_enableAPI\":\"Обрабатывать HTTP запросы /EnOceanAPI/* и /EnOcean/<внутреннее имя zway>/*\",\n\t\"rl_publicAPI\":\"Разрешить доступ к EnOcean API без аутентификации\",\n\t\"h_publicAPI\":\"Не требовать аутентификации при обработке запросов к EnOcean API\",\n\t\"rl_createVDev\":\"Создавать виртуальные устройства домашней автоматизации\",\n\t\"h_createVDev\":\"Если отключить, то EnOcean устройства будут видны только в Экспертном интерфейсе и через EnOcean API\",\n\t\"l_config\":\"Путь к папке с настройками config/\",\n\t\"h_change_sth\":\"Не изменяйте, если не знаете, что делаете\",\n\t\"err_binding_start\":\"Невозможно запустить EnOcean движок: \",\n\t\"err_dev_create\":\"Не возможно создать vDev основанное на: \"\n}"
  },
  {
    "path": "modules/EnOcean/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"peripherals\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.svg\",\n\t\"moduleName\":\"EnOcean\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"name\": \"zeno\",\n\t\t\"port\": \"/dev/ttyUSB0\",\n\t\t\"enableAPI\": true,\n\t\t\"publicAPI\": false,\n\t\t\"createVDev\": true,\n\t\t\"config\": \"config\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"port\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"port\": {\n\t\t\t\t\"label\": \"__l_port__\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"label\": \"__l_name__\",\n\t\t\t\t\"helper\": \"__h_name__\"\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_enableAPI__\",\n\t\t\t\t\"helper\": \"__h_enableAPI__\"\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_publicAPI__\",\n\t\t\t\t\"helper\": \"__h_publicAPI__\"\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_createVDev__\",\n\t\t\t\t\"helper\": \"__h_createVDev__\"\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_config__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/FosCam9805/index.js",
    "content": "/*** FosCam9805 Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of FosCam9805\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction FosCam9805 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tFosCam9805.super_.call(this, id, controller);\n}\n\ninherits(FosCam9805, AutomationModule);\n\n_module = FosCam9805;\n\n// ----------------------------------------------------------------------------\n// --- Module insFosCam98059828tance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(FosCam9805.prototype, {\n\tinit: function (config) {\n\t\tFosCam9805.super_.prototype.init.call(this, config);\n\t\tvar self=this;\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tthis.proxy_url \t= \"/\" + vDevId + \"/stream\";\n\t\tvar authent\t\t= \"&usr=\" + config.user  + \"&pwd=\" + config.password;\n\t\tthis.cgi \t\t= \"/cgi-bin/CGIProxy.fcgi?cmd=\";\n\t\t\n\t\tvar urlzoomin\t= config.url + this.cgi + \"zoomIn\" + authent;\n\t\tvar urlzoomout\t= config.url + this.cgi + \"zoomOut\" + authent;\n\t\tvar urlzoomstop\t= config.url + this.cgi + \"zoomStop\" + authent;\n\t\t\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\t\n\t\tthis.setup\t= config.url+ \"/cgi-bin/CGIProxy.fcgi?cmd=setSubStreamFormat&format=1\" + authent;\n\t\t\n\t\tif (this.setup) {\n\t\t\thttp.request({\n\t\t\t\turl: this.setup,\n\t\t\t\tasync: true\n\t\t\t});\n\t\t}\n\n\t\tthis.url\t= config.url + \"/cgi-bin/CGIStream.cgi?cmd=GetMJStream\" + authent;\t\t\n\t\tws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t\thasZoomIn: !!urlzoomin,\n\t\t\t\t\thasZoomOut: !!urlzoomout,\n\t\t\t\t\thasClose: !!urlzoomstop || (config.doorDevices && config.doorDevices.length)\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\t\t\t\t\n\t\t\t\tif (command == \"zoomIn\") {\n\t\t\t\t\turl = urlzoomin;\n\t\t\t\t} else if (command == \"zoomOut\") {\n\t\t\t\t\turl = urlzoomout;\n\t\t\t\t} else if (command == \"open\") {\n\t\t\t\t\turl = urlopen;\n\t\t\t\t\topener(command);\n\t\t\t\t} else if (command == \"close\") {\n\t\t\t\t\turl = urlzoomstop;\n\n //\t\t\t\t   opener(command);\n\t\t\t\t}\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tFosCam9805.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/FosCam9805/lang/de.json",
    "content": "{\n\t\"m_descr\":\"Ünterstützung der FosCam Outdoor Kameras (FI9805W,FI8905W,FI9805E)\",\n\t\"ip\":\"Kamera IP-Adresse\",\n\t\"h_ip\":\"Beispielformat: 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Benutzername\",\n\t\"h_user\":\"Sie benötigen den Benutzernamen, den Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"Sie benötigen das Password, das Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"door_dev\":\"Türsensor\"\n}"
  },
  {
    "path": "modules/FosCam9805/lang/en.json",
    "content": "{\n\t\"m_descr\":\"Support the FosCam Outdoor Cameras (FI9805W,FI8905W,FI9805E)\",\n\t\"ip\":\"Camera IP URL\",\n\t\"h_ip\":\"in the format 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Username\",\n\t\"h_user\":\"This is the username that was set up during camera configuration\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"This is the password that was set up during camera configuration\",\n\t\"door_dev\":\"Door device\"\n}"
  },
  {
    "path": "modules/FosCam9805/lang/ru.json",
    "content": "{\n\t\"m_descr\":\"Поддержка Уличных Камер FosCam (FI9805W,FI8905W,FI9805E).\",\n\t\"ip\":\"URL Камеры\",\n\t\"h_ip\":\"В формате 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Имя пользователя\",\n\t\"h_user\":\"Имя пользователя, которое установлено в настройках камеры\",\n\t\"pw\":\"Пароль\",\n\t\"h_pw\":\"Пароль, который установлен в настройках камеры\",\n\t\"door_dev\":\"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/FosCam9805/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.foscam.com/\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"FosCam9805\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"FosCam FI9805\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\t\t\t\t\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"label\": \"__user__\",\n\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__pw__\",\n\t\t\t\t\"helper\": \"__h_pw__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/FosCam9821/index.js",
    "content": "/*** FosCam9821 Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of FosCam9821\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction FosCam9821 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tFosCam9821.super_.call(this, id, controller);\n}\n\ninherits(FosCam9821, AutomationModule);\n\n_module = FosCam9821;\n\n// ----------------------------------------------------------------------------\n// --- Module insFosCam98219828tance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(FosCam9821.prototype, {\n\tinit: function (config) {\n\t\tFosCam9821.super_.prototype.init.call(this, config);\n\t\tvar self=this;\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tthis.proxy_url \t= \"/\" + vDevId + \"/stream\";\n\t\tvar authent\t\t= \"&usr=\" + config.user  + \"&pwd=\" + config.password;\n\t\tthis.cgi \t\t= \"/cgi-bin/CGIProxy.fcgi?cmd=\";\n\t\t\n\t   \tvar urlup\t\t= config.url + this.cgi + \"ptzMoveUp\" + authent;\n\t\tvar urldown\t\t= config.url + this.cgi + \"ptzMoveDown\" + authent;\n\t\tvar urlleft\t\t= config.url + this.cgi + \"ptzMoveLeft\" + authent;\n\t\tvar urlright\t= config.url + this.cgi + \"ptzMoveRight\" + authent;\n\t\tvar urlstop\t\t= config.url + this.cgi + \"ptzStopRun\" + authent; \n\t\t\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\t\n\t\tthis.setup \t= config.url+ \"/cgi-bin/CGIProxy.fcgi?cmd=setSubStreamFormat&format=1\" + authent;\n\n\t\tif (this.setup) {\n\t\t\thttp.request({\n\t\t\t\turl: this.setup,\n\t\t\t\tasync: true\n\t\t\t});\n\t\t}\n\n\t\tthis.url\t= config.url + \"/cgi-bin/CGIStream.cgi?cmd=GetMJStream\" + authent;\t\t\n\t\tws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t\thasLeft: !!urlleft,\n\t\t\t\t\thasRight: !!urlright,\n\t\t\t\t\thasUp: !!urlup,\n\t\t\t\t\thasDown: !!urldown,\n\t\t\t\t\thasClose: !!urlstop || (config.doorDevices && config.doorDevices.length)\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\t\t\t\tconsole.log(urlstop);  \n\t\t\t\tif (command == \"left\") {\n\t\t\t\t\turl = urlleft;\n\t\t\t\t} else if (command == \"right\") {\n\t\t\t\t\turl = urlright\n\t\t\t\t} else if (command == \"up\") {\n\t\t\t\t\turl = urlup;\n\t\t\t\t} else if (command == \"down\") {\n\t\t\t\t\turl = urldown;\n\t\t\t\t} else if (command == \"open\") {\n\t\t\t\t\turl = urlopen;\n\t\t\t\t\topener(command);\n\t\t\t\t} else if (command == \"close\") {\n\t\t\t\t\turl = urlstop;\n\n //\t\t\t\t   opener(command);\n\t\t\t\t}\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tFosCam9821.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/FosCam9821/lang/de.json",
    "content": "{\n\t\"m_descr\":\"Ünterstützung der FosCam Indoor Kameras ohne Zoom (FI9821, FI9831, FI8910)\",\n\t\"ip\":\"Kamera IP-Adresse\",\n\t\"h_ip\":\"Beispielformat: 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Benutzername\",\n\t\"h_user\":\"Sie benötigen den Benutzernamen, den Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"Sie benötigen das Password, das Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"door_dev\":\"Türsensor\"\n}"
  },
  {
    "path": "modules/FosCam9821/lang/en.json",
    "content": "{\n\t\"m_descr\":\"Support the FosCam Indoor Cameras without Zoom (FI9821, FI9831, FI8910)\",\n\t\"ip\":\"Camera IP URL\",\n\t\"h_ip\":\"in the format 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Username\",\n\t\"h_user\":\"This is the username that was set up during camera configuration\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"This is the password that was set up during camera configuration\",\n\t\"door_dev\":\"Door device\"\n}"
  },
  {
    "path": "modules/FosCam9821/lang/ru.json",
    "content": "{\n\t\"m_descr\":\"Поддержка Камер FosCam без зума (FI9821, FI9831, FI8910).\",\n\t\"ip\":\"URL Камеры\",\n\t\"h_ip\":\"В формате 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Имя пользователя\",\n\t\"h_user\":\"Имя пользователя, которое установлено в настройках камеры\",\n\t\"pw\":\"Пароль\",\n\t\"h_pw\":\"Пароль, который установлен в настройках камеры\",\n\t\"door_dev\":\"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/FosCam9821/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.foscam.com/\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"FosCam9821\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"FosCam FI9821\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\t\t\t\t\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"label\": \"__user__\",\n\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__pw__\",\n\t\t\t\t\"helper\": \"__h_pw__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/FosCam9826/index.js",
    "content": "/*** FosCam9826 Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of FosCam9826\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction FosCam9826 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tFosCam9826.super_.call(this, id, controller);\n}\n\ninherits(FosCam9826, AutomationModule);\n\n_module = FosCam9826;\n\n// ----------------------------------------------------------------------------\n// --- Module insFosCam98269828tance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(FosCam9826.prototype, {\n\tinit: function (config) {\n\t\tFosCam9826.super_.prototype.init.call(this, config);\n\t\tvar self=this;\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tthis.proxy_url \t= \"/\" + vDevId + \"/stream\";\n\t\tvar authent\t\t= \"&usr=\" + config.user  + \"&pwd=\" + config.password;\n\t\tthis.cgi \t\t= \"/cgi-bin/CGIProxy.fcgi?cmd=\";\n\t\t\n\t   \tvar urlup\t\t= config.url + this.cgi + \"ptzMoveUp\" + authent;\n\t\tvar urldown\t\t= config.url + this.cgi + \"ptzMoveDown\" + authent;\n\t\tvar urlleft\t\t= config.url + this.cgi + \"ptzMoveLeft\" + authent;\n\t\tvar urlright\t= config.url + this.cgi + \"ptzMoveRight\" + authent;\n\t\tvar urlstop\t\t= config.url + this.cgi + \"ptzStopRun\" + authent; \n\t\tvar urlzoomin\t= config.url + this.cgi + \"zoomIn\" + authent;\n\t\tvar urlzoomout\t= config.url + this.cgi + \"zoomOut\" + authent;\n\t\tvar urlzoomstop\t= config.url + this.cgi + \"zoomStop\" + authent;\n\t\t\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\t\n\t\tthis.setup \t= config.url+ \"/cgi-bin/CGIProxy.fcgi?cmd=setSubStreamFormat&format=1\" + authent;\n\n\t\tif (this.setup) {\n\t\t\thttp.request({\n\t\t\t\turl: this.setup,\n\t\t\t\tasync: true\n\t\t\t});\n\t\t}\n\n\t\tthis.url\t= config.url + \"/cgi-bin/CGIStream.cgi?cmd=GetMJStream\" + authent;\t\t\n\t\tws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t\thasZoomIn: !!urlzoomin,\n\t\t\t\t\thasZoomOut: !!urlzoomout,\n\t\t\t\t\thasLeft: !!urlleft,\n\t\t\t\t\thasRight: !!urlright,\n\t\t\t\t\thasUp: !!urlup,\n\t\t\t\t\thasDown: !!urldown,\n\t\t\t\t\thasClose: !!urlstop || (config.doorDevices && config.doorDevices.length)\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\t\t\t\tconsole.log(urlstop);  \n\t\t\t\tif (command == \"zoomIn\") {\n\t\t\t\t\turl = urlzoomin;\n\t\t\t\t} else if (command == \"zoomOut\") {\n\t\t\t\t\turl = urlzoomout;\n\t\t\t\t} else if (command == \"left\") {\n\t\t\t\t\turl = urlleft;\n\t\t\t\t} else if (command == \"right\") {\n\t\t\t\t\turl = urlright\n\t\t\t\t} else if (command == \"up\") {\n\t\t\t\t\turl = urlup;\n\t\t\t\t} else if (command == \"down\") {\n\t\t\t\t\turl = urldown;\n\t\t\t\t} else if (command == \"open\") {\n\t\t\t\t\turl = urlopen;\n\t\t\t\t\topener(command);\n\t\t\t\t} else if (command == \"close\") {\n\t\t\t\t\turl = urlstop;\n\t\t\t\t\turl = urlzoomstop;\n\n //\t\t\t\t   opener(command);\n\t\t\t\t}\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tFosCam9826.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/FosCam9826/lang/de.json",
    "content": "{\n\t\"m_descr\":\"Ünterstützung der Indoor Zoom Kameras (FI9826W)\",\n\t\"ip\":\"Kamera IP-Adresse\",\n\t\"h_ip\":\"Beispielformat: 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Benutzername\",\n\t\"h_user\":\"Sie benötigen den Benutzernamen, den Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"Sie benötigen das Password, das Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"door_dev\":\"Türsensor\"\n}"
  },
  {
    "path": "modules/FosCam9826/lang/en.json",
    "content": "{\n\t\"m_descr\":\"Support the FosCam Indoor Zoom Cameras (FI9826W)\",\n\t\"ip\":\"Camera IP URL\",\n\t\"h_ip\":\"in the format 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Username\",\n\t\"h_user\":\"This is the username that was set up during camera configuration\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"This is the password that was set up during camera configuration\",\n\t\"door_dev\":\"Door device\"\n}"
  },
  {
    "path": "modules/FosCam9826/lang/ru.json",
    "content": "{\n\t\"m_descr\":\"Поддержка Камер FosCam с зумом (FI9826W).\",\n\t\"ip\":\"URL Камеры\",\n\t\"h_ip\":\"В формате 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Имя пользователя\",\n\t\"h_user\":\"Имя пользователя, которое установлено в настройках камеры\",\n\t\"pw\":\"Пароль\",\n\t\"h_pw\":\"Пароль, который установлен в настройках камеры\",\n\t\"door_dev\":\"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/FosCam9826/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.foscam.com/\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"FosCam9826\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"FosCam FI9826\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\t\t\t\t\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"label\": \"__user__\",\n\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__pw__\",\n\t\t\t\t\"helper\": \"__h_pw__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/FosCam9828/index.js",
    "content": "/*** FosCam9828 Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of FosCam9828\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction FosCam9828 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tFosCam9828.super_.call(this, id, controller);\n}\n\ninherits(FosCam9828, AutomationModule);\n\n_module = FosCam9828;\n\n// ----------------------------------------------------------------------------\n// --- Module insFosCam98289828tance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(FosCam9828.prototype, {\n\tinit: function (config) {\n\t\tFosCam9828.super_.prototype.init.call(this, config);\n\t\tvar self=this;\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tthis.proxy_url \t= \"/\" + vDevId + \"/stream\";\n\t\tvar authent\t\t= \"&usr=\" + config.user  + \"&pwd=\" + config.password;\n\t\tthis.cgi \t\t= \"/cgi-bin/CGIProxy.fcgi?cmd=\";\n\t\t\n\t   \tvar urlup\t\t= config.url + this.cgi + \"ptzMoveUp\" + authent;\n\t\tvar urldown\t\t= config.url + this.cgi + \"ptzMoveDown\" + authent;\n\t\tvar urlleft\t\t= config.url + this.cgi + \"ptzMoveLeft\" + authent;\n\t\tvar urlright\t= config.url + this.cgi + \"ptzMoveRight\" + authent;\n\t\tvar urlstop\t\t= config.url + this.cgi + \"ptzStopRun\" + authent; \n\t\tvar urlzoomin\t= config.url + this.cgi + \"zoomIn\" + authent;\n\t\tvar urlzoomout\t= config.url + this.cgi + \"zoomOut\" + authent;\n\t\tvar urlzoomstop\t= config.url + this.cgi + \"zoomStop\" + authent;\n\t\t\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\t\n\t\tthis.setup \t= config.url+ \"/cgi-bin/CGIProxy.fcgi?cmd=setSubStreamFormat&format=1\" + authent;\n\n\t\tif (this.setup) {\n\t\t\thttp.request({\n\t\t\t\turl: this.setup,\n\t\t\t\tasync: true\n\t\t\t});\n\t\t}\n\t\t\t\n\t\tthis.url\t= config.url + \"/cgi-bin/CGIStream.cgi?cmd=GetMJStream\" + authent;\t\t\n\t\tws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t\thasZoomIn: !!urlzoomin,\n\t\t\t\t\thasZoomOut: !!urlzoomout,\n\t\t\t\t\thasLeft: !!urlleft,\n\t\t\t\t\thasRight: !!urlright,\n\t\t\t\t\thasUp: !!urlup,\n\t\t\t\t\thasDown: !!urldown,\n\t\t\t\t\thasClose: !!urlstop || (config.doorDevices && config.doorDevices.length)\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\t\t\t\tconsole.log(urlstop);  \n\t\t\t\tif (command == \"zoomIn\") {\n\t\t\t\t\turl = urlzoomin;\n\t\t\t\t} else if (command == \"zoomOut\") {\n\t\t\t\t\turl = urlzoomout;\n\t\t\t\t} else if (command == \"left\") {\n\t\t\t\t\turl = urlleft;\n\t\t\t\t} else if (command == \"right\") {\n\t\t\t\t\turl = urlright\n\t\t\t\t} else if (command == \"up\") {\n\t\t\t\t\turl = urlup;\n\t\t\t\t} else if (command == \"down\") {\n\t\t\t\t\turl = urldown;\n\t\t\t\t} else if (command == \"open\") {\n\t\t\t\t\turl = urlopen;\n\t\t\t\t\topener(command);\n\t\t\t\t} else if (command == \"close\") {\n\t\t\t\t\turl = urlstop;\n\t\t\t\t\turl = urlzoomstop;\n\n //\t\t\t\t   opener(command);\n\t\t\t\t}\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tFosCam9828.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/FosCam9828/lang/de.json",
    "content": "{\n\t\"m_descr\":\"Ünterstützung der FosCam Dome Outdoor Kameras (FI9828, FI9819)\",\n\t\"ip\":\"Kamera IP-Adresse\",\n\t\"h_ip\":\"Beispielformat: 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Benutzername\",\n\t\"h_user\":\"Sie benötigen den Benutzernamen, den Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"Sie benötigen das Password, das Sie in der Kamerakonfiguration angegeben haben.\",\n\t\"door_dev\":\"Türsensor\"\n}"
  },
  {
    "path": "modules/FosCam9828/lang/en.json",
    "content": "{\n\t\"m_descr\":\"Support the FosCam dome Outdoor Cameras (FI9828, FI9819)\",\n\t\"ip\":\"Camera IP URL\",\n\t\"h_ip\":\"in the format 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Username\",\n\t\"h_user\":\"This is the username that was set up during camera configuration\",\n\t\"pw\":\"Password\",\n\t\"h_pw\":\"This is the password that was set up during camera configuration\",\n\t\"door_dev\":\"Door device\"\n}"
  },
  {
    "path": "modules/FosCam9828/lang/ru.json",
    "content": "{\n\t\"m_descr\":\"Поддержка Уличных Камер FosCam (FI9828, FI9819).\",\n\t\"ip\":\"URL Камеры\",\n\t\"h_ip\":\"В формате 'http://IPADDRESS:PORT'\",\n\t\"user\":\"Имя пользователя\",\n\t\"h_user\":\"Имя пользователя, которое установлено в настройках камеры\",\n\t\"pw\":\"Пароль\",\n\t\"h_pw\":\"Пароль, который установлен в настройках камеры\",\n\t\"door_dev\":\"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/FosCam9828/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.foscam.com/\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"FosCam9828\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"FosCam FI9828\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\t\t\t\t\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"label\": \"__user__\",\n\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__pw__\",\n\t\t\t\t\"helper\": \"__h_pw__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/GlobalCache/index.js",
    "content": "/*** GlobalCache Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tImplements Global Cache support\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction GlobalCache (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tGlobalCache.super_.call(this, id, controller);\n}\n\ninherits(GlobalCache, AutomationModule);\n\n_module = GlobalCache;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nGlobalCache.prototype.init = function (config) {\n\tGlobalCache.super_.prototype.init.call(this, config);\n\n\tvar self = this;\t\t\n \n\tvar vDev = self.controller.devices.create({\n\t\tdeviceId: \"GlobalCache_Device_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"toggleButton\",\n\t\t\tmetrics: {\n\t\t\t\ttitle: 'Global Cache ' + this.id,\n\t\t\t\ticon: \"\"\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\ttry {\n\t\t\t\tvar sock = new sockets.tcp();\n\t\t\t\tsock.connect(self.config.host, 4998);\n\t\t\t\tsock.send(self.config.data + \"\\r\\n\\r\\n\");\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(\"Failed to send data to GlobalCache: \" + e.toString() + \" (IP: \" + self.config.host + \", data: \\\"\" + self.config.data + \"\\\")\");\n\t\t\t} finally {\n\t\t\t\tsock.close();\n\t\t\t}\n\t\t\t\n\t\t\tself.vDev.set(\"metrics:level\", \"on\"); // update on ourself to allow catch this event\n\t\t},\n\t\tmoduleId: this.id\n\t});\n};\n\nGlobalCache.prototype.stop = function () {\n\tthis.controller.devices.remove(\"GlobalCache_Device_\" + this.id);\n\t\n\tGlobalCache.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/GlobalCache/lang/de.json",
    "content": "{\n\t\"m_title\":\"Global Caché\",\n\t\"m_descr\":\"Global Cache ist ein Hersteller verschiedener Geräte, die per IP Befehl an- bzw. ausgeschalten werden können. Diese App erstellt ein neues Element und verbindet dessen Schaltfläche mit einem bestimmten Befehl, der an ein Global Cache Gerät gesendet wird. <br><br>Einstellungen:<br><ul><li>IP Adresse oder Hostname des Global Cache Gerätes</li><li>Befehls-String zur Ausführung der gewünschten Aktion am Global Cache Gerät. Informationen zur Befehlsbestimmung entnehmen Sie bitte den Global Cache Anleitungen.</li></ul>\",\n\t\"l_host\":\"Global Caché IP or hostname\",\n\t\"l_data\":\"Command to send\",\n\t\"h_data\":\"Command as reported by Global Caché IR Learning Utility WITHOUT final new line symbols (&#92;r&#92;n&#92;r&#92;n).\"\n}"
  },
  {
    "path": "modules/GlobalCache/lang/en.json",
    "content": "{\n\t\"m_title\":\"Global Caché\",\n\t\"m_descr\":\"Global Cache is a manufacturer of various devices that can be turned on/off using an IP command.   This app will create a new element and connect the toggle button of this element with a defined command sent to a Global Cache device.<br><br>Settings:<br><ul><li>IP Address or host name of the Global Cache device</li><li>Command String to execute the desired action on the Global Cache device. Please refer to the Global Cache manuals for information how to define this command.</li></ul>\",\n\t\"l_host\":\"Global Caché IP or hostname\",\n\t\"l_data\":\"Command to send\",\n\t\"h_data\":\"Command as reported by Global Caché IR Learning Utility WITHOUT final new line symbols (&#92;r&#92;n&#92;r&#92;n).\"\n}"
  },
  {
    "path": "modules/GlobalCache/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Global Caché\",\n\t\"m_descr\":\"Создать кнопку, отправляющую команду устройству Global Caché.\",\n\t\"l_host\":\"IP или имя хоста \"Global Caché\",\n\t\"l_data\":\"Отправляемая команда\",\n\t\"h_data\":\"Команда, полученная из Global Caché IR Learning Utility БЕЗ символов переноса строки (&#92;r&#92;n&#92;r&#92;n).\"\n}"
  },
  {
    "path": "modules/GlobalCache/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"support_external_dev\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\": \"GlobalCache\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"host\": \"\",\n\t\t\"data\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"host\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"data\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"host\": {\n\t\t\t\t\"label\": \"__l_host__\",\n\t\t\t\t\"placeholder\": \"192.168.0.100 or hostname\"\n\t\t\t},\n\t\t\t\"data\": {\n\t\t\t\t\"label\": \"__l_data__\",\n\t\t\t\t\"placeholder\": \"sendir,1:1,7,35874,1,1,.......,2500\",\n\t\t\t\t\"helper\": \"__h_data__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/GoogleHome/index.js",
    "content": "/*** GoogleHome Z-Way HA module *******************************************\n\n Version: 0.0.2 beta\n (c) Z-Wave.Me, 2019\n -----------------------------------------------------------------------------\n Author: Avaliani Alexander <aam@z-wave.me>\n Description:\n\n ******************************************************************************/\n\nfunction GoogleHome (id, controller) {\n    // Call superconstructor first (AutomationModule)\n    GoogleHome.super_.call(this, id, controller);\n}\n\ninherits(GoogleHome, AutomationModule);\n\n_module = GoogleHome;\n\nGoogleHome.prototype.init = function(config) {\n    var self = this;\n\n    GoogleHome.super_.prototype.init.call(this, config);\n\n    this.HOMEGRAPH_URL = 'https://ghome.z-wave.me:5002/zway/api/v1.0/';\n    this.GOOGLE_PROFILE_NAME = 'https://oauth-redirect.googleusercontent.com';\n    \n    this.deferredVDevCreation = [];\n    this.deferredVDevCreationTimer = null;\n    this.deferredVDevReport = [];\n    this.deferredVDevReportTimer = null;\n\n    this.delayedRequestSyncDevicesHandler = function(dev) {\n      self.delayedRequestSyncDevices(dev);\n    };\n    \n    this.delayedReportStateDevicesHandler = function(dev) {\n      if (!dev.get('permanently_hidden')) {\n        self.delayedReportStateDevices(dev);\n      }\n    };\n    \n    this.requestSyncProfilesHandler = function(profile) {\n      self.requestSyncProfiles(self.getActiveAgentUsers().filter(function(agentUser) {\n        return agentUser.name === profile.login;\n      }).map(function(agentUser) {\n        return agentUser.agentId;\n      }));\n    };\n    \n    this.controller.devices.on('change:metrics:level', this.delayedReportStateDevicesHandler);\n    this.controller.devices.on('change:metrics:title', this.delayedRequestSyncDevicesHandler);\n    this.controller.devices.on('change:location', this.delayedRequestSyncDevicesHandler);\n    this.controller.devices.on('created', this.delayedRequestSyncDevicesHandler);\n    this.controller.on('profile.updated', this.requestSyncProfilesHandler);\n};\n\nGoogleHome.prototype.stop = function() {\n    this.controller.devices.off('change:metrics:level', this.delayedReportStateDevicesHandler);\n    this.controller.devices.off('change:metrics:title', this.delayedRequestSyncDevicesHandler);\n    this.controller.devices.off('change:location', this.delayedRequestSyncDevicesHandler);\n    this.controller.devices.off('created', this.delayedRequestSyncDevicesHandler);\n    this.controller.off('profile.updated', this.requestSyncProfilesHandler);\n\n    GoogleHome.super_.prototype.stop.call(this);\n};\n\nGoogleHome.prototype.delayedReportStateDevices = function(dev) {\n  var self = this;\n  \n  // remove the device from the list if it was already there\n  for (var i = 0; i < this.deferredVDevReport.length; i++) {\n    if (this.deferredVDevReport[i].id === dev.id) {\n      this.deferredVDevReport.splice(i, 1);\n      break;\n    }\n  }\n  \n  this.deferredVDevReport.push(dev);\n  \n  // set a short timer and send after the delay\n  if (!this.deferredVDevReportTimer) {\n    this.deferredVDevReportTimer = setTimeout(function() {\n      self.reportState(self.deferredVDevReport);\n      self.deferredVDevReport = [];\n      self.deferredVDevReportTimer = null;\n    }, 3*1000);\n  }\n};\n\nGoogleHome.prototype.delayedRequestSyncDevices = function(dev) {\n  var self = this;\n  \n  // remove the device from the list if it was already there\n  for (var i = 0; i < this.deferredVDevCreation.length; i++) {\n    if (this.deferredVDevCreation[i].id === dev.id) {\n      this.deferredVDevCreation.splice(i, 1);\n      break;\n    }\n  }\n  \n  this.deferredVDevCreation.push(dev);\n  \n  // restart the timer everty time to collect more data\n  if (this.deferredVDevCreationTimer) {\n    clearTimeout(this.deferredVDevCreationTimer);\n  }\n  \n  this.deferredVDevCreationTimer = setTimeout(function() {\n    self.requestSyncDevices(self.deferredVDevCreation);\n    self.deferredVDevCreation = [];\n    self.deferredVDevCreationTimer = null;\n  }, 10*1000);\n};\n\nGoogleHome.prototype.requestSyncProfiles = function(agentUserIds) {\n  if (agentUserIds.length != 0) {\n    data = JSON.stringify({'agentUserIds': agentUserIds});\n    http.request({\n      method: 'POST',\n      url: this.HOMEGRAPH_URL + 'requestSync',\n      async: true,\n      data: data,\n      headers: {\n        \"Content-Type\": \"application/json\"\n      },\n      success: function(response) {\n        console.log(\"Google Home updated\");\n      },\n      error: function(response) {\n        console.log(\"Google Home update error: \" + response.statusText + \", \" + response.data);\n      }\n    });\n  }\n};\n\nGoogleHome.prototype.requestSyncDevices = function(devices) {\n    var self = this,\n      agentUserIds = [];\n\n    var agentUsers = this.getActiveAgentUsers();\n    \n    devices.forEach(function(dev) {\n      agentUsers.forEach(function(agentUser) {\n        if (agentUserIds.indexOf(agentUser.agentId) === -1 && self.controller.deviceByUser(dev.id, agentUser.id)) {\n          agentUserIds.push(agentUser.agentId);\n        }\n      });\n    });\n\n    this.requestSyncProfiles(agentUserIds);\n}\n\nGoogleHome.prototype.reportState = function(devices) {\n  var self = this,\n      data = [];\n  \n  devices.forEach(function(dev) {\n    // check every profile if its list of devices has changed and make request to server\n    self.getActiveAgentUsers().forEach(function(profile) {\n      if (self.controller.deviceByUser(dev.id, profile.id)) {\n        data.push({\n          agentUserId: profile.agentId,\n          device: dev\n        })\n      }\n    });\n\n    if (data.length != 0) {\n      http.request({\n        method: 'POST',\n        url: self.HOMEGRAPH_URL + 'reportState',\n        async: true,\n        data: JSON.stringify(data),\n        headers: {\n          \"Content-Type\": \"application/json\"\n        },\n        success: function(response) {\n          // not to spam in the log // console.log(\"Google Home updated\");\n        },\n        error: function(response) {\n          console.log(\"Google Home update error: \" + response.statusText + \", \" + response.data + \", \" + JSON.stringify(data));\n        }\n      });\n    }\n  });\n};\n\nGoogleHome.prototype.getActiveAgentUsers = function() {\n  var self = this;\n  \n  // get only active Google OAuth profiles\n  return this.controller.profiles.filter(function(profile) {\n    // TODO: Change this to some special mark of token\n    return profile.login.indexOf(self.GOOGLE_PROFILE_NAME) !== -1;\n  }).map(function(profile) {\n    return {\n      id: profile.id,\n      name: profile.login,\n      agentId: profile.uuid\n    };\n  });\n}\n\n// TODO: API to notify this module that the token has to be marked as Google Home (and the profile too)\n\n// TODO: !!! Check that you can link two times the same profile with two Google accounts and Google will not complain on this (same agentId). In that case change agentID to tokenID\n"
  },
  {
    "path": "modules/GoogleHome/lang/de.json",
    "content": "{\n  \"m_title\":\"Google Home\",\n  \"m_descr\":\"Mit diesem Modul können Sie Ihre Z-Way Geräte über den Google-Assistenten steuern.\"\n}\n"
  },
  {
    "path": "modules/GoogleHome/lang/en.json",
    "content": "{\n  \"m_title\":\"Google Home\",\n  \"m_descr\":\"This module let you control your Z-Way devices through the Google Assistant.\"\n}\n"
  },
  {
    "path": "modules/GoogleHome/module.json",
    "content": "{\n  \"dependencies\": [],\n  \"singleton\": true,\n  \"category\": \"support_external_dev\",\n  \"author\": \"Z-Wave.Me\",\n  \"homepage\": \"http://razberry.z-wave.me\",\n  \"icon\": \"icon.png\",\n  \"moduleName\":\"GoogleHome\",\n  \"version\": \"0.1.0\",\n  \"maturity\": \"beta\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n  },\n  \"defaults\": {\n    \"title\" : \"__m_title__\",\n    \"description\": \"__m_descr__\",\n    \"devices\": []\n  }\n}\n"
  },
  {
    "path": "modules/GroupDevices/index.js",
    "content": "/*** GroupDevices Z-Way HA module *******************************************\n\nVersion: 2.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tGroups several devices together to make a new virtual device\n\nChangelog:\n16.12.2015 (aivs) - Added selector to set how group widget associated with devices in group: 1) not associated, 2) show biggest value, 3) show smaller value\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction GroupDevices (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tGroupDevices.super_.call(this, id, controller);\n}\n\ninherits(GroupDevices, AutomationModule);\n\n_module = GroupDevices;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nGroupDevices.prototype.init = function (config) {\n\tGroupDevices.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\ticon = \"\",\n\tlevel = \"\",\n\tdeviceType = this.config.isDimmable ? \"switchMultilevel\" : \"switchBinary\";\n\n\tswitch(deviceType) {\n\t\tcase \"switchBinary\":\n\t\t\ticon = \"switch\";\n\t\t\tlevel = \"off\";\n\t\t\tbreak;\n\t\tcase \"switchMultilevel\":\n\t\t\ticon = \"multilevel\";\n\t\t\tlevel = 0;\n\t\t\tbreak;\n\t}\n\n\tvar defaults = {\n\t\tmetrics: {\n\t\t\ttitle: self.getInstanceTitle()\n\t\t}\n\t};\n \n\tvar overlay = {\n\t\t\tdeviceType: deviceType,\n\t\t\tmetrics: {\n\t\t\t\ticon: icon,\n\t\t\t\tlevel: level\n\t\t\t}\t  \n\t};\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"GroupDevices_\" + this.id,\n\t\tdefaults: defaults,\n\t\toverlay: overlay,\n\t\thandler: function(command, args) {\n\t\t\tself.config.devices.forEach(function(dev) {\n\t\t\t\tvar vDev = self.controller.devices.get(dev.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (command === \"on\" || command === \"off\" || (command === \"exact\" && vDev.get(\"deviceType\") === \"switchBinary\")) {\n\t\t\t\t\t\tvDev.performCommand((dev.invert ^ (command === \"on\" || (command === \"exact\" && args.level > 0)))? \"on\" : \"off\");\n\t\t\t\t\t} else if (command === \"exact\") {\n\t\t\t\t\t\tvDev.performCommand(\"exact\", { level: dev.invert ? (99-args.level) : args.level });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tif (command === \"on\" || command === \"off\") {\n\t\t\t\tvar scenes = command === \"on\" ? self.config.scenesOn : self.config.scenesOff;\n\n\t\t\t\tscenes.forEach(function(scene) {\n\t\t\t\t\tvar vDev = self.controller.devices.get(scene);\n\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tvar level = command;\n\t\t\tif (self.config.isDimmable) {\n\t\t\t\tif (command === \"on\") {\n\t\t\t\t\tlevel = 99;\n\t\t\t\t} else if (command === \"off\") {\n\t\t\t\t\tlevel = 0;\n\t\t\t\t} else {\n\t\t\t\t\tlevel = args.level;\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.set(\"metrics:level\", level);\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\tthis.handler = function() {\n\t\tvar associationType = self.config.associationType;\n\t\tswitch(associationType) {\n\t\t\tcase \"noAssociation\":\n\t\t\t\t// widget doesn't change\n\t\t\t\tbreak;\n\t\t\tcase \"oneOff-widgetOff\":\n\t\t\t\t// for dimmers show minimal value from group\n\t\t\t\t// for switch show off\n\t\t\t\tvar res = 99; // max value\n\t\t\t\tself.config.devices.forEach(function(xdev) {\n\t\t\t\t\tvar devValue = self.controller.devices.get(xdev.device).get(\"metrics:level\");\n\t\t\t\t\t// check dimmer value\n\t\t\t\t\tif (devValue < res) {\n\t\t\t\t\t\tres = devValue;\n\t\t\t\t\t}\n\t\t\t\t\t// check switch value. If one of all switch turned off, show 0\n\t\t\t\t\tif (devValue === \"off\") {\n\t\t\t\t\t\tres = 0;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (self.config.isDimmable) {\n\t\t\t\t\tself.vDev.set(\"metrics:level\", res);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tself.vDev.set(\"metrics:level\", res > 0 ? \"on\" : \"off\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tbreak;\n\t\t\tcase \"oneOn-widgetOn\":\n\t\t\t\t// for dimmers show maximum value from group\n\t\t\t\t// for switch show on\n\t\t\t\tvar res = 0; // min value\n\t\t\t\tself.config.devices.forEach(function(xdev) {\n\t\t\t\t\tvar devValue = self.controller.devices.get(xdev.device).get(\"metrics:level\");\n\t\t\t\t\t// check dimmer value\n\t\t\t\t\tif (devValue > res) {\n\t\t\t\t\t\tres = devValue;\n\t\t\t\t\t}\n\t\t\t\t\t// check switch value. If all dimmers turned OFF and one of all switches turned on, show 1\n\t\t\t\t\tif (devValue === \"on\" && res === 0) {\n\t\t\t\t\t\tres = 1;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (self.config.isDimmable) {\n\t\t\t\t\tself.vDev.set(\"metrics:level\", res);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tself.vDev.set(\"metrics:level\", res > 0 ? \"on\" : \"off\");\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t};\n\t\n\tthis.config.devices.forEach(function(dev) {\n\t\tthis.controller.devices.on(dev.device, \"change:metrics:level\", self.handler);\n\t});\n\n};\n\nGroupDevices.prototype.stop = function () {\n\tvar self = this;\n\t\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tthis.config.devices.forEach(function(dev) {\n\t\tthis.controller.devices.off(dev.device, \"change:metrics:level\", self.handler);\n\t});\n\n\tGroupDevices.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "modules/GroupDevices/lang/de.json",
    "content": "{\n\t\"m_title\":\"Gerätegruppe\",\n\t\"m_descr\":\"Gruppiert Geräte in einem Element. Das Element kann sowohl ein- und ausgeschalten werden und ist zusätzlich dimmbar. Es können außerdem Szenen aktiviert werden. Diese App ist im Grunde genommen eine andere Art und Weise, um Szenen zu definieren.<br><br>Einstellungen:<br><ul><li><li>Anzuwählen, wenn die Gerätegruppe ein einfacher An-/Ausschalter oder dimmbar sein soll.</li>  <li>Wählen Sie eine Reihe an Geräten als Teil der Gerätegruppe aus. Es ist möglich, die Aktion pro Gerät zu invertieren. Das heißt, dass das Einschalten der Gerätegruppe bedeutet, das Gerät mit einer invertierten Aktion zu schalten.</li><li>Wählen Sie weitere Lichtszenen aus, die Sie auf AN oder AUS aktivieren möchten. Hieran verdeutlicht sich der Vorteil einer Gerätegruppe im Vergleich zu einer Szene. Eine Szene kann nur aktiviert werden. Hat man zwei Szenen ermöglicht diese App zwischen beiden Szenen hin- und her zu schalten.</li></ul>\",\n\t\"rl_options\":\"Dimmbar\",\n\t\"l_devices\":\"Gerätegruppe\",\n\t\"rl_invert\":\"Umgekehrte Aktionen\",\n\t\"l_scenesOn\":\"Liste von Szenen/Aktionen, die beim Auslösen aktiviert werden (On).\",\n\t\"l_scenesOff\":\"Liste von Szenen/Aktionen, die beim Auslösen deaktiviert werden (Off).\",\n\t\"noAssociation\":\"The group value does not depend on the values of the devices in the group\",\n\t\"oneOff-widgetOff\":\"The group value corresponds to the smallest value of the devices in the group\",\n\t\"oneOn-widgetOn\":\"The group value corresponds to the highest value of the devices in the group\"\n}"
  },
  {
    "path": "modules/GroupDevices/lang/en.json",
    "content": "{\n\t\"m_title\":\"Group devices\",\n\t\"m_descr\":\"Groups devices into one element. The element can either be on/off or even dimmable. Scenes can also be activated. This app is essentially a different way to define a scene.<br><br>Settings: <br><ul><li>Select if the group device shall be a simple on/off switch or dimmable. </li><li>Select a list of devices as part of the group. Its possible to invert the action per device. This means that turning the group device on mean to turn of the device with inverted action.</li><li>Select further light scenes you like to activate on ON or OFF. Here you see the large advantage of the group device again a scene. A scene can only be activated. Having two scenes this app allows to toggle the two scenes.<li></ul>\",\n\t\"rl_options\":\"Dimmable\",\n\t\"l_devices\":\"Group devices\",\n\t\"rl_invert\":\"Invert action\",\n\t\"l_scenesOn\":\"List of scenes to activate on On action\",\n\t\"l_scenesOff\":\"List of scenes to activate on Off action\",\n\t\"noAssociation\":\"The group value does not depend on the values of the devices in the group\",\n\t\"oneOff-widgetOff\":\"The group value corresponds to the smallest value of the devices in the group\",\n\t\"oneOn-widgetOn\":\"The group value corresponds to the highest value of the devices in the group\"\n}\n"
  },
  {
    "path": "modules/GroupDevices/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Группа устройств\",\n\t\"m_descr\":\"Объединить несколько устройств в одну группу.\",\n\t\"rl_options\":\"Диммируемая группа устройств\",\n\t\"l_devices\":\"Устройства в группе\",\n\t\"rl_invert\":\"Инвертировать действие\",\n\t\"l_scenesOn\":\"Список сцен запускаемых при Включении группы\",\n\t\"l_scenesOff\":\"Список сцен запускаемых при Выключении группы\",\n\t\"noAssociation\":\"Значение группы не зависит от значения устройств в группе\",\n\t\"oneOff-widgetOff\":\"Значение группы соответствует наименьшему значению устройства в группе\",\n\t\"oneOn-widgetOn\":\"Значение группы соответствует наибольшему значению устройства в группе\"\n}"
  },
  {
    "path": "modules/GroupDevices/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"device_enhancements\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\": \"GroupDevices\",\n\t\"version\": \"2.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"isDimmable\": false,\n\t\t\"associationType\": \"noAssociation\",\n\t\t\"devices\": [],\n\t\t\"scenesOn\": [],\n\t\t\"scenesOff\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"isDimmable\": {\n\t\t\t\t\"type\": \"boolean\"\n\t\t\t},\n\t\t\t\"associationType\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [\"noAssociation\", \"oneOff-widgetOff\", \"oneOn-widgetOn\"]\n\t\t\t},\n\t\t\t\"devices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"invert\": {\n\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scenesOn\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scenesOff\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"isDimmable\": {\n\t\t\t\t\"label\": \"\",\n\t\t\t\t\"rightLabel\": \"__rl_options__\"\n\t\t\t},\n\t\t\t\"associationType\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [\"__noAssociation__\", \"__oneOff-widgetOff__\", \"__oneOn-widgetOn__\"]\n\t\t\t},\n\t\t\t\"devices\": {\n\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"invert\": {\n\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\"rightLabel\": \"__rl_invert__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scenesOn\": {\n\t\t\t\t\"label\": \"__l_scenesOn__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scenesOff\": {\n\t\t\t\t\"label\": \"__l_scenesOff__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/HTTPDevice/index.js",
    "content": "/*** HTTPDevice Z-Way HA module *******************************************\n\nVersion: 2.2.1\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Yurkin Vitaliy <aivs@z-wave.me>\nDescription:\n\tImplements virtual device based on HTTP object\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction HTTPDevice (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tHTTPDevice.super_.call(this, id, controller);\n}\n\ninherits(HTTPDevice, AutomationModule);\n\n_module = HTTPDevice;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nHTTPDevice.prototype.init = function (config) {\n\tHTTPDevice.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\ticon = \"\",\n\t\tlevel = \"\",\n\t\tscaleTitle = \"\",\n\t\tdeviceType = this.config.deviceType;\n\t\tprobeType = \"\"\n\t\t\n\tswitch(deviceType) {\n\t\tcase \"sensorBinary\":\n\t\t\ticon = this.config.iconSensorBinary;\n\t\t\tprobeType = this.config.iconSensorBinary == \"door\" ? \"door-window\" : this.config.iconSensorBinary;\n\t\t\tlevel = \"off\";\n\t\t\tbreak;\n\t\tcase \"sensorMultilevel\":\n\t\t\ticon = this.config.iconSensorMultilevel;\n\t\t\tprobeType = this.config.iconSensorMultilevel;\n\t\t\tscaleTitle = this.config.scale_sensorMultilevel;\n\t\t\tlevel = 0;\n\t\t\tbreak;\n\t\tcase \"switchBinary\":\n\t\t\ticon = \"switch\";\n\t\t\tlevel = \"off\";\n\t\t\tbreak;\n\t\tcase \"switchMultilevel\":\n\t\t\ticon = \"multilevel\";\n\t\t\tlevel = 0;\n\t\t\tbreak;\n\t\tcase \"toggleButton\":\n\t\t\ticon = \"gesture\";\n\t\t\tlevel = \"on\";\n\t\t\tbreak;\n\t}\n\t\n\tvar defaults = {\n\t\tmetrics: {\n\t\t\ttitle: self.getInstanceTitle()\n\t\t}\n\t};\n \n\tvar overlay = {\n\t\t\tdeviceType: deviceType,\n\t\t\tprobeType: probeType,\n\t\t\tmetrics: {\n\t\t\t\ticon: icon,\n\t\t\t\tlevel: level,\n\t\t\t\tscaleTitle: scaleTitle\n\t\t\t}\t  \n\t};\n\n\tvar vDev = self.controller.devices.create({\n\t\tdeviceId: \"HTTP_Device_\" + deviceType + \"_\" + this.id,\n\t\tdefaults: defaults,\n\t\toverlay: overlay,\n\t\thandler: function (command, args) {\n\t\t\tvar vDevType = deviceType;\n\n\t\t\tif (command === \"update\" && (vDevType === \"sensorBinary\" || vDevType === \"sensorMultilevel\" || vDevType === \"switchBinary\" || vDevType === \"switchMultilevel\")) {\n\t\t\t\tself.update(this);\n\t\t\t}\n\n\t\t\tif (command === \"on\" && (vDevType === \"toggleButton\" || vDevType === \"switchBinary\")) {\n\t\t\t\tself.act(this, \"On\", null, (vDevType === \"switchBinary\" ? \"on\" : null));\n\t\t\t}\n\n\n\t\t\tif (command === \"off\" && vDevType === \"switchBinary\") {\n\t\t\t\tself.act(this, \"Off\", null, \"off\");\n\t\t\t}\n\n\t\t\tif ((command === \"off\" || command === \"on\" || command === \"exact\") && vDevType === \"switchMultilevel\") {\n\t\t\t\tvar level = command === \"exact\" ? parseInt(args.level, 10) : (command === \"on\" ? 99 : 0);\n\t\t\t\tself.act(this, \"Level\", level, level);\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\tif (vDev && this.config[\"getter_\" + deviceType] && this.config[\"getterPollInterval_\" + deviceType]) {\n\t\tthis.timer = setInterval(function() {\n\t\t\tself.update(vDev);\n\t\t}, this.config[\"getterPollInterval_\" + deviceType] * 1000);\n\t}\n};\n\nHTTPDevice.prototype.stop = function () {\n\tif (this.timer) {\n\t\tclearInterval(this.timer);\n\t}\n\t\n\tthis.controller.devices.remove(\"HTTP_Device_\" + this.config.deviceType + \"_\" + this.id);\n\t\n\tHTTPDevice.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nHTTPDevice.prototype.update = function (vDev) {\n\tvar self = this,\n\t\tdeviceType = vDev.get(\"deviceType\"),\n\t\turl = this.config[\"getter_\" + deviceType],\n\t\tparser = this.config[\"getterParser_\" + deviceType];\n\t\n\tif (url) {\n\t\tvar req = {\n\t\t\turl: url,\n\t\t\tasync: true,\n\t\t\tsuccess: function(response) {\n\t\t\t\tvar data = null;\n\t\t\t\tif (parser) {\n\t\t\t\t\tdata = (function($$) {\n\t\t\t\t\t\treturn eval(parser);\n\t\t\t\t\t})(response.data);\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof(response.data) === \"string\") {\n\t\t\t\t\t\tvar _data = response.data.trim();\n\t\t\t\t\t\tif (deviceType === \"switchBinary\" || deviceType === \"sensorBinary\") {\n\t\t\t\t\t\t\tif (_data === \"1\" || _data === \"on\" || _data === \"true\") {\n\t\t\t\t\t\t\t\tdata = \"on\";\n\t\t\t\t\t\t\t} else if (_data === \"0\" || _data === \"off\" || _data === \"false\") {\n\t\t\t\t\t\t\t\tdata = \"off\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (deviceType === \"switchMultilevel\" || deviceType === \"sensorMultilevel\") {\n\t\t\t\t\t\t\tif (parseFloat(_data) != NaN) {\n\t\t\t\t\t\t\t\tdata = parseFloat(_data);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (data !== null && (self.config.skipEventIfSameValue !== true || data !== vDev.get(\"metrics:level\"))) {\n\t\t\t\t\tvDev.set(\"metrics:level\", data);\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function(response) {\n\t\t\t\tself.log(\"Can not make request: \" + response.statusText + \" \" + url);\n\t\t\t} \n\t\t};\n\n\t\t// With Method\n\t\tif (self.config.methodForGetValue && (deviceType === \"switchMultilevel\" || deviceType === \"switchBinary\")) { // compatibility with 2.1\n\t\t\treq.method = self.config.methodForGetValue;\n\t\t}\n\t\telse {\n\t\t\treq.method = self.config.method; // compatibility with 2.1\n\t\t}\n\n\t\tif (req.method === \"POST\") {\n\t\t\t// With Content type\n\t\t\tif (self.config.contentTypeForGetValue && (deviceType === \"switchMultilevel\" || deviceType === \"switchBinary\")) { // compatibility with 2.1\n\t\t\t\treq.headers = { \"Content-Type\": self.config.contentTypeForGetValue}\n\t\t\t}\n\t\t\telse if (self.config.contentType) {\n\t\t\t\treq.headers = { \"Content-Type\": self.config.contentType} // compatibility with 2.1\n\t\t\t}\n\n\t\t\t// With Data\n\t\t\tif (self.config.dataForGetValue && (deviceType === \"switchMultilevel\" || deviceType === \"switchBinary\")) { // compatibility with 2.1\n\t\t\t\treq.data = self.config.dataForGetValue;\n\t\t\t}\n\t\t\telse if (self.config.data) {\n\t\t\t\treq.data = self.config.data; // compatibility with 2.1\n\t\t\t}\n\t\t}\n\t\t\n\t\t// With Authorization\n\t\tif (self.config.login && self.config.password) {\n\t\t\treq.auth = {\n\t\t\t\t\tlogin: self.config.login,\n\t\t\t\t\tpassword: self.config.password\n\t\t\t};\n\t\t}\n\t\thttp.request(req);\n\t}\n};\n\nHTTPDevice.prototype.act = function (vDev, action, subst, selfValue) {\n\tvar self = this,\n\t\tdeviceType = vDev.get(\"deviceType\"),\n\t\turl = this.config[\"setter\" + action + \"_\" + deviceType],\n\t\tlangFile = self.loadModuleLang();\n\t\n\tif (!!url) {\n\t\tif (subst !== null) {\n\t\t\turl = url.replace(/\\$\\$/g, subst);\n\t\t}\n\t\tvar req = {\n\t\t\turl: url,\n\t\t\tmethod: this.config.method,\n\t\t\tasync: true,\n\t\t\terror: function(response) {\n\t\t\t\tself.addNotification(\"error\", langFile.err_req + response.statusText + \" (\" + url + \")\", \"module\");\n\t\t\t}\n\t\t};\n\n\t\tif (req.method === \"POST\") {\n\t\t\t// With Content type\n\t\t\tif (self.config.contentType) {\n\t\t\t\treq.headers = { \"Content-Type\": self.config.contentType }\n\t\t\t}\n\n\t\t\t// With Data\n\t\t\tif (self.config.data) {\n\t\t\t\treq.data = self.config.data.replace(/\\$\\$/g, subst);\n\t\t\t}\n\t\t}\n\t\t// With authorization\n\t\tif (self.config.login && self.config.password) {\n\t\t\treq.auth = {\n\t\t\t\t\tlogin: self.config.login,\n\t\t\t\t\tpassword: self.config.password\n\t\t\t};\n\t\t}\n\t\thttp.request(req);\n\t}\n\t\n\tif ((!url || this.config.updateOnAction === true) && selfValue !== null) {\n\t\tvDev.set(\"metrics:level\", selfValue);\n\t}\n};\n\n/* Log helper functions */\nHTTPDevice.prototype.log = function(message) {\n    if (undefined === message) return;\n    console.log(\"[\"+this.constructor.name+\"-\"+this.id+\"] \"+message);\n};\n"
  },
  {
    "path": "modules/HTTPDevice/lang/de.json",
    "content": "{\n\t\"m_title\":\"HTTP-Gerät\",\n\t\"m_descr\":\"Die Anwendung dieser App erfordert solide Kenntnisse in der JavaScript Programmierung. Diese App ermöglicht die Erstellung eines Elements basierend auf Informationen, die Sie durch eine HTTP Abfrage erhalten können. In Abhängigkeit von der Information können Sie einen Binärsensor oder einen mehrstufigen Sensor auswählen. Es ist ebenso möglich, ein Element zu erstellen, welches einige Funktionen via HTTP steuert: In diesem Fall müssen Sie zur Befehlsausführung URLs hinzufügen; bei Binärschaltern ein Link auf „An“ und „Aus“, bei mehrstufigen Schaltern eine URL zur Einstellung des erforderlichen Wertes. Daraus resultiert ein neues Element, das wie ein Element aus dem Smart Home Netzwerk erscheint. <br><br>Einstellungen:<br><ul><li>Wählen Sie zu allererst den Elementtyp, der erstellt werden soll. Weitere Einstellungen sind vom Elementtyp abhängig. </li><li>Alle Geräte benötigen eine URL, um den Wert aus dem Internet abzurufen.</li><li>Es gibt eine Möglichkeit, die Ansprache mit mathematischer Logik zu entwickeln. Dafür werden fundierte Kenntnisse im JavaScript benötigt.</li><li>Bestimmen Sie die Abrufzeit.</li><li>Definieren Sie, ob „POST“ oder „GET“ verwendet wird.</li><li>Bei mehrstufigen Sensoren können Sie den zu verwendenden Maßstab einstellen.</li><li>Bei Schaltern können die URLs für Schaltungen bestimmt werden.</li></ul><br>Beispiel: Eine App soll den aktuellen Wechselkurs zwischen USD und EUR anzeigen. Die verwendete URL kann http://www.floatrates.com/daily/usd.xml sein. Mit dieser XML-Datei ist es möglich, den wirklichen Wechselkurs durch Verwendung des String “parseFloat($$$$.findOne('/channel/item/exchangeRate/text()'))” herauszufiltern. <br>Anwendung: Die App erstellt ein neues Element. In Hinblick auf das oben aufgeführte Beispiel zeigt das Element den Wechselkurs an.\",\n\t\"l_schema\":\"Wählen Sie einen Gerätetyp\",\n\t\"l_icon\":\"Icon\",\n\t\"l_setterOn\":\"Schalte das Gerät über die URL an (ON)\",\n\t\"p_setterOn\":\"http://192.168.0.100/action/on\",\n\t\"l_setterOff\":\"Schalte das Gerät über die URL aus (OFF)\",\n\t\"p_setterOff\":\"http://192.168.0.100/action/off\",\n\t\"l_getter\":\"Rufe einen Wert über die URL ab\",\n\t\"p_getter\":\"http://192.168.0.100/get/value\",\n\t\"l_getterParser_Binary\":\"Inline Javascript für das Einlesen der hereinkommenden Daten als 'on'/'off' Strings\",\n\t\"h_getterParser_Binary\":\"Bei keiner Eingabe wird der ankommende String verwendet. Bsp.: $$$$.split(':')[1] oder $$$$.data.metrics.level oder $$$$ === 'ON' ? 'on' : 'off'\",\n\t\"l_getterPollInterval\":\"Abfrageintervall in Sekunden\",\n\t\"h_getterPollInterval\":\"Bei keiner Eingabe oder 0 wird kein Abfrageintervall instanziiert (Explizite update Kommandos funktionieren auch weiterhin)\",\n\t\"l_getterParser_Multilevel\":\"Inline Javascript für das Einlesen eingehender Daten als Zahlen\",\n\t\"h_getterParser_Multilevel\":\"Bei keiner Eingabe wird parseFloat() verwendet. Bsp.: $$$$.split(':'')[1] oder parseInt($$$$, 16) oder $$$$.data.metrics.level oder parseFloat($$$$.findOne(\\\\\\\"/A/B[@C='123']/D/text()\\\\\\\"))\",\n\t\"l_setterLevel\":\"Führe eine Aktion über die URL aus\",\n\t\"p_setterLevel\":\"http://192.168.0.100/action/set/$$$$\",\n\t\"h_setterLevel\":\"$$$$ wird benutzt um das Level in der URL zu symbolisieren. Bsp.: http://host/dimmer/level/$$$$/set\",\n\t\"l_scale\":\"Sensor Skala\",\n\t\"l_method\":\"HTTP Methoden\",\n\t\"l_contentType\":\"Content type\",\n\t\"h_contentType\":\"Can be application/json, application/xml, text/html and another MIME types.\",\n\t\"l_data\":\"Data\",\n\t\"h_data\":\"Data to send with POST request. As example string to set value in virtual device in Fibaro HC2: {\\\\\\\"args\\\\\\\":[\\\\\\\"ui.Label1.value\\\\\\\",\\\\\\\"$$$$\\\\\\\"]}\",\n\t\"l_methodForGetValue\":\"HTTP method to get value\",\n\t\"l_contentTypeForGetValue\":\"Content type to get value\",\n\t\"h_contentTypeForGetValue\":\"Can be application/json, application/xml, text/html and another MIME types.\",\n\t\"l_dataForGetValue\":\"Data to get value\",\n\t\"h_dataForGetValue\":\"Data to send with POST request. As example string to set value in virtual device in Fibaro HC2: {\\\\\\\"args\\\\\\\":[\\\\\\\"ui.Label1.value\\\\\\\",\\\\\\\"$$$$\\\\\\\"]}\",\n\t\"err_req\":\"Es konnte kein Request gesendet werden: \",\n\t\"rl_updateOnAction\": \"Update value on action\",\n\t\"h_updateOnAction\": \"On actions (on/off/dimming) update value accordingly before it is polled\",\n\t\"rl_skipEventIfSameValue\": \"Don't send update event if value has not changed\",\n\t\"h_skipEventIfSameValue\": \"If same value is reported, do not send update event. In this case no update listeners will be called.\",\n\t\"l_login\":\"Login\",\n\t\"h_login\":\"If needed, set login\",\n\t\"l_password\":\"Pasword\",\n\t\"h_password\":\"If needed, set password\"\n}"
  },
  {
    "path": "modules/HTTPDevice/lang/en.json",
    "content": "{\n\t\"m_title\":\"HTTP Device\",\n\t\"m_descr\":\"The use of this app requires solid knowledge of JavaScript programming. This app allows you creating an element based on information you can get from a HTTP request. Depending on the information you may choose a sensor binary or a sensor multilevel. It is also possible to create an element controlling some functions via HTTP: In this case you need to add URLs for executing the commands; for binary switches one link of “on” and “off”, for multilevel switch an URL to set a value is required. The result is a new element that appears like an element from the Smart Home network.<br><br>Settings:<br><ul><li>First of all you need to choose what type of element shall be created. Depending on the type other settings are required.</li><li>All devices need an URL to call the value from the Internet</li><li>There is a chance to form the response using formal logic. In order to do this some detailed JavaScript knowledge is needed.</li><li>Define the polling time.</li><li>Define if POST or GET is used.</li><li>For Multilevel sensor you can define the scale to be used.</li><li>For Switches the URLS for switching can be defined.</li></ul><br>Example: An app shall show the current exchange rate between USD and EUR. The URL used can be http://www.floatrates.com/daily/usd.xml. This is an XML file, so it is possible to filter out the real exchange rate using the string “parseFloat($$$$.findOne('/channel/item/exchangeRate/text()'))”<br>Usage: The app creates a new element. In case of the example the element will show the exchange rate.\",\n\t\"l_schema\":\"Select device type\",\n\t\"l_icon\":\"Icon\",\n\t\"l_setterOn\":\"URL for action On\",\n\t\"p_setterOn\":\"http://192.168.0.100/action/on\",\n\t\"l_setterOff\":\"URL for action Off\",\n\t\"p_setterOff\":\"http://192.168.0.100/action/off\",\n\t\"l_getter\":\"URL to get value\",\n\t\"p_getter\":\"http://192.168.0.100/get/value\",\n\t\"l_getterParser_Binary\":\"Inline Javascript to parse incoming data to 'on'/'off' strings\",\n\t\"h_getterParser_Binary\":\"Can be empty to use string as is. Example: $$$$.split(':')[1] or $$$$.data.metrics.level or $$$$ === 'ON' ? 'on' : 'off'\",\n\t\"l_getterPollInterval\":\"Interval in seconds between polling requests\",\n\t\"h_getterPollInterval\":\"Empty or 0 to disable periodical requests (explicit update command will still initiate request process)\",\n\t\"l_getterParser_Multilevel\":\"Inline Javascript to parse incoming data to number\",\n\t\"h_getterParser_Multilevel\":\"Can be empty to use parseFloat() function. Example: $$$$.split(':')[1] or parseInt($$$$, 16) or $$$$.data.metrics.level or parseFloat($$$$.findOne(\\\\\\\"/A/B[@C='123']/D/text()\\\\\\\"))\",\n\t\"l_setterLevel\":\"URL for action\",\n\t\"p_setterLevel\":\"http://192.168.0.100/action/set/$$$$\",\n\t\"h_setterLevel\":\"$$$$ is used to represent level in the URL. For example: http://host/dimmer/level/$$$$/set\",\n\t\"l_scale\":\"Sensor scale\",\n\t\"l_method\":\"HTTP method\",\n\t\"l_contentType\":\"Content type\",\n\t\"h_contentType\":\"Can be application/json, application/xml, text/html and another MIME types.\",\n\t\"l_data\":\"Data\",\n\t\"h_data\":\"Data to send with POST request. As example string to set value in virtual device in Fibaro HC2: {\\\\\\\"args\\\\\\\":[\\\\\\\"ui.Label1.value\\\\\\\",\\\\\\\"$$$$\\\\\\\"]}\",\n\t\"l_methodForGetValue\":\"HTTP method to get value\",\n\t\"l_contentTypeForGetValue\":\"Content type to get value\",\n\t\"h_contentTypeForGetValue\":\"Can be application/json, application/xml, text/html and another MIME types.\",\n\t\"l_dataForGetValue\":\"Data to get value\",\n\t\"h_dataForGetValue\":\"Data to send with POST request. As example string to set value in virtual device in Fibaro HC2: {\\\\\\\"args\\\\\\\":[\\\\\\\"ui.Label1.value\\\\\\\",\\\\\\\"$$$$\\\\\\\"]}\",\n\t\"err_req\":\"Can not make request: \",\n\t\"rl_updateOnAction\": \"Update value on action\",\n\t\"h_updateOnAction\": \"On actions (on/off/dimming) update value accordingly before it is polled\",\n\t\"rl_skipEventIfSameValue\": \"Don't send update event if value has not changed\",\n\t\"h_skipEventIfSameValue\": \"If same value is reported, do not send update event. In this case no update listeners will be called.\",\n\t\"l_login\":\"Login\",\n\t\"h_login\":\"If needed, set login\",\n\t\"l_password\":\"Pasword\",\n\t\"h_password\":\"If needed, set password\"\n}"
  },
  {
    "path": "modules/HTTPDevice/lang/ru.json",
    "content": "{\n\t\"m_title\":\"HTTP устройство\",\n\t\"m_descr\":\"Создание устройства основанного на HTTP запросах.\",\n\t\"l_schema\":\"Выберите тип устройства\",\n\t\"l_icon\":\"Иконка\",\n\t\"l_setterOn\":\"URL для действия Включить\",\n\t\"p_setterOn\":\"http://192.168.0.100/action/on\",\n\t\"l_setterOff\":\"URL для действия Выключить\",\n\t\"p_setterOff\":\"http://192.168.0.100/action/off\",\n\t\"l_getter\":\"URL для получения значения\",\n\t\"p_getter\":\"http://192.168.0.100/get/value\",\n\t\"l_getterParser_Binary\":\"JavaScript код для преобразования полученного значения в строки 'on' или 'off'\",\n\t\"h_getterParser_Binary\":\"Поле может быть пустым, если использовать полученную строку без изменений. Пример преобразования: $$$$.split(':')[1] или $$$$.data.metrics.level или $$$$ === 'ON' ? 'on' : 'off'\",\n\t\"l_getterPollInterval\":\"Интервал в секундах опроса значения\",\n\t\"h_getterPollInterval\":\"Пусто или 0 отключают периодический опрос (запросить значение можно вручную командой update)\",\n\t\"l_getterParser_Multilevel\":\"JavaScript код для преобразования полученного значения в число\",\n\t\"h_getterParser_Multilevel\":\"Поле может быть пустым, тогда будет использована функция parseFloat(). Пример преобразования: $$$$.split(':')[1] или parseInt($$$$, 16) или $$$$.data.metrics.level или parseFloat($$$$.findOne(\\\\\\\"/A/B[@C='123']/D/text()\\\\\\\"))\",\n\t\"l_setterLevel\":\"URL для действия\",\n\t\"p_setterLevel\":\"http://192.168.0.100/action/set/$$$$\",\n\t\"h_setterLevel\":\"Символы $$$$ содержат значение уровня диммирования от 0 до 99 в URL. Например: http://host/dimmer/level/$$$$/set\",\n\t\"l_scale\":\"Единица измерения\",\n\t\"l_method\":\"HTTP метод\",\n\t\"l_contentType\":\"Content type\",\n\t\"h_contentType\":\"Может быть application/json, application/xml, text/html и др. MIME типы.\",\n\t\"l_data\":\"Данные\",\n\t\"h_data\":\"Данные отправляемые в POST запросе. Например строка для передачи текущего значения датчика в виртуальное устройство на Fibaro HC2: {\\\\\\\"args\\\\\\\":[\\\\\\\"ui.Label1.value\\\\\\\",\\\\\\\"$$$$\\\\\\\"]}\",\n\t\"l_method\":\"HTTP метод для получения значения\",\n\t\"l_contentType\":\"Content type для получения значения\",\n\t\"h_contentType\":\"Может быть application/json, application/xml, text/html и др. MIME типы.\",\n\t\"l_data\":\"Data для получения значения\",\n\t\"h_data\":\"Данные отправляемые в POST запросе. Например строка для передачи текущего значения датчика в виртуальное устройство на Fibaro HC2: {\\\\\\\"args\\\\\\\":[\\\\\\\"ui.Label1.value\\\\\\\",\\\\\\\"$$$$\\\\\\\"]}\",\n\t\"err_req\":\"Невозможно выполнить запрос: \",\n\t\"rl_updateOnAction\": \"Менять состояние при действиях\",\n\t\"h_updateOnAction\": \"При действиях с устройством (включение/выключение/диммирование), менять состояние на соответствующее действию, не дожидаясь получения опроса значения.\",\n\t\"rl_skipEventIfSameValue\": \"Не отправлять событие обновления, если значение не поменялось\",\n\t\"h_skipEventIfSameValue\": \"Если получено значение, совпадающее с предыдущим, не обновлять значение. В этом случае не будут вызваны подписчики на события обновления.\",\n\t\"l_login\":\"Логин\",\n\t\"h_login\":\"Если требуется, задайте логин\",\n\t\"l_password\":\"Пароль\",\n\t\"h_password\":\"Если требуется, задайте пароль\"\n}"
  },
  {
    "path": "modules/HTTPDevice/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"developers_stuff\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"HTTPDevice\",\n\t\"version\": \"2.2.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"deviceType\": \"toggleButton\",\n\t\t\"iconSensorBinary\": \"\",\n\t\t\"iconSensorMultilevel\": \"\",\n\t\t\"setterOn_toggleButton\": \"\",\n\t\t\"getter_sensorBinary\": \"\",\n\t\t\"getterParser_sensorBinary\": \"\",\n\t\t\"getterPollInterval_sensorBinary\": 0,\n\t\t\"getter_sensorMultilevel\": \"\",\n\t\t\"getterParser_sensorMultilevel\": \"\",\n\t\t\"getterPollInterval_sensorMultilevel\": 0,\n\t\t\"scale_sensorMultilevel\": \"\",\n\t\t\"setterOn_switchBinary\": \"\",\n\t\t\"setterOff_switchBinary\": \"\",\n\t\t\"getter_switchBinary\": \"\",\n\t\t\"getterParser_switchBinary\": \"\",\n\t\t\"getterPollInterval_switchBinary\": 0,\n\t\t\"setterLevel_switchMultilevel\": \"\",\n\t\t\"getter_switchMultilevel\": \"\",\n\t\t\"getterParser_switchMultilevel\": \"\",\n\t\t\"getterPollInterval_switchMultilevel\": 0,\n\t\t\"method\": \"GET\",\n\t\t\"contentType\": \"application/x-www-form-urlencoded\",\n\t\t\"data\":\"\",\n\t\t\"methodForGetValue\": \"GET\",\n\t\t\"contentTypeForGetValue\": \"application/x-www-form-urlencoded\",\n\t\t\"dataForGetValue\":\"\",\n\t\t\"updateOnAction\": false,\n\t\t\"skipEventIfSameValue\": false,\n\t\t\"login\":\"\",\n\t\t\"password\":\"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"deviceType\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"toggleButton\", \"sensorBinary\", \"sensorMultilevel\", \"switchBinary\", \"switchMultilevel\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"iconSensorBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"alarm\", \"motion\", \"smoke\", \"co\", \"flood\",\"cooling\",\"tamper\",\"door\"],\n\t\t\t\t\"default\": \"alarm\", \n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"iconSensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"temperature\", \"luminosity\", \"energy\", \"humidity\", \"barometer\",\"seismic\",\"ultraviolet\",\"acceleration_x\",\"acceleration_y\",\"acceleration_z\"],\n\t\t\t\t\"default\": \"temperature\", \n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterOn_toggleButton\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_sensorBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterParser_sensorBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorBinary\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_sensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterParser_sensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorMultilevel\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"scale_sensorMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterOn_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterOff_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterParser_switchBinary\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_switchBinary\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"setterLevel_switchMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getter_switchMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterParser_switchMultilevel\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"getterPollInterval_switchMultilevel\": {\n\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\"required\": false,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"method\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [\"GET\", \"POST\"]\n\t\t\t},\n\t\t\t\"contentType\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"method\"\n\t\t\t},\n\t\t\t\"data\":{\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"method\"\n\t\t\t},\n\t\t\t\"methodForGetValue\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [\"GET\", \"POST\"],\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\t\t\t\"contentTypeForGetValue\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"methodForGetValue\"\n\t\t\t},\n\t\t\t\"dataForGetValue\":{\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"methodForGetValue\"\n\t\t\t},\n\t\t\t\"updateOnAction\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"deviceType\"\n\t\t\t},\n\n\t\t\t\"skipEventIfSameValue\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"login\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": false\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"deviceType\": {\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"iconSensorBinary\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"label\": \"__l_icon__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"iconSensorMultilevel\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"label\": \"__l_icon__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterOn_toggleButton\": {\n\t\t\t\t\"label\": \"__l_setterOn__\",\n\t\t\t\t\"placeholder\": \"__p_setterOn__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"toggleButton\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_sensorBinary\": {\n\t\t\t\t\"label\": \"__l_getter__\",\n\t\t\t\t\"placeholder\": \"__p_getter__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterParser_sensorBinary\": {\n\t\t\t\t\"label\": \"__l_getterParser_Binary__\",\n\t\t\t\t\"helper\": \"__h_getterParser_Binary__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorBinary\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_getter__\",\n\t\t\t\t\"placeholder\": \"__p_getter__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterParser_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_getterParser_Multilevel__\",\n\t\t\t\t\"helper\": \"__h_getterParser_Multilevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scale_sensorMultilevel\": {\n\t\t\t\t\"label\": \"__l_scale__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"sensorMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterOn_switchBinary\": {\n\t\t\t\t\"label\": \"__l_setterOn__\",\n\t\t\t\t\"placeholder\": \"__p_setterOn__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterOff_switchBinary\": {\n\t\t\t\t\"label\": \"__l_setterOff__\",\n\t\t\t\t\"placeholder\": \"__p_setterOff__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_switchBinary\": {\n\t\t\t\t\"label\": \"__l_getter__\",\n\t\t\t\t\"placeholder\": \"__p_getter__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterParser_switchBinary\": {\n\t\t\t\t\"label\": \"__l_getterParser_Binary__\",\n\t\t\t\t\"helper\": \"__h_getterParser_Binary__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_switchBinary\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchBinary\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"setterLevel_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_setterLevel__\",\n\t\t\t\t\"placeholder\": \"__p_setterLevel__\",\n\t\t\t\t\"helper\": \"__h_setterLevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getter_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_getter__\",\n\t\t\t\t\"placeholder\": \"__p_getter__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterParser_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_getterParser_Multilevel__\",\n\t\t\t\t\"helper\": \"__h_getterParser_Multilevel__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"getterPollInterval_switchMultilevel\": {\n\t\t\t\t\"label\": \"__l_getterPollInterval__\",\n\t\t\t\t\"helper\": \"__h_getterPollInterval__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": \"switchMultilevel\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"method\": {\n\t\t\t\t\"label\": \"__l_method__\",\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"contentType\": {\n\t\t\t\t\"label\": \"__l_contentType__\",\n\t\t\t\t\"helper\": \"__h_contentType__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"method\": \"POST\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"data\":{\n\t\t\t\t\"label\": \"__l_data__\",\n\t\t\t\t\"helper\": \"__h_data__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"method\": \"POST\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"methodForGetValue\": {\n\t\t\t\t\"label\": \"__l_methodForGetValue__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": [\"switchBinary\", \"switchMultilevel\"]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"contentTypeForGetValue\": {\n\t\t\t\t\"label\": \"__l_contentTypeForGetValue__\",\n\t\t\t\t\"helper\": \"__h_contentTypeForGetValue__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"methodForGetValue\": \"POST\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"dataForGetValue\":{\n\t\t\t\t\"label\": \"__l_dataForGetValue__\",\n\t\t\t\t\"helper\": \"__h_dataForGetValue__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"methodForGetValue\": \"POST\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"updateOnAction\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_updateOnAction__\",\n\t\t\t\t\"helper\": \"__h_updateOnAction__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"deviceType\": [ \"switchBinary\", \"switchMultilevel\"]\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"skipEventIfSameValue\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_skipEventIfSameValue__\",\n\t\t\t\t\"helper\": \"__h_skipEventIfSameValue__\"\n\t\t\t},\n\n\t\t\t\"login\": {\n\t\t\t\t\"label\": \"__l_login__\",\n\t\t\t\t\"helper\": \"__h_login__\"\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__l_password__\",\n\t\t\t\t\"helper\": \"__h_password__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/HazardNotification/index.js",
    "content": "/*** HazardNotification Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2015\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>\n        Karsten Reichel <kar@zwave.eu>\n        Michael Hensche <mh@zwave.eu>\nDescription:\n    Filters all water sensors, fire sensors and creates a virtual device to monitor and control them together.\n******************************************************************************/\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\nfunction HazardNotification(id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tHazardNotification.super_.call(this, id, controller);\n}\n\ninherits(HazardNotification, AutomationModule);\n\n_module = HazardNotification;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nHazardNotification.prototype.init = function(config) {\n\tHazardNotification.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tfilteredSensorsFromDevices = [],\n\t\thazardSensorMetrics = [],\n\t\titem = {};\n\n\tthis.vDev = null;\n\n\tif (self.config.triggerEvent.length > 0 && !self.config.transformed) {\n\t\tvar new_triggerEvents = [];\n\n\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes \n\t\t    {\n\t\t        deviceId: '',\n\t\t        deviceType: '',\n\t\t        level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t        sendAction: true || false >> don't do this if level is already triggered\n\t\t    }\n\t\t*/\n\t\tself.config.triggerEvent.forEach(function(entry) {\n\t\t\tvDev = self.controller.devices.get(entry.deviceId);\n\n\t\t\tnew_triggerEvents.push({\n\t\t\t\tdeviceId: entry.deviceId,\n\t\t\t\tdeviceType: vDev ? vDev.get('deviceType') : '',\n\t\t\t\tlevel: entry.status && entry.status != 'level' ? entry.status : (entry.status === 'level' && entry.level ? entry.level : 0),\n\t\t\t\tsendAction: entry.sendAction || false\n\t\t\t});\n\t\t});\n\n\t\t// overwrite config devices list\n\t\tself.config.triggerEvent = _.uniq(new_triggerEvents);\n\t\tself.config.transformed = true;\n\n\t\t//save into config\n\t\tself.saveConfig();\n\t}\n\n\t// update vDev attributes (water and fire sensors)\n\tself.updateAttributes = function(dev) {\n\t\tvar hazardSensors = [],\n\t\t\tsensor = [],\n\t\t\tindx = null;\n\n\t\thazardSensors = self.vDev.get('metrics:sensors');\n\n\t\tsensor = hazardSensors.filter(function(sensor) {\n\t\t\treturn sensor.id === dev.get('id');\n\t\t});\n\n\t\tif (sensor[0]) {\n\t\t\t// update sensor metrics\n\t\t\tsensor[0].metrics = dev.get('metrics');\n\t\t}\n\t};\n\n\t// add sensors to vDev (after server startup)\n\tself.updateIfHazardSensorsAreCreated = function(dev) {\n\t\tvar indx = self.config.sensors.indexOf(dev.id);\n\n\t\tif (indx > -1 && hazardSensorMetrics.map(function(e) {\n\t\t\t\treturn e.id;\n\t\t\t}).indexOf(dev.id) === -1) {\n\n\t\t\tif (filteredSensorsFromDevices.indexOf(dev) === -1) {\n\t\t\t\tfilteredSensorsFromDevices.push(dev);\n\t\t\t}\n\n\t\t\titem = {\n\t\t\t\tid: dev.id,\n\t\t\t\tdeviceType: dev.get('deviceType'),\n\t\t\t\tmetrics: dev.get('metrics'),\n\t\t\t\thasHistory: dev.get('hasHistory'),\n\t\t\t\tupdateTime: dev.get('updateTime')\n\t\t\t};\n\n\t\t\thazardSensorMetrics.push(item);\n\n\t\t\t// listen to sensor changes\n\t\t\tself.controller.devices.on(dev.id, 'change:[object Object]', self.updateAttributes);\n\n\t\t\t// setup arm mode (reinitialize vDev)\n\t\t\tif (self.vDev.get('metrics:state') === 'armed') {\n\t\t\t\tif (dev.get('metrics:level') === 'on') {\n\t\t\t\t\tself.setAlert();\n\t\t\t\t}\n\n\t\t\t\t// listen to sensor changes\n\t\t\t\tself.controller.devices.on(dev.id, 'change:metrics:level', self.throwAlert);\n\t\t\t}\n\t\t}\n\t};\n\n\t// activate armed modus\n\tself.setupArmed = function() {\n\t\t// if it is still alert set alert mode \n\t\tif (self.getSensorLevels().length > 0 && self.getSensorLevels().indexOf('on') !== -1) {\n\t\t\tself.setAlert();\n\t\t} else {\n\t\t\tself.vDev.set('metrics:level', 'OK');\n\t\t\tvar icon = config.hazardType == \"fire\" ? \"fire_ok.png\" : \"leakage_ok.png\";\n\t\t\tself.vDev.set('metrics:icon', '/ZAutomation/api/v1/load/modulemedia/HazardNotification/'+icon);\n\t\t}\n\n\t\t// listen to sensor changes\n\t\tfilteredSensorsFromDevices.forEach(function(dev) {\n\t\t\tself.controller.devices.on(dev.id, 'change:metrics:level', self.throwAlert);\n\t\t});\n\t};\n\n\t// listener - what to do if sensors state has changed \n\tself.throwAlert = function(dev) {\n\n\t\t//set alert mode\n\t\tif (dev.get('metrics:level') === 'on' && self.vDev.get('metrics:level') !== 'ALERT') {\n\t\t\tself.setAlert();\n\t\t}\n\n\t\t//set back armed mode if alert is OK and device is not disarmed\n\t\tif (dev.get('metrics:level') === 'off' &&\n\t\t\tself.vDev.get('metrics:level') === 'ALERT' &&\n\t\t\tself.getSensorLevels().length > 0 &&\n\t\t\tself.getSensorLevels().indexOf('on') === -1 &&\n\t\t\tself.vDev.get('metrics:state') !== 'disarmed') {\n\n\t\t\tself.vDev.set('metrics:level', 'OK!');\n\t\t\tvar icon = config.hazardType == \"fire\" ? \"fire_warning.png\" : \"leakage_warning.png\";\n\t\t\tself.vDev.set('metrics:icon', '/ZAutomation/api/v1/load/modulemedia/HazardNotification/' + icon);\n\n\t\t\tself.triggerNotification('revert');\n\n\t\t\tif (self.sendInterval) {\n\t\t\t\t//console.log('Stop - Clear send ...');\n\t\t\t\tclearInterval(self.sendInterval);\n\t\t\t\tself.sendInterval = undefined;\n\t\t\t}\n\t\t}\n\t};\n\n\t// set vDev to alert mode\n\tself.setAlert = function() {\n\t\tvar icon = config.hazardType == \"fire\" ? \"fire_alarm.png\" : \"leakage_alarm.png\";\n\t\tself.vDev.set('metrics:level', 'ALERT');\n\t\tself.vDev.set('metrics:icon', '/ZAutomation/api/v1/load/modulemedia/HazardNotification/' + icon);\n\n\t\t// trigger reaction\n\t\tself.triggerEvents();\n\n\t\tif (!self.sendInterval) {\n\t\t\tself.triggerNotification('alarm');\n\t\t\tself.sendInterval = setInterval(function() {\n\t\t\t\t//console.log('Send ...');\n\t\t\t\tself.triggerNotification('alarm');\n\t\t\t}, parseInt(config.notificationsInterval, 10) * 1000);\n\t\t}\n\t};\n\n\tself.triggerNotification = function(type) {\n\t\t_.forEach(config.sendNotifications, function(notification) {\n\t\t\tif (type == notification.firedOn) {\n\t\t\t\tvar notificationType = '',\n\t\t\t\t\tnotificationMessage = '';\n\n\t\t\t\tif (notification.target && notification.target !== '') {\n\t\t\t\t\tself.controller.notificationChannelSend(notification.target, notification.message ? notification.message : self.getInstanceTitle());\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\tself.triggerEvents = function() {\n\t\t_.forEach(config.triggerEvent, function(event) {\n\t\t\t/*var vDev = self.controller.devices.get(event.deviceId),\n\t\t\t    lvl = event.status == \"lvl\" ? event.level : event.status,\n\t\t\t    set = event.sendAction ? self.executeActions(event.sendAction, vDev, lvl) : true;\n\t\t\tif (vDev && set) {\n\t\t\t    self.setNewDeviceState(vDev, lvl);\n\t\t\t}*/\n\n\t\t\tself.shiftDevice(event);\n\t\t});\n\t};\n\n\t// listener - set vDev level back to OK if device is disarmed and sensor levels are all 'off'\n\tself.onPoll = function() {\n\t\tif (self.getSensorLevels().indexOf('on') === -1 && self.vDev) {\n\t\t\tself.vDev.set('metrics:level', 'OK');\n\t\t\tvar icon = config.hazardType == \"fire\" ? \"fire_ok.png\" : \"leakage_ok.png\";\n\t\t\tself.vDev.set('metrics:icon', '/ZAutomation/api/v1/load/modulemedia/HazardNotification/'+icon);\n\t\t\tself.removePolling();\n\t\t}\n\t};\n\n\t// remove polling after disarm and sensor levels are ok\n\tself.removePolling = function() {\n\n\t\tif (self.timer) {\n\t\t\t//console.log('Clear check ...');\n\t\t\tclearInterval(self.timer);\n\t\t\tself.timer = undefined;\n\t\t}\n\n\t\tif (self.sendInterval) {\n\t\t\t//console.log('Clear send ...');\n\t\t\tclearInterval(self.sendInterval);\n\t\t\tself.sendInterval = undefined;\n\t\t}\n\t};\n\n\tself.checkState = function() {\n\t\tif (!self.timer) {\n\t\t\tself.timer = setInterval(function() {\n\t\t\t\t//console.log('Do check ...');\n\t\t\t\tself.onPoll();\n\t\t\t}, 10 * 1000);\n\t\t}\n\t};\n\n\t// get sensors from devices\n\tfilteredSensorsFromDevices = self.controller.devices.filter(function(dev) {\n\t\treturn self.config.sensors.indexOf(dev.id) > -1;\n\t});\n\n\t// create vDev metrics with sensor values\n\tfilteredSensorsFromDevices.forEach(function(dev) {\n\n\t\titem = {\n\t\t\tid: dev.id,\n\t\t\tdeviceType: dev.get('deviceType'),\n\t\t\tmetrics: dev.get('metrics'),\n\t\t\thasHistory: dev.get('hasHistory'),\n\t\t\tupdateTime: dev.get('updateTime')\n\t\t};\n\n\t\thazardSensorMetrics.push(item);\n\n\t\t// listen to sensor changes\n\t\tself.controller.devices.on(dev.id, 'change:[object Object]', self.updateAttributes);\n\t});\n\n\tvar metr = self.controller.vdevInfo[\"HazardNotification_\" + self.id] && self.controller.vdevInfo[\"HazardNotification_\" + self.id].metrics ? self.controller.vdevInfo[\"HazardNotification_\" + self.id].metrics : null,\n\t\ticon = config.hazardType == \"fire\" ? \"fire_ok.png\" : \"leakage_ok.png\";\n\n\t// create vDev\n\tself.vDev = self.controller.devices.create({\n\t\tdeviceId: \"HazardNotification_\" + self.id,\n\t\tdefaults: {\n\t\t\tdeviceType: 'sensorMultiline',\n\t\t\tmetrics: {\n\t\t\t\tmultilineType: 'protection',\n\t\t\t\ttitle: self.getInstanceTitle(),\n\t\t\t\ticon: '/ZAutomation/api/v1/load/modulemedia/HazardNotification/' + icon,\n\t\t\t\tlevel: !!metr && metr.level ? metr.level : 'OK',\n\t\t\t\tstate: !!metr && metr.state ? metr.state : 'disarmed'\n\t\t\t}\n\t\t},\n\t\toverlay: {\n\t\t\tmetrics: {\n\t\t\t\ttitle: self.getInstanceTitle(),\n\t\t\t\tsensors: hazardSensorMetrics\n\t\t\t}\n\t\t},\n\t\thandler: function(command) {\n\t\t\tvar cutDevId = [],\n\t\t\t\tcutIdNumbers = [],\n\t\t\t\tnodId = [];\n\t\t\t// arm\n\t\t\tif (command === 'arm' && hazardSensorMetrics.length > 0) {\n\t\t\t\t// set vDev state to armed\n\t\t\t\tthis.set('metrics:state', 'armed');\n\n\t\t\t\t// remove polling\n\t\t\t\tself.removePolling();\n\n\t\t\t\t// set up arm mode\n\t\t\t\tself.setupArmed();\n\n\t\t\t\tself.triggerNotification('on');\n\t\t\t}\n\t\t\t// disarm\n\t\t\tif (command === 'disarm' && hazardSensorMetrics.length > 0) {\n\t\t\t\t// set vDev state to disarmed\n\t\t\t\tthis.set('metrics:state', 'disarmed');\n\n\t\t\t\t// set up cron handler checking for alert\n\t\t\t\tif (self.getSensorLevels().indexOf('on') !== -1) {\n\n\t\t\t\t\tself.checkState();\n\t\t\t\t} else {\n\t\t\t\t\tthis.set('metrics:level', 'OK');\n\t\t\t\t\tthis.set('metrics:icon', '/ZAutomation/api/v1/load/modulemedia/HazardNotification/' + icon);\n\t\t\t\t}\n\n\t\t\t\tself.triggerNotification('off');\n\n\t\t\t\tif (self.sendInterval) {\n\t\t\t\t\t//console.log('Disarmed - Clear send ...');\n\t\t\t\t\tclearInterval(self.sendInterval);\n\t\t\t\t\tself.sendInterval = undefined;\n\t\t\t\t}\n\n\t\t\t\t// remove listener of sensor changes\n\t\t\t\tfilteredSensorsFromDevices.forEach(function(dev) {\n\t\t\t\t\tself.controller.devices.off(dev.id, 'change:metrics:level', self.throwAlert);\n\t\t\t\t});\n\n\t\t\t\t//if ALERT send basic off to each water anf fire detector\n\t\t\t\tif (this.get('metrics:level') === 'ALERT') {\n\t\t\t\t\t//get correct node id\n\t\t\t\t\tself.config.sensors.forEach(function(id) {\n\t\t\t\t\t\tcutDevId = id.split('_');\n\t\t\t\t\t\tcutIdNumbers = cutDevId[2].split('-');\n\n\t\t\t\t\t\tif (nodId.indexOf(cutIdNumbers[0]) === -1) {\n\t\t\t\t\t\t\tnodId.push(cutIdNumbers[0]);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tnodId.forEach(function(node) {\n\t\t\t\t\t\t// send via z-way api\n\t\t\t\t\t\tif (zway.devices[node].instances[0].commandClasses[32]) {\n\t\t\t\t\t\t\tzway.devices[node].instances[0].commandClasses[32].Set(0);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//update\n\t\t\tif (command === 'update' && hazardSensorMetrics.length > 0) {\n\t\t\t\tfilteredSensorsFromDevices.forEach(function(sensor) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsensor.performCommand('update');\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tself.controller.addNotification('device-info', 'Update has failed. Error:' + e, 'device-status', sensor.id);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tmoduleId: self.id\n\t});\n\n\t// setup arm mode (reinitialize vDev)\n\tif (self.vDev.get('metrics:state') === 'armed') {\n\t\tself.setupArmed();\n\t}\n\n\t// refresh/create virtual device if sensors are created (after restart)\n\tself.controller.devices.on('created', self.updateIfHazardSensorsAreCreated);\n\n};\n\nHazardNotification.prototype.stop = function() {\n\tvar self = this;\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tthis.controller.devices.filter(function(dev) {\n\t\treturn self.config.sensors.indexOf(dev.id) > -1;\n\t}).forEach(function(dev) {\n\t\tself.controller.devices.off(dev.id, 'change:[object Object]', self.updateAttributes);\n\t\tself.controller.devices.off(dev.id, 'change:metrics:level', self.throwAlert);\n\t});\n\n\tthis.controller.devices.off('created', self.updateIfHazardSensorsAreCreated);\n\n\t// remove polling\n\tthis.removePolling();\n\n\tHazardNotification.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nHazardNotification.prototype.getSensorLevels = function() {\n\tvar self = this;\n\n\treturn self.vDev.get('metrics:sensors').map(function(sensor) {\n\t\treturn sensor.metrics.level;\n\t});\n};\n\n/*// compare old and new level to avoid unnecessary updates\nHazardNotification.prototype.newValueNotEqualsOldValue = function (vDev, valNew) {\n    if (vDev && !!vDev) {\n        var devType = vDev.get('deviceType'),\n            vO = '';\n        vN = _.isNaN(parseFloat(valNew)) ? valNew : parseFloat(valNew);\n\n        switch (devType) {\n            case 'switchRGBW':\n                vO = typeof vN !== 'string' ? vDev.get('metrics:color') : vDev.get('metrics:level');\n\n                if (valNew !== 'string') {\n                    return _.isEqual(vO, vN);\n                }\n            case 'switchControl':\n                if (_.contains(['on', 'off'], vN) || _.isNumber(vN)) {\n                    vO = vDev.get('metrics:level');\n                } else {\n                    vO = vDev.get('metrics:change');\n                }\n            default:\n                vO = vDev.get('metrics:level');\n        }\n        return vO !== vN;\n    }\n};\n\nHazardNotification.prototype.executeActions = function (compareLevelsFirst, vDev, targetValue) {\n    return (!compareLevelsFirst || (compareLevelsFirst && this.newValueNotEqualsOldValue(vDev, targetValue)));\n};\n\nHazardNotification.prototype.setNewDeviceState = function (vDev, type, new_level) {\n    if (vDev && !!vDev) {\n        switch (type) {\n            case 'doorlock':\n            case 'switchBinary':\n                vDev.performCommand(new_level);\n                break;\n            case 'switchMultilevel':\n            case 'thermostat':\n                _.contains(['on', 'off'], new_level) ? vDev.performCommand(new_level) : vDev.performCommand(\"exact\", {\n                    level: new_level\n                });\n                break;\n            case 'switchRGBW':\n                if (_.contains([\"on\", \"off\"], new_level)) {\n                    vDev.performCommand(new_level);\n                } else {\n                    vDev.performCommand(\"exact\", {\n                        red: new_level.red,\n                        green: new_level.green,\n                        blue: new_level.blue\n                    });\n                }\n                break;\n            case 'switchControl':\n                if (_.contains([\"on\", \"off\"], new_level)) {\n                    vDev.performCommand(new_level);\n                } else if (_.contains([\"upstart\", \"upstop\", \"downstart\", \"downstop\"], new_level)) {\n                    vDev.performCommand(\"exact\", {\n                        change: new_level\n                    });\n                } else {\n                    vDev.performCommand(\"exact\", {\n                        level: new_level\n                    });\n                }\n                break;\n            case 'toggleButton':\n                vDev.performCommand('on');\n                break;\n            default:\n                vDev.performCommand(new_level);\n        }\n    }\n};*/"
  },
  {
    "path": "modules/HazardNotification/lang/de.json",
    "content": "{\n    \"m_title\": \"Gefahrenbenachrichtigung\",\n    \"m_descr\": \"\"\n}"
  },
  {
    "path": "modules/HazardNotification/lang/en.json",
    "content": "{\n    \"m_title\": \"Hazard Notification\",\n    \"m_descr\": \"\"\n}"
  },
  {
    "path": "modules/HazardNotification/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"system\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"HazardNotification\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"sensors\": [],\n\t\t\"triggerEvent\": [],\n\t\t\"sendNotifications\": [],\n\t\t\"notificationsInterval\": 0,\n\t\t\"hazardType\": \"\"\n\t},\n\t\"schema\": {},\n\t\"options\": {}\n}"
  },
  {
    "path": "modules/Heating/htdocs/js/postRender.js",
    "content": "function modulePostRender(control) {\n\n    var $tableRoom = $('.climateControlRoomSettings').find('table'),\n        $tableRoomHead = $tableRoom.find('thead tr'),\n        $tableSheduler = $('.climateControlSchedule').find('table'),\n        $tableShedulerHead = $tableSheduler.find('thead tr');\n\n    $(document).off('click', 'button[data-alpaca-array-actionbar-action=\"clone\"]').on('click', 'button[data-alpaca-array-actionbar-action=\"clone\"]', function(e) {\n        e.preventDefault();\n        var $cloneButton = $(this);\n        var $addButton = $cloneButton.parent().find('button[data-alpaca-array-actionbar-action=\"add\"]');\n\n        $addButton.on('click',function() {\n\n            var $oldRow = $(this).parent().parent().parent();\n            setTimeout(function(){\n                var $newRow = $oldRow.next('tr');\n\n                var $oldInputs = $oldRow.find('input:text,input:checkbox, select');\n                var $newInputs = $newRow.find('input:text,input:checkbox, select');\n\n                $newInputs.each(function(i,v) {\n                    if ($(v).attr('type') == 'checkbox') {\n                        $(v).prop('checked', $($oldInputs[i]).is(':checked'));\n                    }\n                    else {\n                        $(v).val($($oldInputs[i]).val());\n                    }\n                    \n                });\n\n                $addButton.off('click');\n            },300);\n        });\n\n        $addButton.click();\n    });\n\n\n    if($tableRoomHead.children('th').length > 6) {\n        var tHeadlength = $tableRoomHead.children('th').length,\n            label = $tableRoomHead.find('th:nth-child(2)').text().split('_')[0],\n            visiblelength = tHeadlength-4;\n\n        for(var i = visiblelength; i > 2; i--) {\n            $tableRoomHead.find('th:nth-child(' + i + ')').remove();\n        }\n        $tableRoomHead.find('th:nth-child(2)').text(label);\n    }\n\n    $tableRoomHead.hide();\n    $tableShedulerHead.hide();\n\n    if($tableRoom.find('tbody tr').length >= 1) {\n        $tableRoomHead.show();\n        $tableRoom.find('tbody tr').each(function(i, v) {\n            buildRow($(v));\n        });\n    }\n\n    if($tableSheduler.find('tbody tr').length >= 1) {\n        $tableShedulerHead.show();\n    }\n\n    $('.climateControlRoomSettings').on('click', 'button[data-alpaca-array-toolbar-action=add]', function(event) {\n        $tableRoomHead.show();\n        var toolbarTimer = setInterval(function() {\n            if($tableRoom.find('tbody tr').length >= 1) {\n                buildRow($tableRoom.find('tbody tr'));\n\n                if(toolbarTimer) {\n                    clearInterval(toolbarTimer);\n                }\n            }\n        }, 100);\n    });\n\n    $('.climateControlSchedule').on('click', 'button[data-alpaca-array-toolbar-action=add]', function(event) {\n       $tableShedulerHead.show();\n    });\n\n    function buildRow($tr) {\n        var currRow = $tr.attr('data-alpaca-field-name'),\n            hideTd = [],\n            elCnt = $tr.find('td[data-alpaca-container-item-name^=' + currRow + '_devicesByRoom_]').length;\n\n        $tr.find('td[data-alpaca-container-item-name^=' + currRow + '_devicesByRoom_]').each(function(i, v) {\n            $formGroup = $(v).find('select').closest('div');\n\n            if($formGroup.css('display') === 'none') {\n                hideTd.push($(v));\n            }\n        });\n\n        if(elCnt === hideTd.length) {\n            $.each(hideTd, function(i, td) {\n                if(i === 0) {\n                    td.show();\n                } else {\n                    td.hide();\n                }\n            });\n        } else {\n            $.each(hideTd, function(i, td) {\n                td.hide();\n            });\n        }\n    }\n\n    $tableRoom.on('click', 'button', function(event) {\n        var $this = $(this),\n            action = $this.attr('data-alpaca-array-actionbar-action'),\n            tableRows = $tableRoom.find('tbody tr').length,\n            $tr = $this.closest('tr');\n\n        switch(action) {\n            case 'add':\n                var addTimer = setInterval(function () {\n\n                    if ($tableRoom.find('tbody tr').length === tableRows +1 && $tr.next('tr')) {\n                        $tableRoom.find('tbody tr').each(function(i, v) {\n                            buildRow($(v));\n                        });\n                        if (addTimer) {\n                            clearInterval(addTimer);\n                        }\n                    }\n                }, 500);\n                break;\n            case 'remove':\n                $tr.remove();\n                if($tableRoom.find('tbody tr').length < 1) {\n                    $tableRoomHead.hide();\n                    $('.climateControlRoomSettings').find('button[data-alpaca-array-toolbar-action=add]').closest('div').show();\n                }\n                break;\n        }\n    });\n\n    $tableRoom.on('change', 'select', function(event) {\n        var $this = $(this),\n            $tr = $this.closest('tr');\n\n        if($this.attr('name').split('_')[3] === 'room') {\n            var currRow = $tr.attr('data-alpaca-field-name');\n            var roomId = $this.find('option:selected').val();\n            if(roomId != '') {\n                $tr.find('td[data-alpaca-container-item-name^=' + currRow + '_devicesByRoom_]').each(function (i, v) {\n                    if ($(v).attr('data-alpaca-container-item-name') === (currRow + '_devicesByRoom_' + roomId)) {\n                        $(v).show();\n                    } else {\n                        $(v).hide();\n                    }\n                });\n            } else {\n                buildRow($tr);\n            }\n        }\n    });\n};\n"
  },
  {
    "path": "modules/Heating/index.js",
    "content": "/*** Heating Z-Way HA module *******************************************\n\n Version: 1.3 stable\n (c) Z-Wave.Me, 2021\n -----------------------------------------------------------------------------\n Author:    Niels Roche <nir@zwave.eu>,\n            Martin Petzold <mp@zwave.eu>,\n            Michael Hensche <mh@zwave.eu>,\n            Karsten Reichel <kar@zwave.eu>,\n            Vitaliy Yurkin <aivs@z-wave.me>\n Description:\n This module creates a central heat control that can control all thermostats of a room\n by defining a temperature sensor and a target temperature.\n\n ******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Heating(id, controller) {\n    // Call superconstructor first (AutomationModule)\n    Heating.super_.call(this, id, controller);\n}\n\ninherits(Heating, AutomationModule);\n\n_module = Heating;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nHeating.prototype.prepareSchedule = function(rooms) {\n    var self = this,\n        schedule = [];\n    _.each(rooms, function(data, roomID) {\n\n        _.each(data.schedule, function(sc, day) {\n            _.each(sc, function(s) {\n                // is there already some schedule with same start && end && temp ? -> just add day to list\n                sched = _.filter(schedule, function(entry) {\n                    return entry.RoomID == roomID && entry.Starttime == s.stime && entry.Endtime == s.etime && entry.Temperature == s.temp;\n                });\n\n                if (!_.isEmpty(sched)) {\n                    sched[0].Weekday.push(day);\n                } else {\n                    // add schedule\n                    schedule.push({\n                        \"RoomID\": roomID,\n                        \"Room\": \"\",\n                        \"Weekday\": [day],\n                        \"Starttime\": s.stime,\n                        \"Endtime\": s.etime,\n                        \"Temperature\": s.temp\n                    });\n                }\n            });\n        });\n    });\n\n    return schedule;\n};\n\nHeating.prototype.init = function(config) {\n    Heating.super_.prototype.init.call(this, config);\n    var self = this;\n    self.fallbackOverTime = [];\n    //\"room\": _.findIndex(self.config.roomSettings,function(obj) {return obj === sc}),\n    this.newRooms = _.map(self.config.roomSettings, function(sc, roomId) {\n        return {\n            \"room\": roomId,\n            \"comfort\": sc.comfortTemp,\n            \"energySave\": sc.energySaveTemp,\n            \"frostProtection\": sc.frostProtectionTemp,\n            \"fallback\": sc.fallbackTemp,\n            \"mainSensor\": sc.sensorId\n        }\n    });\n    this.vDev = null;\n    this.alreadyChangedThermostats = [];\n    this.registerdSchedules = {};\n    this.alarmTimer = {};\n    this.fallbackThermostatSettings = {};\n    this.langFile = self.controller.loadModuleLang(\"Heating\");\n    this.schedule = self.prepareSchedule(self.config.roomSettings);\n    this.waitingTime = self.config.resetTime * 1000 * 60 * 60; // convert in hours\n    self.initFunctions();\n    this.createHouseControl();\n\n    this.pollReset = function() {\n        var now = Date.now();\n\n        //self.log(\"self.fallbackOverTime:\", self.fallbackOverTime, true);\n\n        Object.keys(self.resetList).forEach(function(resetEntry) {\n            var resetvDev = self.controller.devices.get(resetEntry);\n\n            if (!!resetvDev) {\n                //self.log(\"time diff:\", now - self.resetList[resetEntry]);\n                if (self.resetList[resetEntry] <= now) {\n                    // check if a fallback level exists\n                    entryExists = _.filter(self.fallbackOverTime, function(entry) {\n                        return entry.id === resetvDev.id;\n                    });\n\n                    // set new level if values are not equal\n                    if (entryExists[0] && (parseFloat(entryExists[0].temperature) !== resetvDev.get(\"metrics:level\"))) {\n                        // add thermostat to the module trigger array or change list\n                        if (self.alreadyChangedThermostats.indexOf(resetvDev.id) < 0) {\n                            self.alreadyChangedThermostats.push(resetvDev.id);\n                        }\n                        resetvDev.performCommand(\"exact\", {\n                            level: entryExists[0].temperature\n                        });\n\n                        delete self.resetList[resetEntry];\n                    }\n                }\n            }\n        });\n    }\n\n    this.controller.on(\"HeatingReset_\" + this.id + \".poll\", this.pollReset);\n    this.controller.emit(\"cron.addTask\", \"HeatingReset_\" + this.id + \".poll\", {\n        minute: null,\n        hour: null,\n        weekDay: null,\n        day: null,\n        month: null\n    });\n\n    this.triggerControl = function(vdev) {\n        var isThermostat = vdev.get('deviceType') === 'thermostat',\n            roomId = vdev.get('location');\n\n        if (isThermostat && roomId > 0) {\n\n            var state = self.config.roomSettings[roomId].state,\n                stateName = state + \"Temp\";\n            if (state === \"schedule\") {\n                var now = new Date(),\n                    today = (now.getDay()).toString(),\n                    minutesToday = (now.getHours() * 60) + now.getMinutes(),\n                    scheduleFound = false;\n\n                _.forEach(self.schedule, function(entry) {\n                    if (parseInt(entry.RoomID) === roomId) {\n                        var Starttime = entry.Starttime,\n                            Endtime = entry.Endtime,\n                            sHours = parseInt(Starttime.substr(0, 2), 10),\n                            sMinutes = parseInt(Starttime.substr(3, 2), 10),\n                            eHours = parseInt(Endtime.substr(0, 2), 10),\n                            eMinutes = parseInt(Endtime.substr(3, 2), 10),\n                            startMinutesToday = (sHours * 60) + sMinutes,\n                            endMinutesToday = (eHours * 60) + eMinutes === 0 ? 24*60 : (eHours * 60) + eMinutes,\n                            weekday = entry.Weekday;\n\n                        // If time in schedule range set schedule temperature\n                        if (weekday.indexOf(today) >= 0 && minutesToday >= startMinutesToday && minutesToday < endMinutesToday) {\n                            // Set temperature from schedule\n                            scheduleFound = true;\n                            self.performChangesOnThermostats(vdev, parseFloat(entry.Temperature));\n                        }\n                    }\n                });\n                // If schedule is not found set energySave\n                if (scheduleFound == false) {\n                    if (self.config.roomSettings[roomId].energySaveTemp !== undefined) self.performChangesOnThermostats(vdev, self.config.roomSettings[roomId].energySaveTemp);\n                }\n            }\n            else {\n                // Set temperature from state frostProtection/energySave/comfort\n                if (self.config.roomSettings[roomId][stateName] !== undefined) self.performChangesOnThermostats(vdev, self.config.roomSettings[roomId][stateName]);\n            }\n\n\n            var entryExists = _.filter(self.fallbackOverTime, function(entry) {\n                return entry.id === vdev.id;\n            })\n            if (entryExists[0]) {\n                entryExists[0].temperature = vdev.get('metrics:level');\n            } else {\n                self.fallbackOverTime.push({\n                    id: vdev.id,\n                    temperature: vdev.get('metrics:level')\n                });\n            }\n            //deregister thermostat\n            self.controller.devices.off(vdev.id, \"change:metrics:level\", self.sensorFunction);\n            //register thermostat\n            self.controller.devices.on(vdev.id, \"change:metrics:level\", self.sensorFunction);\n        }\n    }\n\n    this.controller.devices.on('created', this.triggerControl);\n\n    this.updateRoomsList = function(id) {\n        delete self.config.roomSettings[id];\n        self.saveConfig();\n        var newRooms = self.vDev.get('metrics:rooms').filter(function(el) { return parseInt(el.room) != id });\n        self.vDev.set('metrics:rooms', newRooms);\n    }\n\n    // update the list of rooms after deleting a room\n    this.controller.on('location.removed', this.updateRoomsList);\n};\n\nHeating.prototype.stop = function() {\n    var self = this;\n    self.newRooms.forEach(function(room) {\n        self.regTH('off', room.room);\n    });\n\n    var devID = \"Heating_\" + self.id;\n\n    self.vDev = null;\n\n    self.controller.devices.remove(devID);\n\n    for (var key in self.registerdSchedules) {\n        self.registerdSchedules[key].forEach(function(pollEntry) {\n            self.controller.emit(\"cron.removeTask\", pollEntry);\n            if (key === 'start') {\n                self.controller.off(pollEntry, self.pollByStart);\n            } else {\n                self.controller.off(pollEntry, self.pollByEnd);\n            }\n        });\n\n        // clean registry \n        self.registerdSchedules[key] = [];\n    }\n\n    this.controller.emit(\"cron.removeTask\", \"HeatingReset_\" + this.id + \".poll\");\n    this.controller.off(\"HeatingReset_\" + this.id + \".poll\", this.pollReset);\n    this.controller.devices.off('created', this.triggerControl);\n    this.controller.off('location.removed', this.updateRoomsList);\n\n    Heating.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nHeating.prototype.createHouseControl = function() {\n\n    // use vdevinfo if it exists\n    var self = this,\n        vdevEntry = this.controller.vdevInfo[\"Heating_\" + this.id] && this.controller.vdevInfo[\"Heating_\" + this.id].metrics ? this.controller.vdevInfo[\"Heating_\" + this.id].metrics : undefined;\n\n    this.pollByStart = function(filter) {\n        var pollIdentifier = this.event || filter,\n            identifierArr = pollIdentifier.split('.'),\n            locId = parseInt(identifierArr[1], 10),\n            schedulePreset = null,\n            thermostats = [],\n            metrRooms = [];\n\n        /*\n         * identifierArr[1] ... room name\n         * identifierArr[7] ... '-' separeated temperature\n         * \n         */\n\n        schedulePreset = identifierArr[7] !== 'poll' ? identifierArr[7].replace('-', '.') : null;\n\n        //get thermostats\n        thermostats = self.getThermostats(locId);\n\n        if (thermostats.length > 0) {\n\n            // create fallback values \n            self.createFallbackThermostatSettings(locId, thermostats);\n\n            if (self.vDev === null) {\n                self.vDev = self.controller.devices.get('Heating_' + self.id);\n            }\n\n            metrRooms = self.vDev.get('metrics:rooms');\n            // update value in widget\n            metrRooms.forEach(function(room) {\n                if (parseInt(room.room, 10) === locId) {\n\n                    // get modus temperature\n                    if (!!schedulePreset) {\n                        switch (schedulePreset) {\n                            case 'F':\n                                temp = parseFloat(room.frostProtection);;\n                                break;\n                            case 'E':\n                                temp = parseFloat(room.energySave);\n                                break;\n                            case 'C':\n                                temp = parseFloat(room.comfort);\n                                break;\n                            default:\n                                temp = parseFloat(schedulePreset);\n                        }\n                    }\n                    room.targetTemp = 't ~ ' + temp;\n                }\n            });\n\n            self.vDev.set('metrics:rooms', metrRooms);\n\n            thermostats.forEach(function(thermostat) {\n                self.performChangesOnThermostats(thermostat, temp);\n            });\n        }\n    };\n\n    this.pollByEnd = function() {\n        var pollIdentifier = this.event,\n            identifierArr = pollIdentifier.split('.'),\n            locId = parseInt(identifierArr[1], 10),\n            thermostats = [],\n            metrRooms = [];\n\n        // If the end time is equal to the start time do not run the end command\n        var isEndTimeEqualStartTime = false;\n        _.forEach(self.registerdSchedules['start'], function(scheduleStart) {\n            var scheduleStartArray = scheduleStart.split('.');\n            var scheduleEndArray = pollIdentifier.split('.');\n            if (scheduleStartArray[3] === scheduleEndArray[3] &&\n                scheduleStartArray[5] === scheduleEndArray[5] &&\n                scheduleStartArray[6] === scheduleEndArray[6]) {\n                isEndTimeEqualStartTime = true;\n            }\n        });\n        if (isEndTimeEqualStartTime) return;\n\n        /*\n         * identifierArr[1] ... room name\n         * identifierArr[7] ... '-' separeated temperature\n         * \n         */\n\n        //schedulePreset = identifierArr[7] !== 'poll'? identifierArr[7].replace('-', '.') : null;\n\n        //get thermostats\n        thermostats = self.getThermostats(locId);\n\n        if (thermostats.length > 0) {\n\n            metrRooms = self.vDev.get('metrics:rooms');\n            // get all rooms controlled by Heating app, and update them\n            // update value in widget\n            metrRooms.forEach(function(room) {\n                if (parseInt(room.room, 10) === locId) {\n                    if (room.fallback) {\n                        temp = room.fallback == 'F' ? parseFloat(room.frostProtection) : (room.fallback == 'C' ? parseFloat(room.comfort) : parseFloat(room.energySave));\n                    } else {\n                        temp = parseFloat(room.energySave);\n                    }\n\n                    room.targetTemp = temp;\n                }\n            });\n\n            self.vDev.set('metrics:rooms', metrRooms);\n\n            thermostats.forEach(function(thermostat) {\n                self.performChangesOnThermostats(thermostat, temp);\n            });\n        }\n    };\n\n    this.configureSchedules = function(roomId) {\n        var subString = 'Heating.' + roomId + '.',\n            tempSet = false;\n\n        if (typeof self.registerdSchedules['start'] === 'undefined' || typeof self.registerdSchedules['end'] === 'undefined') {\n            // Create listeners for each schedule of the each rooms\n            self.schedule.forEach(function(rSc, index) {\n                // check if there is a '1-3' string and create schedules for each day\n                if (_.isArray(rSc.Weekday) && rSc.Weekday.length > 0) {\n                    rSc.Weekday.forEach(function(day) {\n                        self.initializeSchedules(day, rSc, index);\n                    });\n                }\n            });\n        }\n\n\n        var scheduleFilter = self.registerdSchedules['start'].concat(self.registerdSchedules['end']);\n\n        scheduleFilter = scheduleFilter.filter(function(schedule) {\n            return ~schedule.indexOf(subString);\n        });\n\n        _.forEach(scheduleFilter, function(scheduleEntry) {\n            var scheduleItems = scheduleEntry.split('.'),\n                now = new Date(),\n                startStop = scheduleItems[4],\n                m = parseInt(scheduleItems[6], 10),\n                h = parseInt(scheduleItems[5], 10),\n                d = parseInt(scheduleItems[3], 10);\n\n\n            // At first remove, so that there are no duplicates\n            self.controller.emit(\"cron.removeTask\", scheduleEntry);\n            self.controller.emit(\"cron.addTask\", scheduleEntry, {\n                minute: m,\n                hour: h,\n                weekDay: d,\n                day: null,\n                month: null\n            });\n\n            if (startStop === 'start') {\n                self.controller.on(scheduleEntry, self.pollByStart);\n            } else if (startStop === 'end') {\n                self.controller.on(scheduleEntry, self.pollByEnd);\n            }\n\n            /*\n             * filter for start/end - by index of or substring 'Heating.1.0.2.'\n             * check if start <= n < end\n             * check logic\n             *\n             * */\n            if (now.getDay() === d) {\n                if (startStop === 'start') {\n                    var nowTs = now.getTime(),\n                        midnight = (new Date()).setHours(24, 0),\n                        startI = (new Date()).setHours(h, m),\n                        compareString = scheduleItems[0] + '.' + scheduleItems[1] + '.' + scheduleItems[2] + '.' + d,\n                        endI = getTime(scheduleFilter, compareString + '.end');\n\n                    // check if end is next day\n                    if ((!endI && startI) || (startI && endI && endI < startI)) {\n                        nextDay = d === 6 ? 0 : d + 1;\n                        newCS = scheduleItems[0] + '.' + scheduleItems[1] + '.' + scheduleItems[2] + '.' + nextDay;\n                        endI = getTime(scheduleFilter, newCS + '.end') + 86400000; // add 24h\n                    }\n                    if ((!startI && endI && nowTs < endI) ||\n                        (!endI && startI && startI <= midnight) || // if now is between start and end AND if end is on new day\n                        (startI && endI && startI <= nowTs && nowTs < endI)) { // if now is between start and end\n                        self.pollByStart(scheduleEntry);\n                        tempSet = true;\n                    }\n                }\n            }\n        });\n\n        return tempSet;\n    }\n\n    function getTime(filterArray, compareString) {\n        var time = 0,\n            filter = [];\n\n        filterArray.forEach(function(entry) {\n            if (entry.indexOf(compareString) > -1) {\n                filter = entry.split('.');\n                time = (new Date().setHours(parseInt(filter[5], 10), parseInt(filter[6], 10)));\n            }\n        });\n\n        return time;\n    }\n\n    self.vDev = self.controller.devices.create({\n        deviceId: \"Heating_\" + this.id,\n        defaults: {\n            deviceType: \"sensorMultiline\",\n            metrics: {\n                multilineType: \"climateControl\",\n                icon: \"climatecontrol\",\n                rooms: self.newRooms\n            }\n        },\n        overlay: {\n            metrics: {\n                multilineType: \"climateControl\",\n                title: self.getInstanceTitle(),\n                icon: \"climatecontrol\",\n                state: vdevEntry && vdevEntry.state ? vdevEntry.state : 'energySave',\n                rooms: self.newRooms\n            }\n        },\n        /*\n         * commands:\n         * comfort ... set comfort temperature\n         * energySave ... set energy saving temperature\n         * frostProtection ... set frost protection temperature\n         * schedule ... activate configured schedule\n         * custom ... (only on Heating vDev) activate custom configurations\n         */\n        handler: function(command, args) {\n            var argRoom = !args || args.room === \"null\" ? null : parseInt(args.room, 10),\n                roomCmd = command;\n\n            // do commands for each room entry\n            self.newRooms.forEach(function(room, index) {\n                var currTemp,\n                    roomId = parseInt(room.room, 10);\n                if (argRoom === null || argRoom === roomId) {\n\n                    // set custom configs if configured\n                    if (argRoom === null && command === 'custom') {\n                        roomCmd = room.state;\n                    }\n\n                    // Set state for room\n                    if (command !== 'custom') {\n                        self.config.roomSettings[roomId].state = command;\n                    }\n\n                    var thermostats = self.getThermostats(roomId);\n\n                    // set current temperature\n                    switch (roomCmd) {\n                        case 'comfort':\n                            currTemp = parseFloat(room.comfort);\n                            break;\n                        case 'energySave':\n                            currTemp = parseFloat(room.energySave);\n                            break;\n                        case 'frostProtection':\n                            currTemp = parseFloat(room.frostProtection);\n                            break;\n                        case 'schedule':\n                        default:\n                            currTemp = null;\n                    }\n\n                    // set thermostat temperature\n                    if (!!currTemp) {\n                        thermostats.forEach(function(device) {\n                            self.performChangesOnThermostats(device, currTemp);\n                        });\n\n                        // update room target temperature\n                        room.targetTemp = currTemp;\n                    }\n\n                    // activate schedule by room or if comfort mode for all rooms is choosen\n                    if ((argRoom === null && command === 'schedule') || (argRoom === null && command === 'custom' && roomCmd === 'schedule') || (!!argRoom && roomCmd === 'schedule')) {\n                        // activate schedule\n                        self.checkEntry(thermostats, room);\n                        if (!self.configureSchedules(roomId)) {\n                            currTemp = parseFloat(room.energySave);\n                            thermostats.forEach(function(device) {\n                                self.performChangesOnThermostats(device, currTemp);\n                            });\n\n                            // update room target temperature\n                            room.targetTemp = currTemp;\n                        }\n                    }\n\n                    // clean up schedules after revoking it by room or if a none 'comfort' mode for all rooms is choosen\n                    if ((argRoom === null && self.vDev.get('metrics:state') === 'schedule' && command !== 'schedule') || (!!argRoom && room.state === 'schedule' && roomCmd !== 'schedule')) {\n                        var subString = 'Heating.' + roomId + '.';\n\n                        // delete all thermostat fallback setting for this room\n                        if (self.fallbackThermostatSettings[roomId]) {\n                            delete self.fallbackThermostatSettings[roomId];\n                        }\n\n                        for (var startStop in self.registerdSchedules) {\n                            // search in registry for all regsitered schedules that should be removed from Cron\n                            var newScheduleRegistry = _.filter(self.registerdSchedules[startStop], function(schedule) {\n                                return ~schedule.indexOf(subString);\n                            });\n\n                            // clean up registered schedules\n                            self.registerdSchedules[startStop] = _.filter(self.registerdSchedules[startStop], function(schedule) {\n                                return !~schedule.indexOf(subString);\n                            });\n\n                            // remove schedules from Cron\n                            _.forEach(newScheduleRegistry, function(scheduleEntry) {\n                                self.controller.emit(\"cron.removeTask\", scheduleEntry);\n                                if (startStop === 'start') {\n                                    self.controller.off(scheduleEntry, self.pollByStart);\n                                } else if (startStop === 'end') {\n                                    self.controller.off(scheduleEntry, self.pollByEnd);\n                                }\n                            });\n                        }\n                    }\n\n                    room.state = roomCmd;\n                }\n            });\n\n            self.saveConfig();\n\n            if (!!argRoom) {\n                // set state to custom\n                this.set('metrics:state', 'custom');\n                this.set('metrics:icon', '/ZAutomation/api/v1/load/modulemedia/Heating/heating_custom.png');\n            } else {\n                this.set('metrics:state', command);\n                this.set('metrics:icon', command === 'custom' ? '/ZAutomation/api/v1/load/modulemedia/Heating/heating_custom.png' : 'climatecontrol');\n            }\n\n            this.set('metrics:rooms', self.newRooms);\n        },\n        moduleId: this.id\n    });\n\n    // handle room settings on instances start\n    self.newRooms.forEach(function(room, i) {\n        var roomId = parseInt(room.room, 10);\n\n        // check for the stored state\n        room.state = self.config.roomSettings[roomId].state;\n        room.energySave = parseFloat(room.energySave);\n        room.targetTemp = vdevEntry && vdevEntry.rooms[i] && vdevEntry.rooms[i].targetTemp ? parseFloat(vdevEntry.rooms[i].targetTemp) : parseFloat(room.comfort);\n\n        // activate schedule if exists\n        if (self.schedule) {\n            room.hasSchedule = _.findWhere(self.schedule, {\n                'RoomID': roomId.toString()\n            }) ? true : false;\n        } else {\n            room.hasSchedule = false;\n        }\n\n        if (room.state === 'schedule') {\n            // activate schedule\n            var thermostats = self.getThermostats(roomId);\n\n            // prepare schedule entries\n            self.checkEntry(thermostats, room);\n\n            // set and activate schedule entries for rooms\n            //self.configureSchedules(roomId);\n        }\n\n        //deregister reset\n        self.regTH('off', room.room);\n        //register reset\n        self.regTH('on', room.room);\n    });\n\n    self.vDev.performCommand(self.vDev.get('metrics:state'));\n};\n\nHeating.prototype.performChangesOnThermostats = function(thermostat, temp) {\n    var self = this;\n    var entryExists = _.filter(self.fallbackOverTime, function(entry) {\n        return entry.id === thermostat.id;\n    })\n    if (entryExists[0]) {\n        entryExists[0].temperature = temp;\n    } else {\n        self.fallbackOverTime.push({\n            id: thermostat.id,\n            temperature: temp\n        });\n    }\n\n    // add thermostat to the module trigger array or change list\n    if (self.alreadyChangedThermostats.indexOf(thermostat.id) < 0) {\n        self.alreadyChangedThermostats.push(thermostat.id);\n    }\n\n    // perform command on thermostat\n    thermostat.performCommand(\"exact\", {\"level\": temp});\n};\n\nHeating.prototype.initFunctions = function() {\n    var self = this;\n    self.resetList = {};\n\n    self.sensorFunction = function sensorFunction(idev) {\n        if (self.vDev) {\n            // ignore devices listed on reset list \n            if (self.alreadyChangedThermostats.indexOf(idev.id) < 0) {\n                self.resetList[idev.id] = Date.now() + self.waitingTime;\n                //self.log(\"Set reset time:\", self.resetList[idev.id]);\n\n                // remove thermostat from the module trigger array and reset reset timer if existing\n            } else {\n                if (self.alreadyChangedThermostats.indexOf(idev.id) > 0 && self.resetList[idev.id]) {\n                    delete self.resetList[idev.id];\n                }\n                self.alreadyChangedThermostats = _.filter(self.alreadyChangedThermostats, function(id) {\n                    return id !== idev.id;\n                });\n            }\n        }\n    }\n};\n\n/*\n * un/register thermostats for the reset\n */\nHeating.prototype.regTH = function(action, roomId) {\n    var self = this;\n    var roomId = parseInt(roomId, 10);\n    var thermostatsGL = this.getThermostats(roomId);\n\n    thermostatsGL.forEach(function(device) {\n        self.controller.devices[action](device.id, \"change:metrics:level\", self.sensorFunction);\n    });\n};\n\n/*\n * checks schedule data content\n * handles weekdays and checks for their validation\n */\nHeating.prototype.checkEntry = function(thermostats, room) {\n    var self = this;\n\n    if (_.isArray(thermostats) && thermostats.length > 0 &&\n        self.schedule && self.schedule.length > 0) {\n\n        var roomSchedules = self.schedule.filter(function(entry) {\n            return parseInt(entry.RoomID, 10) === parseInt(room.room, 10);\n        });\n\n        // create listeners for each schedule of the destinated room\n        roomSchedules.forEach(function(rSc, index) {\n            // check if there is a '1-3' string and create schedules for each day\n            if (_.isArray(rSc.Weekday) && rSc.Weekday.length > 0) {\n                rSc.Weekday.forEach(function(day) {\n                    self.initializeSchedules(day, rSc, index);\n                });\n            } else {\n                console.log(\"---  Heating_\" + self.id,self.langFile.err_wrong_date_format);\n            }\n        });\n\n    } else if (self.schedule && _.isArray(thermostats) && thermostats.length < 1) {\n        var thisRoom = self.controller.getLocation(self.controller.locations, room.room);\n        var roomName = thisRoom ? thisRoom.title : room.room;\n        console.log(\"---  Heating_\" + self.id,self.langFile.err_no_thermostats + roomName);\n    } else {\n        console.log(\"---  Heating_\" + self.id,self.langFile.err_parsing_schedule_data);\n    }\n};\n\n/* \n * checks validation of time input\n * and creates schedule identifiers for registry\n */\nHeating.prototype.initializeSchedules = function(day, rSc, index) {\n    var self = this,\n        transformHour = function(hour) {\n            return hour % 24;\n        },\n        startHour = transformHour(parseInt(rSc.Starttime.substring(0, 2), 10)),\n        startMinute = parseInt(rSc.Starttime.substring(3, 5), 10),\n        endHour = transformHour(parseInt(rSc.Endtime.substring(0, 2), 10)),\n        endMinute = parseInt(rSc.Endtime.substring(3, 5), 10),\n        start = 0,\n        end = 0,\n        newDay = (parseInt(day) + 1) % 7,\n        setStart = null,\n        setEnd = null,\n        tempOrModus = rSc.Temperature;\n\n    if (tempOrModus !== '') {\n        if (_.isNumber(tempOrModus) && (tempOrModus < 5 || tempOrModus > 29)) {\n            self.controller.addNotification('warning', self.langFile.err_temp_out_of_range, 'module', 'Heating');\n        } else {\n            setStart = tempOrModus.toString();\n            setEnd = null;\n        }\n    } else {\n        self.controller.addNotification('warning', self.langFile.err_temp_entry, 'module', 'Heating');\n    }\n\n    if ((startHour >= 0 && startHour < 24) && (endHour >= 0 && endHour < 24) && // check  0 >= hours < 24\n        (startMinute >= 0 && startMinute < 60) && (endMinute >= 0 && endMinute < 60)) { // check  0 >= min < 60\n        // check first if second time is on next day\n        if (startHour > endHour || (startHour === endHour && startMinute > endMinute)) {\n            // add cron start\n            self.createSchedule('start', startMinute, startHour, setStart, day, rSc.RoomID, index);\n\n            // add cron stop on next day\n            self.createSchedule('end', endMinute, endHour, setEnd, newDay, rSc.RoomID, index);\n\n        } else {\n            // add cron start\n            self.createSchedule('start', startMinute, startHour, setStart, day, rSc.RoomID, index);\n\n            // add cron end\n            self.createSchedule('end', endMinute, endHour, setEnd, day, rSc.RoomID, index);\n        }\n    } else if ((startHour < 0 && startHour > 24) && (endHour < 0 && endHour > 24) &&\n        (startMinute < 0 && startMinute > 60) && (endMinute < 0 && endMinute > 60)) {\n        console.log(\"---  Heating_\" + self.id,self.langFile.err_wrong_time_format);\n    } else {\n        console.log(\"---  Heating_\" + self.id,self.langFile.err_something_went_wrong);\n    }\n};\n\n/* \n * adds schedule identifier to registry\n * \n */\nHeating.prototype.createSchedule = function(startStop, min, hour, setTempOrModus, weekDay, roomId, scheduleIndex) {\n    var temperature = !!setTempOrModus ? \".\" + setTempOrModus.replace(/\\.|\\,/ig, '-') : '',\n        pollIdentifier = \"Heating.\" + roomId + \".\" + scheduleIndex + \".\" + weekDay + \".\" + startStop + \".\" + hour + \".\" + min + temperature + \".poll\";\n\n    if (!this.registerdSchedules[startStop]) {\n        this.registerdSchedules[startStop] = [];\n    }\n\n    // add identifier\n    if (!~this.registerdSchedules[startStop].indexOf(pollIdentifier)) {\n        this.registerdSchedules[startStop].push(pollIdentifier);\n    }\n};\n\n/* \n * necessary after ending schedule or interval\n * to restore all thermostats state\n */\nHeating.prototype.createFallbackThermostatSettings = function(roomId, thermostatArr) {\n    var self = this;\n\n\n    _.forEach(thermostatArr, function(thermostat) {\n        var thermostatEntry = {\n                id: thermostat.id,\n                level: thermostat.get('metrics:level')\n            },\n            entryExists = [];\n\n        // if empty create new\n        if (!self.fallbackThermostatSettings[roomId]) {\n            self.fallbackThermostatSettings[roomId] = [];\n\n            self.fallbackThermostatSettings[roomId].push(thermostatEntry);\n        }\n\n        // check if entry exists\n        entryExists = _.filter(self.fallbackThermostatSettings[roomId], function(entry) {\n            return entry.id === thermostatEntry.id;\n        });\n\n        if (entryExists < 1) {\n            // add new one\n            self.fallbackThermostatSettings[roomId].push(thermostatEntry);\n        } else if (entryExists[0]) {\n            // update thermostat level\n            if (!_.isEqual(entryExists[0]['level'], thermostatEntry['level'])) {\n                entryExists[0]['level'] = thermostatEntry['level'];\n            }\n        }\n    });\n};\n\n/* \n * filter for all thermostats\n * if surrendered also by room id\n */\nHeating.prototype.getThermostats = function(roomId) {\n    var self = this;\n    // tbf - rrom id should be always present, if not, there is some misconfiguration \n    if (roomId) {\n        return self.controller.devices.filter(function(device) {\n            return device.get(\"deviceType\") === \"thermostat\" &&\n                parseInt(device.get(\"location\"), 10) === roomId;\n        });\n    } else {\n        return self.controller.devices.filter(function(device) {\n            return device.get(\"deviceType\") === \"thermostat\";\n        });\n    }\n};\n\nHeating.prototype.log = function(message, value, stringify) {\n    var self = this;\n    if (stringify) {\n        console.log('##################################');\n        console.log('##');\n        console.log('##', message, JSON.stringify(value, null, 1));\n        console.log('##');\n        console.log('##################################');\n    } else {\n        console.log('##################################');\n        console.log('##');\n        console.log('##', message, value);\n        console.log('##');\n        console.log('##################################');\n    }\n};"
  },
  {
    "path": "modules/Heating/lang/de.json",
    "content": "{\n  \"C\": \"Komfort\",\n  \"E\": \"Energiespar\",\n  \"F\": \"Frostschutz\",\n  \"etimes\": \"Endzeit\",\n  \"friday_short\": \"Fr\",\n  \"h_resetTime\": \"in Stunden\",\n  \"l_table\": \"Raumeinstellungen\",\n  \"l_temperature_id\": \"Temperatur\",\n  \"l_times_id\": \"Zeitplan\",\n  \"m_comfort\": \"Komforttemp.\",\n  \"m_descr\": \"Die Heizungssteuerung ermöglicht die raumindividuelle Temperierung Ihres Heims.<br/><br/><h3>Konfiguration</h3><strong>Raum Einstellungen</strong><br/><ul><li>Fügen Sie die Räume hinzu, die von der Heizungssteuerung verwaltet werden sollen.</li><li>Pro Raum können Sie optional einen Temperatursensor auswählen, der später in der Übersicht aufgelistet werden soll.</li><li>Wählen Sie eine Komfort-Temperatur, die im Bereich zwischen 14 und 27 Grad liegt.</li><li>Wählen Sie eine Energiespar-Temperatur, welche im Energiesparmodus verwendet werden soll und die im Bereich zwischen 14 und 27 Grad liegt.</li><li>Abschließend wählen Sie eine Fallback-Temperatur, die verwendet wird, wenn die Anwendung gemäß dem Zeitplan arbeitet, aber für den aktuellen Zeitpunkt kein Eintrag vorhanden ist.</li><li>Verwenden Sie die Schaltfäche <i class='glyphicon glyphicon-plus-sign'></i> und <i class='glyphicon glyphicon-minus-sign'></i> um einen weiteren Eintrag hinzuzufügen bzw. einen bestehenden Eintrag zu löschen.</li></ul><strong>Zeitplan Einstellungen</strong><br/><ul><li>Wählen Sie einen der zuvor definierten Räume und selektieren Sie die Wochentage und die Zeitstpanne, die durch den Zeitplan abgedeckt werden soll.</li><li>Anschließend wählen Sie die gewünschte Temperatur, indem Sie einen Wert zwischen 14 und 27 Grad oder einen der Modi Frostschutz, Energiesparen oder Komfort wählen.</li><li>Verwenden Sie die Schaltfäche <i class='glyphicon glyphicon-plus-sign'></i> und <i class='glyphicon glyphicon-minus-sign'></i> um einen weiteren Eintrag hinzuzufügen bzw. einen bestehenden Eintrag zu löschen.</li><li>Über die Schaltfäche <i class='fa fa-clone'></i> haben Sie die Möglichkeit den aktuellen Eintrag zu duplizieren.</li><li><strong>Beachten Sie, dass eine fehlerhafte Konfiguration zu undefiniertem Verhalten führen kann.</strong></li></ul><strong>Erweiterte Einstellungen</strong><br/><ul><li>Setzen Sie weiterhin die automatische Rücksetzzeit, indem Sie einen ganzzahligen Stundenwert X eingeben. Werden im laufenden Betrieb Änderungen an einzelnen Thermostaten vorgenommen, so werden diese nach X Stunden automatisch rückgängig gemacht, so dass das System wieder konform mit der Steuerung durch diese Anwendung arbeitet.</li></ul><h3>Handhabung</h3>Die Anwendung generiert nach erfolgreicher Konfiguration ein eigenständiges Widget, welches die Steuerung der Heizungsmodi über vier Schaltfächen ermöglicht.<br/><img src='/ZAutomation/api/v1/load/modulemedia/ClimateControl/widget_de.png' style='display:block; margin: 0 auto;'></img><br/>Von links nach rechts haben die Schaltfächen die Funktionen Frostschutz|Energiesparen|Komfort|Zeitgesteuert.<br/>Über die Schaltfäche 'Räume' können Sie das Konfigurationsfenster mit der Auflistung der einzelnen Räume öffnen.<br/><img src='/ZAutomation/api/v1/load/modulemedia/ClimateControl/modal_de.png' style='display:block; margin: 0 auto;'></img><br/>Wenn für den Raum ein Temperatursensor festgelegt wurde, liefert Ihnen die Übersicht den aktuellen Temperaturwert. Weiterhin wird der aktuell eingestellte Temperaturwert gelistet. Über das Dropdown-Menü haben Sie die Möglichkeit einen der vier Modi pro Raum zu setzen. Das folgende Icon zeigt Ihnen, dass die benutzerspezifische Einstellung pro Raum aktiv ist:<br/><img src='/ZAutomation/api/v1/load/modulemedia/ClimateControl/widget_custom_de.png' style='display:block; margin: 0 auto;'></img>\",\n  \"m_energySave\": \"Energiespar-Temp.\",\n  \"m_fallback\": \"Fallback Temp.\",\n  \"m_mainSens\": \"Sensor\",\n  \"m_resetTime\": \"Automatisierte Rücksetzzeit\",\n  \"m_rooms\": \"Räume\",\n  \"m_setup\": \"Raumeinstellungen\",\n  \"m_title\": \"Heizungssteuerung\",\n  \"monday_short\": \"Mo\",\n  \"saturday_short\": \"Sa\",\n  \"select_room\": \"--- Raum auswählen ---\",\n  \"stimes\": \"Startzeit\",\n  \"sunday_short\": \"So\",\n  \"thursday_short\": \"Do\",\n  \"tuesday_short\": \"Di\",\n  \"wednesday_short\": \"Mi\",\n  \"err_wrong_time_format\": \"Falsches Zeitformat\",\n  \"err_something_went_wrong\": \"Interner Fehler\",\n  \"err_wrong_date_format\": \"Falsches Datumsformat\",\n  \"err_no_thermostats\": \"Keine Thermostate in Raum \",\n  \"err_parsing_schedule_data\": \"Interner Fehler während dem einlesen des Zeitplans\",\n  \"err_temp_out_of_range\": \"Temperatur außerhalb des gültigen Bereichs\",\n  \"err_temp_entry\": \"Fehlerhafter Temperatureintrag\"\n}"
  },
  {
    "path": "modules/Heating/lang/en.json",
    "content": "{\n  \"C\": \"Comfort\",\n  \"E\": \"Saving\",\n  \"F\": \"Frost Protect\",\n  \"etimes\": \"End Time\",\n  \"friday_short\": \"Fr\",\n  \"h_resetTime\": \"in hours\",\n  \"l_table\": \"Add Room Settings\",\n  \"l_temperature_id\": \"Temperature\",\n  \"l_times_id\": \"Schedule\",\n  \"m_comfort\": \"Comfort Temp.\",\n  \"m_descr\": \"This climate control allows controlling the temperature in the whole home based on individual room settings.<br/><br/><h3>Configuarion</h3><strong>Room Settings</strong><br/><ul><li>Add the rooms that should be managed by the heating control.</li><li>You can optionally select a temperature sensor for each room. It will be listed in the overview described later.</li><li>Choose a comfort temperature range between 14 and 27 degrees.</li><li>Optionally select a temperature to be used in energy saving mode. If you do not make an adjustment, the temperature is obtained from the already set global setting.</li><li>Finally, select a fallback temperature that is used when the application is working according to the schedule, but no entry exists for the current time.</li><li>Use the button <i class='glyphicon glyphicon-plus-sign'></i> and <i class='glyphicon glyphicon-minus-sign'></i> to add another entry or delete an existing entry.</li></ul><strong>Schedule Settings</strong><br/><ul><li>Select one of the previously defined rooms and select the day of the week and the time period to be covered by the schedule.</li><li>Then select the desired temperature by selecting a value between 14 and 27 degrees or one of the modes frost protection, energy saving or comfort.</li><li>Use the button <i class='glyphicon glyphicon-plus-sign'></i> and <i class='glyphicon glyphicon-minus-sign'></i> to add another entry or delete an existing entry.</li><li>The <i class='fa fa-clone'></i> button allows you to duplicate the current entry.</li><li><strong>Note that an incorrect configuration can lead to undefined behavior.</strong></li></ul><strong>Advanced Settings</strong><br/><ul><li>Set the automatic reset time by entering an integer value X. If changes are made to individual thermostats during application runtime, these are automatically reversed after X hours.</li></ul><br/><h3>Usage</h3>After successful configuration the application generates a separate widget, which allows the control of the heating modes via four buttons.<br/><img src='/ZAutomation/api/v1/load/modulemedia/ClimateControl/widget_en.png' style='display:block; margin: 0 auto;'></img><br/>From the left to the right the buttons have the functions Frost Protection | Energy saving | Comfort | Time controlled.<br/>Use the 'Rooms' button to open the configuration window with the list of the individual rooms.<br/><img src='/ZAutomation/api/v1/load/modulemedia/ClimateControl/modal_en.png' style='display:block; margin: 0 auto;'></img><br/>If a temperature sensor has been defined for the room, the overview gives you the current temperature value. The currently set temperature is also listed. From the drop-down menu, you have the option to set one of the four modes per room. The following icon will show you that the custom configuration per room is active:<br/><img src='/ZAutomation/api/v1/load/modulemedia/ClimateControl/widget_custom_en.png' style='display:block; margin: 0 auto;'></img>\",\n  \"m_energySave\": \"Saving Temp.\",\n  \"m_fallback\": \"Fallback Temp.\",\n  \"m_mainSens\": \"Temp. Sensor\",\n  \"m_resetTime\": \"Automation Resettime\",\n  \"m_rooms\": \"Room\",\n  \"m_setup\": \"Rooms\",\n  \"m_title\": \"Heating Control\",\n  \"monday_short\": \"Mo\",\n  \"saturday_short\": \"Sa\",\n  \"select_room\": \"--- Choose Room ---\",\n  \"stimes\": \"Start Time\",\n  \"sunday_short\": \"Su\",\n  \"thursday_short\": \"Th\",\n  \"tuesday_short\": \"Tu\",\n  \"wednesday_short\": \"We\",\n  \"err_wrong_time_format\": \"Wrong timeformat\",\n  \"err_something_went_wrong\": \"Internal Error\",\n  \"err_wrong_date_format\": \"Wrong dateformat\",\n  \"err_no_thermostats\": \"No thermostats found in room \",\n  \"err_parsing_schedule_data\": \"Internal Error while parsing schedule\",\n  \"err_temp_out_of_range\": \"Temperature out of range\",\n  \"err_temp_entry\": \"Invalid temperature entry\"\n}"
  },
  {
    "path": "modules/Heating/module.json",
    "content": "{\n  \"dependencies\": [\n    \"Cron\"\n  ],\n  \"singleton\": false,\n  \"category\": \"system\",\n  \"author\": \"Z-Wave.Me\",\n  \"homepage\": \"http://razberry.z-wave.me\",\n  \"icon\": \"icon.png\",\n  \"moduleName\": \"Heating\",\n  \"version\": \"1.2.1\",\n  \"maturity\": \"stable\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n  },\n  \"defaults\": {\n    \"title\": \"__m_title__\",\n    \"description\": \"__m_descr__\",\n    \"roomSettings\": {},\n    \"resetTime\": 2\n  },\n  \"schema\": {},\n  \"options\": {}\n}"
  },
  {
    "path": "modules/HomeKitGate/htdocs/js/postRender.js",
    "content": "function modulePostRender() {\r\n\tif ($(\"div[data-alpaca-field-name='pin']\").find('input').val() === \"\") {\r\n\t\t$(\"div[data-alpaca-field-name='pin']\").hide();\t\r\n\t}\t\r\n\telse {\r\n\t\t$(\"div[data-alpaca-field-name='pin']\").show();\t\t\r\n\t}\r\n};"
  },
  {
    "path": "modules/HomeKitGate/index.js",
    "content": "/*** HomeKitGate Z-Way HA module *******************************************\n \nVersion: 2.4\n(c) Z-Wave.Me, 2023\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Yurkin Vitaliy <aivs@z-wave.me>\nDescription:\n\tThis module announces Z-Way HA devices to HomeKit\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction HomeKitGate (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tHomeKitGate.super_.call(this, id, controller);\n};\n\ninherits(HomeKitGate, AutomationModule);\n\n_module = HomeKitGate;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nHomeKitGate.ControllerId = \"__RaZberry_Controller\";\n\nHomeKitGate.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tHomeKitGate.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\tvar rgbDevices = [];\n\tvar thermostats = [];\n\tvar lastSupportedThermostatMode = 1; // Default Heat\n\t\n\tif (!this.config.hkDevices) {\n\t\tthis.config.hkDevices = {};\n\t}\n\n\t// If hkDevicesArray doesn't contain an vDevId, then remove it from the hkDevices\n\tObject.keys(this.config.hkDevices).forEach(function(vDevId) {\n\t\tif (self.config.hkDevicesArray.indexOf(vDevId) == -1) {\n\t\t\tdelete self.config.hkDevices[vDevId];\n\t\t}\n\t});\n\tthis.saveConfig();\n\tupdateSkippedDevicesList();\n\n\t// define functions and helpers\n\tfunction onDeviceAddedCore(vDevT) {\n\t\tvar controller = this.controller;\n\t\t\n\t\t// defaults\n\t\tvDevT.title = vDevT.title || vDevT.id;\n\t\tvDevT.manufacturer = vDevT.manufacturer || \"Z-Wave.Me\";\n\t\tvDevT.product = vDevT.product || vDevT.deviceType;\n\t\tvDevT.firmwareRevision = vDevT.firmwareRevision || zwayVersion.release;\n\t\tvDevT.serialNumber = vDevT.serialNumber || vDevT.id;\n\n\t\t// Skip widgets\n\t\tif (vDevT.permanently_hidden || !(vDevT.visibility) || (vDevT.probeType === \"alarmSensor_general_purpose\") || (vDevT.probeType === \"thermostat_mode\") || vDevT.tags.indexOf(\"homekit-skip\") !== -1 || (vDevT.deviceType === \"thermostat\" && vDevT.id.indexOf(\"ZWayVDev\") === -1))\n\t\t\treturn;\n\n\t\t// Supported widgets\n\t\tif (!((vDevT.deviceType === \"switchBinary\") || (vDevT.deviceType === \"switchMultilevel\") || (vDevT.deviceType === \"sensorMultilevel\") ||\n\t\t   (vDevT.deviceType === \"sensorBinary\") || (vDevT.deviceType === \"doorlock\") || (vDevT.deviceType === \"switchRGBW\") || (vDevT.deviceType === \"thermostat\")))\n\t\t\treturn;\n\n\t\tvar m = self.addDevice(vDevT);\n\n\t\tvar accessory = m.$accessory;\n\t\t\n\t\tif (vDevT.deviceType === \"switchBinary\") {\n\t\t\t// skip thermostat mode\n\t\t\tif (vDevT.id.slice(-2) === \"64\") return;\n\n\t\t\tvar type = HomeKit.Services.Switch;\n\t\t\tif (vDevT.tags.indexOf(\"type-light\") !== -1) type = HomeKit.Services.Lightbulb;\n\t\t\tif (vDevT.tags.indexOf(\"type-fan\") !== -1) type = HomeKit.Services.Fan;\n\t\t\t\n\t\t\tvar service = accessory.addService(type, \"Binary Switch\");\n\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.On, \"bool\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && d.get(\"metrics:level\") === \"on\"; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) d.performCommand(value ? \"on\" : \"off\"); }\n\t\t\t});\n\t\t}\n\t\telse if (vDevT.deviceType === \"switchMultilevel\" && (vDevT.probeType !== \"motor\") ) {\n\t\t\t// skip if related to switchRGB\n\t\t\tvar nodeId = self.controller.devices.get(vDevT.id).get(\"nodeId\")\n\t\t\tvar match = rgbDevices.filter(function(el) { return el.id === nodeId; })[0];\n\t\t\tif (match) return;\n\n\t\t\tvar service = accessory.addService(HomeKit.Services.Lightbulb, \"Multilevel Switch\");\n\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\t\t\t// necessary\n\t\t\tm.binaryLevel = service.addCharacteristic(HomeKit.Characteristics.On, \"bool\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && d.get(\"metrics:level\") ? true : false; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) d.performCommand(value ? \"on\" : \"off\"); }\n\t\t\t});\n\n\t\t\t// optional\n\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.Brightness, \"int\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); if (!d) return 0; var value = parseInt(d.get(\"metrics:level\")); return value > 99 ? 99 : value || 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (d) d.performCommand(\"exact\", { level: value }); }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\t\t}\n\t\telse if (vDevT.deviceType === \"sensorMultilevel\") {\n\t\t\tvar service;\n\t\t\tif (vDevT.probeType === \"temperature\" || vDevT.scaleTitle === \"°C\"){\n\t\t\t\tservice = accessory.addService(HomeKit.Services.TemperatureSensor, \"Temperature\");\n\t\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.CurrentTemperature, \"float\",  {\n\t\t\t\t\tget: function() {\n\t\t\t\t\t\tvar d = controller.devices.get(vDevT.id);\n\t\t\t\t\t\tif (!d) return 0;\n\t\t\t\t\t\tvar temperature = parseFloat(d.get(\"metrics:level\"));\n\t\t\t\t\t\tif (temperature >= -999 && temperature <= 999) {\n\t\t\t\t\t\t\treturn temperature;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\treturn 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t}},\n\t\t\t\t\tundefined, {\"unit\":\"celsius\", \"maxValue\":999, \"minValue\":-999, \"minStep\":0.0001}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse if (vDevT.probeType === \"humidity\" || vDevT.scaleTitle === \"%\") {\n\t\t\t\tservice = accessory.addService(HomeKit.Services.HumiditySensor, \"Humidity\");\n\t\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.CurrentRelativeHumidity, \"float\",  {\n\t\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && parseFloat(d.get(\"metrics:level\")) || 0.0; }},\n\t\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":100, \"minValue\":0, \"minStep\":0.0001}\n\t\t\t\t);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tservice = accessory.addService(HomeKit.Services.LightSensor, \"LightSensor\");\n\t\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.CurrentAmbientLightLevel, \"float\",  {\n\t\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && parseFloat(d.get(\"metrics:level\")) || 0.0; }},\n\t\t\t\t\tundefined, {\"maxValue\":100000, \"minValue\":-100000, \"minStep\":0.0001}\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\t\t}\n\t\telse if (vDevT.deviceType === \"sensorBinary\") {\n\t\t\tvar service;\n\t\t\tif (vDevT.probeTitle === \"Motion\") {\n\t\t\t\tservice = accessory.addService(HomeKit.Services.MotionSensor, \"Motion Sensor\");\n\t\t\t\t// Contact Sensor Characteristic\n\t\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.MotionDetected, \"uint8\", {\n\t\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && d.get(\"metrics:level\") === \"on\"; }\n\t\t\t\t});\n\t\t\t}\n\t\t\telse {\n\t\t\t\tservice = accessory.addService(HomeKit.Services.ContactSensor, \"Binary Sensor\");\n\t\t\t\t// Contact Sensor Characteristic\n\t\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.ContactSensorState, \"uint8\", {\n\t\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && d.get(\"metrics:level\") === \"on\"; }\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Add Name\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\n\t\t\t//serviceContactSensor.addCharacteristic(HomeKit.Characteristics.StatusLowBattery, [\"pr\", \"ev\"], \"uint8\", \"Status Low Battery\", 0);\n\t\t}\n\t\telse if (vDevT.deviceType === \"doorlock\") {\n\t\t\tvar service = accessory.addService(HomeKit.Services.LockMechanism, \"Door Lock\");\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\t\t\tm.StateLevel = service.addCharacteristic(HomeKit.Characteristics.LockCurrentState, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return (!!d && d.get(\"metrics:level\") === \"close\") ? 1 : 0; }\n\t\t\t});\n\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.LockTargetState, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return (!!d && d.get(\"metrics:level\") === \"close\") ? 1 : 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (d) d.performCommand(value ? \"close\" : \"open\"); }\n\t\t\t});\n\t\t}\n\t\telse if (vDevT.deviceType === \"switchRGBW\") {\n\t\t\t// Don't create rgbw widgets without brightness\n\t\t\tvar brightnessDev = null;\n\t\t\tvar brightnessDevId;\n\t\t\tif (vDevT.id.indexOf(\"RGB\") === 0) {\n\t\t\t\t// RGB module\n\t\t\t\tvar redDevice = self.controller.instances.filter(function(instance){return instance.id == vDevT.id.substring(4)})[0].params.red;\n\t\t\t\tvar before = redDevice.indexOf(\"-\")+1;\n\t\t\t\tvar after = redDevice.indexOf(\"-\",redDevice.indexOf(\"-\")+1);\n\t\t\t\tbrightnessDevId = redDevice.substring(0, before) + \"1\" + redDevice.substring(after);\n\t\t\t\tbrightnessDev = self.controller.devices.get(brightnessDevId);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Z-Wave Device\n\t\t\t\tbrightnessDevId = vDevT.id.substring(0, vDevT.id.indexOf(\"-\",vDevT.id.indexOf(\"-\")+1)+1) + \"38\";\n\t\t\t\tbrightnessDev = self.controller.devices.get(brightnessDevId);\n\t\t\t}\n\t\t\tif (!brightnessDev) return;\n\n\t\t\tvar service = accessory.addService(HomeKit.Services.Lightbulb, \"Multilevel Switch\");\n\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\n\t\t\tself.onDeviceWipedOut(brightnessDevId);\n\n\t\t\tm.level = service.addCharacteristic(HomeKit.Characteristics.On, \"bool\", {\n\t\t\t\tget: function() { var d = controller.devices.get(brightnessDevId); return (!!d && d.get(\"metrics:level\")) ? true : false; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(brightnessDevId); if (!!d) d.performCommand(value ? \"on\" : \"off\"); }\n\t\t\t});\n\n\t\t\tm.hue = service.addCharacteristic(HomeKit.Characteristics.Hue, \"float\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && parseFloat(hsv(d).h) || 0.0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) exactColor(d, \"Hue\", value); }},\n\t\t\t\tundefined, {\"unit\":\"arcdegrees\", \"maxValue\":360, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\n\t\t\tm.saturation = service.addCharacteristic(HomeKit.Characteristics.Saturation, \"float\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && parseFloat(hsv(d).s) || 0.0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) exactColor(d, \"Saturation\", value); }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":100, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\n\t\t\tm.brightness = service.addCharacteristic(HomeKit.Characteristics.Brightness, \"int\", {\n\t\t\t\tget: function() { var d = controller.devices.get(brightnessDevId); if (!d) return 0; var value = d.get(\"metrics:level\"); return value > 99 ? 99 : value || 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) { exactColor(d, \"Brightness\", value); var b = controller.devices.get(brightnessDevId); if (!!b) b.performCommand(\"exact\", { level: value }); }}},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\n\t\t\t// dirty hack to handle in OnLevelChange, but not to create a HK accessory\n\t\t\tif (brightnessDev) {\n\t\t\t\tself.mapping[brightnessDev.id] = {\n\t\t\t\t\t$accessory: m.$accessory,\n\t\t\t\t\tlevel: m.level,\n\t\t\t\t\tbrightness: m.brightness\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\telse if (vDevT.deviceType === \"thermostat\") {\n\t\t\tvar service = accessory.addService(HomeKit.Services.Thermostat, \"Thermostat\");\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\n\t\t\tvar nodeId = self.controller.devices.get(vDevT.id).get(\"nodeId\")\n\t\t\t// If HK thermostat already generated, exit.\n\t\t\tvar match = thermostats.filter(function(el) { return el === nodeId; })[0];\n\t\t\t\n\t\t\tif (match) {\n\t\t\t\tself.onDeviceWipedOut(vDevT.id);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tthermostats.push(nodeId);\n\n\t\t\t// Get all thermostat modes\n\t\t\tvar thermostatModes = [1]; // For danfoss LC and Secure without ThermostatMode CC\n\t\t\tif (zway.devices[nodeId].ThermostatMode && zway.devices[nodeId].ThermostatMode.data.supported.value) {\n\t\t\t\tthermostatModes = Object.keys(zway.devices[nodeId].ThermostatMode.data).filter(function(mode) {return !isNaN(parseInt(mode))});\n\t\t\t}\n\n\t\t\t// Use in HK only Off, Cool, Heat, Auto\n\t\t\tvar supportedHKModes = [0,1,2,3];\n\t\t\tvar modes = [];\n\t\t\tsupportedHKModes.forEach(function(validMode) {\n\t\t\t\tthermostatModes.forEach(function(mode) {\n\t\t\t\t\tif (validMode == mode)\n\t\t\t\t\t\tmodes.push(validMode);\n\t\t\t\t\tif (validMode == 3 && mode == 10)\n\t\t\t\t\t\tmodes.push(validMode);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// Remove mode 3 (Auto) if exist\n\t\t\tvar modesWithOutAuto = modes.filter(function(mode) {return mode != 3});\n\n\t\t\tvar currentMaxMode = Math.max.apply(null, modesWithOutAuto);\n\t\t\tvar currentMinMode = Math.min.apply(null, modesWithOutAuto);\n\n\t\t\tvar targetMaxMode = Math.max.apply(null, modes);\n\t\t\tvar targetMinMode = Math.min.apply(null, modes);\n\n\t\t\tm.currentThermostatMode = service.addCharacteristic(HomeKit.Characteristics.CurrentHeatingCoolingState, \"uint8\",  {\n\t\t\t\tget: function() { return modesWithOutAuto.length > 1 ? getCurrentMode(nodeId) : modesWithOutAuto[0]; }},\n\t\t\t\tundefined, {\"valid-values\": modesWithOutAuto, \"maxValue\": currentMaxMode, \"minValue\": currentMinMode}\n\t\t\t);\n\n\t\t\tm.targetThermostatMode = service.addCharacteristic(HomeKit.Characteristics.TargetHeatingCoolingState, \"uint8\", {\n\t\t\t\tget: function() { return modesWithOutAuto.length > 1 ? getTargetMode(nodeId) : modesWithOutAuto[0];; },\n\t\t\t\tset: function(mode) { zway.devices[nodeId].ThermostatMode.Set(mode == 3 ? 10 : mode); }},\n\t\t\t\tundefined, {\"valid-values\": modes, \"maxValue\":targetMaxMode, \"minValue\":targetMinMode}\n\t\t\t);\n\n\t\t\tm.currentTemperature = service.addCharacteristic(HomeKit.Characteristics.CurrentTemperature, \"float\",  {\n\t\t\t\tget: function() { return getCurrentTemperature(nodeId); }},\n\t\t\t\tundefined, {\"unit\":\"celsius\", \"maxValue\":100, \"minValue\":0, \"minStep\":0.1}\n\t\t\t);\n\n\t\t\tm.targetTemperature = service.addCharacteristic(HomeKit.Characteristics.TargetTemperature, \"float\", {\n\t\t\t\tget: function() { return getTargetTemperature(nodeId); },\n\t\t\t\tset: function(temperature) {\n\t\t\t\t\tif (modesWithOutAuto.length > 1)\n\t\t\t\t\t\tzway.devices[nodeId].ThermostatMode.Set(lastSupportedThermostatMode == 3 ? 10 : lastSupportedThermostatMode);\n\t\t\t\t\telse \n\t\t\t\t\t\tlastSupportedThermostatMode = modesWithOutAuto[0];\n\t\t\t\t\tzway.devices[nodeId].ThermostatSetPoint.Set(lastSupportedThermostatMode, temperature);\n\t\t\t\t}},\n\t\t\t\tundefined, {\"unit\":\"celsius\", \"maxValue\":40, \"minValue\":5, \"minStep\":0.5}\n\t\t\t);\n\n\t\t\t// { 0:\"Celsius\", 1:\"Fahrenheit\" }\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.TemperatureDisplayUnits, \"uint8\", 0,\n\t\t\t\t[\"pr\", \"pw\", \"ev\"], {\"valid-values\":[0, 1], \"maxValue\":1, \"minValue\":0}\n\t\t\t);\n\t\t}\n\t\telse if (vDevT.probeType === \"motor\") {\n\t\t\tvar service = accessory.addService(HomeKit.Services.WindowCovering, \"Blind Control\");\n\t\t\tservice.addCharacteristic(HomeKit.Characteristics.Name, \"string\", vDevT.title);\n\n\t\t\tm.targetPosition = service.addCharacteristic(HomeKit.Characteristics.TargetPosition, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); if (!d) return 0; var value = parseInt(d.get(\"metrics:level\")); return value > 99 ? 99 : value || 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (d) d.performCommand(\"exact\", { level: value }); }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\t\t\tm.currentPosition = service.addCharacteristic(HomeKit.Characteristics.CurrentPosition, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); if (!d) return 0; var value = parseInt(d.get(\"metrics:level\")); return value > 99 ? 99 : value || 0; }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\t\t\tm.positionState = service.addCharacteristic(HomeKit.Characteristics.PositionState, \"uint8\", {\n\t\t\t\tget: function() { return 2; /* Stoped */ }},\n\t\t\t\tundefined, {\"valid-values\":[0, 1, 2], \"maxValue\":2, \"minValue\":0}\n\t\t\t);\n\n\t\t}\n\n\t\t// Battery Service add to all widgets If device is a battery powered\n\t\tvar nodeId = self.controller.devices.get(vDevT.id).get(\"nodeId\")\n\t\tvar\ttechnology = self.controller.devices.get(vDevT.id).get(\"technology\")\n\n\t\tif (technology === \"Z-Wave\" && zway.devices[nodeId].data.isListening.value === false) {\n\t\t\tvar batteryDeviceId = vDevT.id.substring(0, vDevT.id.lastIndexOf(\"_\")+1) + nodeId + \"-0-128\";\n\t\t\tvar batteryService = accessory.addService(HomeKit.Services.Battery, \"Battery\");\n\t\t\tm.batteryLevel = batteryService.addCharacteristic(HomeKit.Characteristics.BatteryLevel, \"uint8\",  {\n\t\t\t\tget: function() { var d = controller.devices.get(batteryDeviceId); return !!d && parseInt(d.get(\"metrics:level\")) || 0; }}, \n\t\t\t\tundefined, {\"maxValue\":100, \"minValue\":0, \"minStep\":1}\n\t\t\t\t);\n\t\t\tm.chargingState = batteryService.addCharacteristic(HomeKit.Characteristics.ChargingState, \"uint8\",  {\n\t\t\t\tget: function() { return 0; }},\n\t\t\t\tundefined, {\"maxValue\":2, \"minValue\":0, \"minStep\":1}\n\t\t\t\t);\n\t\t\tm.statusLowBattery = batteryService.addCharacteristic(HomeKit.Characteristics.StatusLowBattery, \"uint8\",  {\n\t\t\t\tget: function() { var d = controller.devices.get(batteryDeviceId); return !!d && parseInt(d.get(\"metrics:level\")) > 50 ? 0 : 1 || 0; }},\n\t\t\t\tundefined, {\"maxValue\":1, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\t\t}\n\t};\n\n\t/***************** THERMOSTAT HELPERS *****************/\n\tfunction getCurrentTemperature(nodeId) {\n\t\t// Find first CC SensorMultilevel in all instances\n\t\tvar ccSensorMultilevel;\n\t\tvar insts_keys = Object.keys(zway.devices[nodeId].instances);\n\t\tfor (var i = 0; i < insts_keys.length; i++) {\n\t\t\tif (zway.devices[nodeId].instances[parseInt(insts_keys[i])].SensorMultilevel) {\n\t\t\t\tccSensorMultilevel = zway.devices[nodeId].instances[parseInt(insts_keys[i])].SensorMultilevel;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif  (ccSensorMultilevel && ccSensorMultilevel.data[1] && ccSensorMultilevel.data[1].val && ccSensorMultilevel.data[1].val.value) {\n\t\t\treturn ccSensorMultilevel.data[1].val.value;\n\t\t}\n\t\telse {\n\t\t\tif (lastSupportedThermostatMode == 3){\n\t\t\t\tlastSupportedThermostatMode = 10;\n\t\t\t}\n\t\t\telse if (lastSupportedThermostatMode == 0) {\n\t\t\t\tlastSupportedThermostatMode = 1;\n\t\t\t}\n\t\t\treturn zway.devices[nodeId].ThermostatSetPoint.data[lastSupportedThermostatMode].val.value;\n\t\t}\n\t};\n\n\tfunction getTargetTemperature(nodeId) {\n\t\tvar targetTemperature;\n\t\tif (zway.devices[nodeId].ThermostatMode) {\n\t\t\tvar mode = zway.devices[nodeId].ThermostatMode.data.mode.value;\n\t\t\tif (mode == 1 || mode == 2 || mode == 3) {\n\t\t\t\ttargetTemperature = zway.devices[nodeId].ThermostatSetPoint.data[mode].val.value;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (lastSupportedThermostatMode == 0) {\n\t\t\t\t\ttargetTemperature = 10;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttargetTemperature = zway.devices[nodeId].ThermostatSetPoint.data[lastSupportedThermostatMode == 3 ? 10 : lastSupportedThermostatMode].val.value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (targetTemperature < 5)\n\t\t\t\ttargetTemperature = 5;\n\t\t\tif (targetTemperature > 40)\n\t\t\t\ttargetTemperature = 40;\n\t\t}\n\t\telse {\n\t\t\ttargetTemperature = zway.devices[nodeId].ThermostatSetPoint.data[1].val.value; // Danfoss LC\n\t\t}\n\n\t\treturn targetTemperature;\n\t};\n\n\tfunction getTargetMode(nodeId) {\n\t\tvar mode = zway.devices[nodeId].ThermostatMode.data.mode.value;\n\t\tif (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 10) {\n\t\t\tlastSupportedThermostatMode = mode == 10 ? 3 : mode; // Transform ZW Auto(10) mode to HK Auto(3) mode\n\t\t}\n\t\treturn lastSupportedThermostatMode;\n\t}\n\n\tfunction getCurrentMode(nodeId) {\n\t\tvar mode = zway.devices[nodeId].ThermostatMode.data.mode.value;\n\t\tif (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 10) {\n\t\t\tif (mode == 3 || mode == 10){\n\t\t\t\tlastSupportedThermostatMode = 1; // CurrentHeatingCoolingState not support Auto(10) mode, change it to Heat(1)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlastSupportedThermostatMode = mode;\n\t\t\t}\n\t\t}\n\t\treturn lastSupportedThermostatMode;\n\t}\n\n\t/***************** RGB HELPERS *****************/\n\tfunction exactColor(vDev, valueName, value) {\n\t\tvar match = rgbDevices.filter(function(el) { return el.id === vDev.id; })[0];\n\n\t\t// If vDev already in rgbDevices array, set propertie\n\t\tif (match) {\n\t\t\tif (valueName === \"Hue\") {\n\t\t\t\tmatch.hue = value;\n\t\t\t\tmatch.valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Saturation\") {\n\t\t\t\tmatch.saturation = value;\n\t\t\t\tmatch.valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Brightness\") {\n\t\t\t\tmatch.brightness = value;\n\t\t\t}\n\n\t\t\t// Wait 2 Characteristics: \"Hue, Saturation\" to exact color\n\t\t\tif (valueName !== \"Brightness\" && match.valueCount == 2) {\n\t\t\t\tmatch.valueCount = 0;\n\t\t\t\tvar colors = hsv2rgb({h:match.hue, s:match.saturation, v:match.brightness});\n\t\t\t\tvDev.performCommand(\"exact\", {red: colors.r, green: colors.g, blue: colors.b});\n\t\t\t}\n\t\t}\n\t\t// If vDev not in rgbDevices array, add vDev and set propertie\n\t\telse {\n\t\t\tvar last = (rgbDevices.push({\"id\":vDev.id, hue: 0, saturation: 0, brightness: 100, valueCount:0}) - 1);\n\t\t\tif (valueName === \"Hue\") {\n\t\t\t\trgbDevices[last].hue = value;\n\t\t\t\trgbDevices[last].valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Saturation\") {\n\t\t\t\trgbDevices[last].saturation = value;\n\t\t\t\trgbDevices[last].valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Brightness\") {\n\t\t\t\trgbDevices[last].brightness = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction hsv(vDev){\n\t\treturn rgb2hsv({r:vDev.get(\"metrics:color:r\"), g:vDev.get(\"metrics:color:g\"), b:vDev.get(\"metrics:color:b\")});\n\t}\n\n\tfunction hsv2rgb(obj) {\n\t\t// H: 0-360; S,V: 0-100; RGB: 0-255\n\t\tvar r, g, b;\n\t\tvar sfrac = obj.s / 100;\n\t\tvar vfrac = obj.v / 100;\n\n\t\tif(sfrac === 0){\n\t\t\tvar vbyte = Math.round(vfrac*255);\n\t\t\treturn { r: vbyte, g: vbyte, b: vbyte };\n\t\t}\n\n\t\tvar hdb60 = (obj.h % 360) / 60;\n\t\tvar sector = Math.floor(hdb60);\n\t\tvar fpart = hdb60 - sector;\n\t\tvar c = vfrac * (1 - sfrac);\n\t\tvar x1 = vfrac * (1 - sfrac * fpart);\n\t\tvar x2 = vfrac * (1 - sfrac * (1 - fpart));\n\t\tswitch(sector){\n\t\t\tcase 0:\n\t\t\t\tr = vfrac; g = x2;\tb = c;\t  break;\n\t\t\tcase 1:\n\t\t\t\tr = x1;\tg = vfrac; b = c;\t  break;\n\t\t\tcase 2:\n\t\t\t\tr = c;\t g = vfrac; b = x2;\t break;\n\t\t\tcase 3:\n\t\t\t\tr = c;\t g = x1;\tb = vfrac;  break;\n\t\t\tcase 4:\n\t\t\t\tr = x2;\tg = c;\t b = vfrac;  break;\n\t\t\tcase 5:\n\t\t\tdefault:\n\t\t\t\tr = vfrac; g = c;\t b = x1;\t break;\n\t\t}\n\n\t\treturn { \"r\": Math.round(255 * r), \"g\": Math.round(255 * g), \"b\": Math.round(255 * b) };\n\t}\n\n\tfunction rgb2hsv(obj) {\n\t\t// RGB: 0-255; H: 0-360, S,V: 0-100\n\t\tvar r = obj.r/255, g = obj.g/255, b = obj.b/255;\n\t\tvar max, min, d, h, s, v;\n\n\t\tmin = Math.min(r, Math.min(g, b));\n\t\tmax = Math.max(r, Math.max(g, b));\n\n\t\tif (min === max) {\n\t\t\t// shade of gray\n\t\t\treturn {h: 0, s: 0, v: r * 100};\n\t\t}\n\n\t\tvar d = (r === min) ? g - b : ((b === min) ? r - g : b - r);\n\t\th = (r === min) ? 3 : ((b === min) ? 1 : 5);\n\t\th = 60 * (h - d/(max - min));\n\t\ts = (max - min) / max;\n\t\tv = max;\n\t\treturn {\"h\": h, \"s\": s * 100, \"v\": v * 100};\n\t}\n\n\tfunction updateSkippedDevicesList() {\n\t\t// Add tag \"homekit-skip\" for all skipped devices from config\n\t\tself.config.skippedDevices.forEach(function(vDevId) {\n\t\t\tdelete self.config.hkDevices[vDevId];\n\t\t\tremoveFromHkDevicesArray(vDevId);\n\t\t\tvar vDev = self.controller.devices.get(vDevId);\n\t  \t\tif (vDev !== null && vDev.get(\"tags\").indexOf(\"homekit-skip\") === -1 ) {\n\t  \t\t\tvDev.addTag(\"homekit-skip\");\n\t  \t\t}\n\t\t});\n\t\tself.saveConfig();\n\n\t\t// Remove tag \"homekit-skip\" if device not in skipped list\n\t\tself.controller.devices.forEach(function(vDev) {\n\t\t\tif (vDev !== null \n\t\t\t\t&& vDev.get(\"tags\").indexOf(\"homekit-skip\") !== -1\n\t\t\t\t&& self.config.skippedDevices.indexOf(vDev.id) === -1) {\n\t  \t\t\t\tvDev.removeTag(\"homekit-skip\");\n\t  \t\t}\n\t\t});\n\t}\n\n\tfunction removeFromHkDevicesArray(vDevid) {\n\t\tvar index = self.config.hkDevicesArray.indexOf(vDevid);\n\t\tif  (index !== -1) {\n\t\t\tself.config.hkDevicesArray.splice(index, 1);\n\t\t}\n\t}\n\n\tthis.hkDeviceRemove = function (vDevId) {\n\t\tvar m = self.mapping[vDevId];\n\t\tif (m) {\n\t\t\tvar accessory = m.$accessory;\n\t\t\tif (accessory)\n\t\t\t\taccessory.remove();\n\t\t\t\n\t\t\tdelete self.mapping[vDevId];\n\t\t}\n\t}\n\n\tthis.onDeviceAdded = function (vDev) {\n\t   \tconsole.log(\"HK: added\", vDev.id);\n\t   \t\n\t\tonDeviceAddedCore(self.vDevToTemplate(vDev));\n\t\n\t\t// update device tree\n\t\tself.hk.update();\n\t}\n\t\n\tthis.onDeviceRemoved = function (vDev) {\n\t\tconsole.log(\"HK: removed\", vDev.id);\n\t\t\n\t\tvar m = self.mapping[vDev.id];\n\t\tif (m) {\n\t\t\tvar accessory = m.$accessory;\n\t\t\tself.hk.update(accessory.aid, m[\"reachable\"].iid);\n\t\t}\n\t}\n\t\n\tthis.onDeviceWipedOut = function (vDevId) {\n\t\tconsole.log(\"HK: wipe out\", vDevId);\n\t\t\n\t\tself.hkDeviceRemove(vDevId);\n\t\t\n\t\t// update device tree\n\t\tself.hk.update();\n\t}\n\t\n\tthis.onLevelChanged = function (vDev) {\n\t\tconsole.log(\"HK: updated\", vDev.id);\n\t\t\n\t\tvar m = self.mapping[vDev.id];\n\t\tif (!m) return;\n\t\t\n\t\tvar accessory = m.$accessory;\n\t\tif (!accessory) return;\n\t\t\n\t\tfor (var characteristicName in m) {\n\t\t\t// skip special names\n\t\t\tif (characteristicName[0] === \"$\") continue;\n\t\t\tself.hk.update(accessory.aid, m[characteristicName].iid);\n\t\t}\n\t}\n\n\tthis.onTagsChanged = function (vDev) {\n\t\t// Add tag \"homekit-skip\" to skipped Devices list in config and remove device from Homekit\n\t\tif (vDev.get(\"tags\").indexOf(\"homekit-skip\") !== -1 && self.config.skippedDevices.indexOf(vDev.id) === -1) {\n\t\t\tself.config.skippedDevices.push(vDev.id);\n\t\t\tdelete self.config.hkDevices[vDev.id];\n\t\t\tremoveFromHkDevicesArray(vDev.id);\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceWipedOut(vDev.id);\n\t  \t}\n\n\t  \t// Remove tag \"homekit-skip\" from skipped Devices list in config and add device to Homekit\n\t  \tif (vDev.get(\"tags\").indexOf(\"homekit-skip\") === -1 && self.config.skippedDevices.indexOf(vDev.id) !== -1) {\n\t  \t\tvar index = self.config.skippedDevices.indexOf(vDev.id);\n\t\t\tself.config.skippedDevices.splice(index, 1);\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceAdded(vDev);\n\t  \t}\n\t}\n\n\tthis.onPermanentlyHiddenChanged = function (vDev) {\n\t\t// Remove device from Homekit\n\t\tif (vDev.get(\"permanently_hidden\") === true) {\n\t\t\tdelete self.config.hkDevices[vDev.id];\n\t\t\tremoveFromHkDevicesArray(vDev.id);\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceWipedOut(vDev.id);\n\t\t}\n\n\t\t// Add device to Homekit\n\t\tif (vDev.get(\"permanently_hidden\") === false) {\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceAdded(vDev);\n\t\t}\n\n\t}\n\n\tvar pin = this.config.pin; // if undefined or empty, will be autogenerated\n\t\n\tthis.hk = new HomeKit(this.config.name, function(r) {\n\t\tif (r.method == \"GET\" && r.path == \"/accessories\") {\n\t\t\treturn this.accessories.serialize(r);\n\t\t} else if (r.method == \"PUT\" && r.path == \"/characteristics\" && r.data && r.data.characteristics) {\n\t\t\tr.data.characteristics.forEach(function (c) {\n\t\t\t\tif (typeof c.value !== \"undefined\") {\n\t\t\t\t\t// use c.aid, c.iid and c.value here\n\t\t\t\t\tvar characteristic = this.accessories.find(c.aid, c.iid);\n\t\t\t\t\tif (characteristic)\n\t\t\t\t\t\tcharacteristic.value = c.value;\n\n\t\t\t\t\t// update subscribers\n\t\t\t\t\tthis.update(c.aid, c.iid);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (typeof c.ev === \"boolean\") {\n\t\t\t\t\t// set event subscription state\n\t\t\t\t\tr.events(c.aid, c.iid, c.ev);\n\t\t\t\t}\n\t\t\t}, this);\n\t\t\treturn null; // 204\n\t\t} else if (r.method == \"GET\" && r.path.substring(0, 20) == \"/characteristics?id=\") {\n\t\t\t\n\t\t\tvar self = this;\n\t\t\t// Array of characteristics to update\n\t\t\tvar accessoriesCharacteristics = r.path.substring(20).split(',');\n\t\t\tvar characteristics = [];\n\t\t\taccessoriesCharacteristics.forEach(function(item, i, arr) {\n\t\t\t\tcharacteristicsItem = item.split('.').map(function(x) { return parseInt(x) });\n\t\t\t\tvar characteristic = self.accessories.find(characteristicsItem[0], characteristicsItem[1]);\n\t\t\t\tif (characteristic) {\n\t\t\t\t\tcharacteristics.push({ aid: characteristicsItem[0], iid: characteristicsItem[1], value: characteristic.value});\n\t\t\t\t}\n\t\t\t});\n\t\t\t\n\t\t\treturn {\"characteristics\": characteristics};\n\t\t\t\n\t\t} else if (r.path == \"/identify\") {\n\t\t\tconsole.log(this.name, \"PIN:\", this.pin);\n\t\t\tif (self.config.pin != this.pin) {\n\t\t\t\tself.config.pin = this.pin;\n\t\t\t\tself.saveConfig();\n\t\t\t}\n\t\t\tself.controller.addNotification(\"notification\", \"HomeKit PIN: \" + this.pin, \"module\", \"HomeKitGate\");\n\t\t}\n\t}, pin);\n\n\t// prepare the structure holders\n\t\n\tthis.hk.accessories = new HKAccessoryCollection(this.hk);\n\n\tthis.mapping = {}\n\n\t// load saved devices in case vDevs are not yet loaded to make sure HK always receives the full list of device\n\tthis.preloadDevices();\n\n\t// add main accessory\n\tvar razberryAccessory = this.addDevice({\n\t\tid: HomeKitGate.ControllerId,\n\t\ttitle: \"Z-Way\",\n\t\tmanufacturer: \"Z-Wave.Me\",\n\t\tproduct: \"RaZberry\",\n\t\tserialNumber: \"12345678\",\n\t\tfirmwareRevision: zwayVersion.release\n\t}).$accessory;\n\tvar razberryService = razberryAccessory.addService(HomeKit.Services.HAPProtocolInformation, \"RaZberry Service\");\n\trazberryService.addCharacteristic(HomeKit.Characteristics.State, \"uint8\" , 0, [\"pr\", \"ev\"], {\"maxValue\":1, \"minValue\":0, \"minStep\":1});\n\trazberryService.addCharacteristic(HomeKit.Characteristics.Version, \"string\", \"1.0\", [\"pr\", \"ev\"]);\n\trazberryService.addCharacteristic(HomeKit.Characteristics.ControlPoint, \"data\", \"\", [\"pr\", \"pw\", \"ev\"]);\n\n\t// add existing devices\n\tthis.controller.devices.each(function(d) { onDeviceAddedCore(self.vDevToTemplate(d)); });\n\t\n\t// listen for future device collection changes\n\tthis.controller.devices.on(\"created\", this.onDeviceAdded);\n\tthis.controller.devices.on(\"removed\", this.onDeviceRemoved);\n\tthis.controller.devices.on(\"wipedOut\", this.onDeviceWipedOut);\n\tthis.controller.devices.on(\"change:metrics:level\", this.onLevelChanged);\n\tthis.controller.devices.on(\"change:metrics:isFailed\", this.onLevelChanged);\n\tthis.controller.devices.on(\"change:tags\", this.onTagsChanged);\n\tthis.controller.devices.on(\"change:permanently_hidden\", this.onPermanentlyHiddenChanged);\n\t\n\t// update device tree\n\tthis.hk.update();\n\t\n\tconsole.log(\"HomeKit PIN:\", this.hk.pin);\n\tself.config.pin = this.hk.pin;\n\tthis.controller.addNotification(\"notification\", \"HomeKit PIN: \" + this.hk.pin, \"module\", \"HomeKitGate\");\n};\n\nHomeKitGate.prototype.stop = function () {\n\tHomeKitGate.super_.prototype.stop.call(this);\n\n\tthis.controller.devices.off(\"created\", this.onDeviceAdded);\n\tthis.controller.devices.off(\"removed\", this.onDeviceRemoved);\n\tthis.controller.devices.off(\"wipedOut\", this.onDeviceWipedOut);\n\tthis.controller.devices.off(\"change:metrics:level\", this.onLevelChanged);\n\tthis.controller.devices.off(\"change:metrics:isFailed\", this.onLevelChanged);\n\tthis.controller.devices.off(\"change:tags\", this.onTagsChanged);\n\tthis.controller.devices.off(\"change:permanently_hidden\", this.onPermanentlyHiddenChanged);\n\n\n\tif (this.hk) {\n\t\tthis.hk.stop();\n\t}\n\t\n\tdelete this.mapping;\n\tdelete this.onDeviceAdded;\n\tdelete this.onDeviceRemoved;\n\tdelete this.onDeviceWipedOut;\n\tdelete this.onLevelChanged;\n\tdelete this.onTagsChanged;\n\tdelete this.onPermanentlyHiddenChanged;\n};\n\n\nHomeKitGate.prototype.addDevice = function(vDevT) {\n\tvar self = this;\n\t\n\t// clean old structure if any\n\tthis.hkDeviceRemove(vDevT.id);\n\t\n\tvar m = this.mapping[vDevT.id] = {};\n\t\n\tif (!_.isEqual(_.omit(this.config.hkDevices[vDevT.id], \"aid\"), _.omit(vDevT, \"aid\"))) {\n\t\tvar aid = (this.config.hkDevices[vDevT.id] && this.config.hkDevices[vDevT.id].aid) || (1 + Math.max(0, Math.max.apply(null, Object.keys(this.config.hkDevices).map(function(k) { return self.config.hkDevices[k].aid; }))));\n\t\tthis.config.hkDevices[vDevT.id] = vDevT;\n\t\tif (this.config.hkDevicesArray.indexOf(vDevT.id) == -1)\n\t\t\tthis.config.hkDevicesArray.push(vDevT.id);\n\t\tthis.config.hkDevices[vDevT.id].aid = aid;\n\t\tthis.saveConfig();\n\t}\n\t\n\tvar aid = this.config.hkDevices[vDevT.id].aid;\n\t\n\tvar accessory = m.$accessory = this.hk.accessories.addAccessory(vDevT.title, vDevT.manufacturer, vDevT.product, vDevT.serialNumber, vDevT.firmwareRevision, aid);\n\t\n\t// add Bridging State Service to all Accessories\n\tvar service = accessory.addService(HomeKit.Services.BridgingState, \"BridgingState\");\n\tservice.addCharacteristic(HomeKit.Characteristics.LinkQuality, \"uint8\", 1, [\"pr\", \"ev\"], {\"maxValue\":4, \"minValue\":1, \"minStep\":1});\n\tservice.addCharacteristic(HomeKit.Characteristics.AccessoryIdentifier, \"string\", HomeKitGate.generateUUID());\n\tservice.addCharacteristic(HomeKit.Characteristics.Category, \"uint16\", 1, [\"pr\", \"ev\"], {\"maxValue\":16, \"minValue\":1, \"minStep\":1});\n\tm.reachable = service.addCharacteristic(HomeKit.Characteristics.Reachable, \"bool\", vDevT.id === HomeKitGate.ControllerId ? true : {\n\t\tget: function() { var d = self.controller.devices.get(vDevT.id); return !!d && !d.get(\"metrics:isFailed\"); }\n\t}, [\"pr\", \"ev\"]);\n\t\n\treturn m;\n};\n\nHomeKitGate.prototype.preloadDevices = function() {\n\tvar self = this;\n\t\n\tObject.keys(this.config.hkDevices).forEach(function(vDevId) {\n\t\tself.addDevice(self.config.hkDevices[vDevId]);\n\t});\n};\n\nHomeKitGate.prototype.vDevToTemplate = function(vDev) {\n\treturn {\n\t\tid: vDev.id,\n\t\tdeviceType: vDev.get(\"deviceType\"),\n\t\tprobeType: vDev.get(\"probeType\"),\n\t\ttags: vDev.get(\"tags\"),\n\t\tpermanently_hidden: vDev.get('permanently_hidden'),\n\t\tvisibility: vDev.get('visibility'),\n\t\ttitle: vDev.get(\"metrics:title\"),\n\t\tscaleTitle: vDev.get(\"metrics:scaleTitle\"),\n\t\tprobeTitle: vDev.get(\"metrics:probeTitle\"),\n\t\tmanufacturer: vDev.get(\"manufacturer\"),\n\t\tproduct: vDev.get(\"product\"),\n\t\tfirmwareRevision: vDev.get(\"firmware\"),\n\t\tserialNumber: undefined\n\t};\n};\n\n// Static methods\n\nHomeKitGate.generateUUID = function () {\n\treturn 'xxxxxxxx-xxxx-xxxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {\n\t\tvar r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);\n\t\treturn v.toString(16);\n\t});\n}\n"
  },
  {
    "path": "modules/HomeKitGate/lang/de.json",
    "content": "{\n\t\"m_title\":\"Apple HomeKit Gateway\",\n\t\"m_descr\":\"Fügt alle im Z-Way verfügbaren Widgets zum Apple HomeKit hinzu.<br><br>If you don't want to export some device in HomeKit, add <i>homekit-skip</i> tag to that device. Make a switch look like a bulb: add tag <i>type-light</i>, for fun: <i>type-fun</i>.<br><br>NB! Works only with Z-Way v3.0.0 and upper.\",\n\t\"l_options\":\"Name, wie er in iOS Geräten angezeigt werden soll:\",\n\t\"l_pin\":\"Apple Homekit Pin\",\n\t\"l_skipped_devices\":\"Devices that don't need to be displayed in HomeKit\",\n\t\"h_skipped_devices\":\"<b>homekit-skip</b> tag will be added to each selected device.\",\n\t\"l_hkDevicesArray\": \"Devices exported to Apple HomeKit (autogenerated)\"\n}"
  },
  {
    "path": "modules/HomeKitGate/lang/en.json",
    "content": "{\n\t\"m_title\":\"Apple HomeKit Gate\",\n\t\"m_descr\":\"The Apple HomeKit protocol allows controlling HomeKit compatible devices from Apple iOS devices (iPhone, iPad). Activating this option your Z-Way gateway will be recognized as a HomeKit Bridge. All Z-Wave switches, dimmer etc. are mapped into the HomeKit world and can be controlled using third party HomeKit apps on the given platforms as well as in the native iOS Home app.<br><br>If you don't want to export some device in HomeKit, add <i>homekit-skip</i> tag to that device. Make a switch look like a bulb: add tag <i>type-light</i>, for fun: <i>type-fun</i>.<br><br>NB! Works only with Z-Way v3.0.0 and upper.\",\n\t\"l_options\":\"Name as it appears in iOS devices\",\n\t\"l_pin\":\"Apple Homekit Pin\",\n\t\"l_skipped_devices\":\"Devices that don't need to be displayed in HomeKit\",\n\t\"h_skipped_devices\":\"<b>homekit-skip</b> tag will be added to each selected device.\",\n\t\"l_hkDevicesArray\": \"Devices exported to Apple HomeKit (autogenerated)\"\n}"
  },
  {
    "path": "modules/HomeKitGate/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Apple HomeKit Шлюз\",\n\t\"m_descr\":\"Интеграция с приложением Дом от Apple (HomeKit) позволяет управлять устройвами с устройств iOS (iPhone и iPad). <br><br>Чтобы не выгружать устройство в HomeKit добавьте ему тег <i>homekit-skip</i>. Чтобы реле отображалось как лампа, добавьте тег <i>type-light</i>, вентилятор: <i>type-fun</i>. <br><br>Важно! Работает только с Z-Way v3.0.0 и выше.\",\n\t\"l_options\":\"Имя которое будет отображаться при поиске на iOS устройстве\",\n\t\"l_pin\":\"Пин-код HomeKit\",\n\t\"l_skipped_devices\":\"Устройства, которые не нужно отображать в HomeKit\",\n\t\"h_skipped_devices\":\"<b>homekit-skip</b> тэг будет добавлен каждому выбранному устройству.\",\n\t\"l_hkDevicesArray\": \"Устройства, экспортированные в HomeKit (заполняется автоматически)\"\n}"
  },
  {
    "path": "modules/HomeKitGate/module.json",
    "content": "{\n    \"singleton\": true,\n    \"dependencies\": [],\n    \"category\": \"support_external_ui\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://razberry.z-wave.me\",\n    \"icon\": \"icon.png\",\n    \"moduleName\": \"HomeKitGate\",\n    \"version\": \"2.4\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"name\": \"RaZberry\",\n        \"pin\": \"\",\n        \"hkDevicesArray\": [],\n        \"skippedDevices\": []\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"name\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"pin\": {\n                \"type\": \"string\",\n                \"readonly\": true\n            },\n            \"skippedDevices\": {\n                \"type\": \"array\",\n                \"field\": \"enum\",\n                \"datasource\": \"namespaces\",\n                \"enum\": \"namespaces:devices_all:deviceId\",\n                \"required\": false\n            },\n            \"hkDevicesArray\" : {\n                \"type\": \"array\",\n                \"items\": {\n                    \"type\": \"string\",\n                    \"required\": false\n                }\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"name\": {\n                \"label\": \"__l_options__\"\n            },\n            \"pin\": {\n                \"label\": \"__l_pin__\"\n            },\n            \"skippedDevices\": {\n                \"label\": \"__l_skipped_devices__\",\n                \"helper\": \"__h_skipped_devices__\",\n                \"type\": \"checkbox\",\n                \"datasource\": \"namespaces\",\n                \"field\": \"optionLabels\",\n                \"optionLabels\": \"namespaces:devices_all:deviceName\"\n            },\n            \"hkDevicesArray\": {\n                \"label\": \"__l_hkDevicesArray__\",\n                \"fields\": {\n                    \"item\": {\n                        \"type\": \"text\",\n                        \"readonly\": true\n                    }\n                }\n            }\n        }\n    },\n    \"postRender\": \"loadFunction:postRender.js\"\n}\n"
  },
  {
    "path": "modules/IfThen/index.js",
    "content": "/*** IfThen Z-Way HA module *******************************************\n\nVersion: 2.6.0\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>\nAuthor: Hans-Christian Göckeritz <hcg@zwave.eu>\nAuthor: Karsten Reichel <kar@zwave.eu>\nAuthor: Serguei Poltorak <ps@z-wave.me>\nDescription:\n\tBind actions on one device to other devices or scenes\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction IfThen (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tIfThen.super_.call(this, id, controller);\n}\n\ninherits(IfThen, AutomationModule);\n\n_module = IfThen;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nIfThen.prototype.init = function (config) {\n\tIfThen.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tifElement = self.config.sourceDevice[self.config.sourceDevice.filterIf];\n\tthis.handlerLevel = function (sDev) {\n\t\tvar that = self,\n\t\t\toperator = ifElement.operator,\n\t\t\tifLevel = (ifElement.status === 'level' && ifElement.level) || (!ifElement.status && ifElement.level) ? ifElement.level : ifElement.status,\n\t\t\tcheck = false,\n\t\t\tvalue = sDev.get(\"metrics:level\");\n\n\t\tif (operator && ifLevel) {\n\t\t\tswitch (operator) {\n\t\t\t\tcase '>':\n\t\t\t\t\tcheck = value > ifLevel;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '=':\n\t\t\t\t\tcheck = value === ifLevel;\n\t\t\t\t\tbreak;\n\t\t\t\tcase '<':\n\t\t\t\t\tcheck = value < ifLevel;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t\n\t\t// handle 0 and 99 for dimmers as off/on\n\t\tif (value === 99 && ifLevel === \"on\") value = \"on\";\n\t\tif (value === 0 && ifLevel === \"off\") value = \"off\";\n\t\t\n\t\tif(check || value === ifLevel || sDev.get('deviceType') === 'toggleButton'){\n\t\t\tself.config.targets.forEach(function(el) {\n\t\t\t\tvar type = el.filterThen;\n\t\t\t\t\n\t\t\t\tvar id = el[type].target,\n\t\t\t\t\tlvl = el[type].status === 'level' && typeof el[type].level === 'number' ? el[type].level : (el[type].status === 'color' && el[type].color? el[type].color: el[type].status),\n\t\t\t\t\tvDev = that.controller.devices.get(id),\n\t\t\t\t\t// compare old and new level to avoid unneccessary updates\n\t\t\t\t\tcompareValues = function(valOld,valNew){\n\t\t\t\t\t\tvar vO = _.isNaN(parseFloat(valOld))? valOld : parseFloat(valOld),\n\t\t\t\t\t\t    vN = _.isNaN(parseFloat(valNew))? valNew : parseFloat(valNew);\n\t\t\t\t\t\t\n\t\t\t\t\t\treturn vO !== vN;\n\t\t\t\t\t},\n\t\t\t\t\tset = compareValues(vDev.get(\"metrics:level\"), lvl);\n\t\t\t\t\n\t\t\t\t//if (vDev && set) {\n\t\t\t\tif (vDev && (!el[type].sendAction || (el[type].sendAction && set))) {\n\t\t\t\t\tif (vDev.get(\"deviceType\") === type && (type === \"switchMultilevel\" || type === \"thermostat\" || type === \"switchRGBW\")) {\n\t\t\t\t\t\tif (lvl === 'on' || lvl === 'off'){\n\t\t\t\t\t\t\tvDev.performCommand(lvl);\n\t\t\t\t\t\t} else if (typeof lvl === 'object') {\n\t\t\t\t\t\t\tvDev.performCommand(\"exact\", lvl);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvDev.performCommand(\"exact\", { level: lvl });\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (vDev.get(\"deviceType\") === \"toggleButton\" && type === \"scene\") {\n\t\t\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t\t\t} else if (vDev.get(\"deviceType\") === type) {\n\t\t\t\t\t\tvDev.performCommand(lvl);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// Setup metric update event listener\n\tif(ifElement && ifElement.device){\n\t\tself.controller.devices.on(ifElement.device, 'change:metrics:level', self.handlerLevel);\n\t}\n};\n\nIfThen.prototype.stop = function () {\n\tvar self = this;\n\t\n\t// remove event listener\n\tself.controller.devices.off(self.config.sourceDevice[self.config.sourceDevice.filterIf].device,'change:metrics:level', self.handlerLevel);\n\n\tIfThen.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/IfThen/lang/de.json",
    "content": "{\n\t\"m_title\":\"Wenn -> Dann\",\n\t\"m_descr\":\"Ein oder mehrere Geräte werden immer DANN geschaltet, WENN ein gewähltes Ereignis eingetreten ist. Dieses Ereignis kann das Auslösen eines Bewegungsmelders oder Türkontaktes sein aber auch das Umschalten eines anderen Schaltaktors.\",\n\t\"l_event_sources\":\"Wenn\",\n\t\"l_actors\":\"Dann\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_level\":\"Level\",\n\t\"level\": \"Setze Level\",\n\t\"open\":\"Öffnen\",\n\t\"close\":\"Schließen\",\n\t\"l_scene\":\"Szene order Benachrichtigung\",\n\t\"switchBinary\":\"Binärschalter\",\n\t\"switchMultilevel\":\"Multilevelschalter\",\n\t\"sensorMultilevel\":\"Multilevelsensor\",\n\t\"doorlock\":\"Türschloss\",\n\t\"thermostat\":\"Thermostat\",\n\t\"l_filter\":\"Filtern nach Typ\",\n\t\"l_target_device\":\"Gerät\",\n\t\"l_action\":\"Aktion\",\n\t\"toggleButton\": \"Schaltsteuerung / Szene (nur An)\",\n\t\"switchControl\": \"Schaltsteuerung (An/Aus/Level)\",\n\t\"sensorBinary\": \"Binärsensor\",\n\t\"l_choose\":\"--- Gerätetyp wählen ---\",\n\t\"l_choose_dev\":\"--- Gerät wählen ---\",\n\t\"l_choose_controller_action\":\"--- Interaktion wählen ---\",\n\t\"l_controller_action\":\"Interaktionen\",\n\t\"h_controller_action\":\"Die Aktion wird als zweistelliger Wert angegeben: Die erste Zahl ist die Nummer des Tasters/der Szene, die zweite Zahl stellt die Aktion des Tasters/der Szene dar (0 = kurz gedrückt, 1 = losgelassen, 2 = gehalten, 3 = 2x kurz gedrückt, 4 = 3x kurz gedrückt, usw. Besispiele: Doppelklick Taste/Szene 2 => 23, Einfachklick Taste/Szene 1 = 10)\",\n\t\"sensorDiscrete\":\"Szenensteuerung\",\n\t\"switchRGBW\":\"Farbsteuerung\",\n\t\"l_red\":\"Rot\",\n\t\"l_green\":\"Grün\",\n\t\"l_blue\":\"Blau\",\n\t\"colors\":\"Farben\",\n\t\"h_color\":\"Wählen Sie einen Wert von 0 - 255\",\n\t\"l_sendAction\":\"Sende kein 'An' Kommando, wenn das Gerät bereits aktiviert ist. Das Gleiche gilt für 'Aus'.\",\n\t\"h_sendAction\":\"Verhindert überflüssige Befehle im Netzwerk.\"\n}"
  },
  {
    "path": "modules/IfThen/lang/en.json",
    "content": "{\n\t\"m_title\":\"If -> Then\",\n\t\"m_descr\":\"The If->Then is the foundation of automation. A selected action (WHEN) is executed automatically at the moment when a certain event (IF) has happen. This app allows defining these relationships.  The (IF) event must be a event that happens at one time. Examples for this are a door that is opened (the door sensor trips) or a button that is pressed. A simple switch is also a reasonable source for an event because this switch can be switched. A temperature sensor is NO event in this regard because this sensor will continuously send temperature and not create an event. The event need to have two defines status of ‘0’ and ‘1’ Every binary sensor or switch button has these states. Status=1 will send a Command Set(1) to the list of selected actuators, Status=0 will sen Set(0) to these devices.<br> <br>Settings:<br> <ul><li>Pick the events that shall trigger. You can select multiple events and all of them will trigger the selected action (connected with Logical OR). If you pick a dimmer or a motor control the change to full 100 % will be considered as the event to trigger.</li> <li>Pick the devices that shall be switches depending on the action. Please not that these devices must be able to receive and execute Set(1) and set(0) commands.</li></ul>\",\n\t\"l_event_sources\":\"If\",\n\t\"l_actors\":\"Then\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_level\":\"Level\",\n\t\"level\": \"Set Level\",\n\t\"open\":\"Open\",\n\t\"close\":\"Close\",\n\t\"l_scene\":\"Scene or notification\",\n\t\"l_filter\":\"Filter by Type\",\n\t\"switchBinary\":\"Binary Switch\",\n\t\"switchMultilevel\":\"Multilevel Switch\",\n\t\"sensorMultilevel\":\"Multilevel Sensor\",\n\t\"doorlock\":\"Doorlock\",\n\t\"thermostat\":\"Thermostat\",\n\t\"l_target_device\":\"Device\",\n\t\"l_action\":\"Action\",\n\t\"toggleButton\": \"Switch Control / Scene (On only)\",\n\t\"switchControl\": \"Switch Control (On/Off/Level)\",\n\t\"sensorBinary\": \"Binary Sensor\",\n\t\"l_choose\":\"--- Choose a device type ---\",\n\t\"l_choose_dev\":\"--- Choose a device ---\",\n\t\"l_choose_controller_action\":\"--- Choose a controller action ---\",\n\t\"l_controller_action\":\"Controller Actions\",\n\t\"h_controller_action\":\"The action is described with a two-digit value: The first digit is the button number, the second digit points to the action of this button (0=short press, 1=release, 2=hold, 3=short press two times, 4 = short press three times, and so on. Examples: Double Click button 2 => 23, Single Click button 1 = 10)\",\n\t\"sensorDiscrete\":\"Scene Controller\",\n\t\"switchRGBW\":\"Color Switch\",\n\t\"l_red\":\"Red\",\n\t\"l_green\":\"Green\",\n\t\"l_blue\":\"Blue\",\n\t\"colors\":\"Colors\",\n\t\"h_color\":\"Choose a value from 0 - 255\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/IfThen/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Если -> Тогда\",\n\t\"m_descr\":\"Ассоциирование устройств с возможностью задать состояния устройств.\",\n\t\"l_event_sources\":\"Если\",\n\t\"l_actors\":\"Тогда\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_level\":\"Уровень\",\n\t\"level\": \"Set Level\",\n\t\"open\":\"Открыть\",\n\t\"close\":\"Закрыть\",\n\t\"l_scene\":\"Сцена или уведомление\",\n\t\"l_filter\":\"Фильтр по типу\",\n\t\"switchBinary\":\"Выключатель\",\n\t\"switchMultilevel\":\"Диммер\",\n\t\"sensorMultilevel\":\"Multilevel Sensor\",\n\t\"doorlock\":\"Замок\",\n\t\"thermostat\":\"Thermostat\",\n\t\"l_target_device\":\"Устройство\",\n\t\"l_action\":\"Действие\",\n\t\"toggleButton\": \"Кнопка (только Включить)\",\n\t\"switchControl\": \"Кнопка (Включить/Выключить/Level)\",\n\t\"sensorBinary\": \"Бинарный датчик\",\n\t\"l_choose\":\"--- Выберите тип устройства ---\",\n\t\"l_choose_dev\":\"--- Выберите устройство ---\",\n\t\"l_choose_controller_action\":\"--- Choose a controller action ---\",\n\t\"l_controller_action\":\"Controller Actions\",\n\t\"h_controller_action\":\"The action is described with a two-digit value: The first digit is the button number, the second digit points to the action of this button (0=short press, 1=release, 2=hold, 3=short press two times, 4 = short press three times, and so on. Examples: Double Click button 2 => 23, Single Click button 1 = 10)\",\n\t\"sensorDiscrete\":\"Scene Controller\",\n\t\"switchRGBW\":\"Color Switch\",\n\t\"l_red\":\"Красный\",\n\t\"l_green\":\"Зеленый\",\n\t\"l_blue\":\"Синий\",\n\t\"colors\":\"Цвет\",\n\t\"h_color\":\"Выберите значение 0 - 255\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Нужно чтобы не забивать сеть.\",\n\t\"b_createmail\": \"Activate EMailMe\",\n\t\"m_createmail\": \"ATTENTION! <br /> When leaving the current configuration, all previous settings are lost. <br /><br /> NOTE: <br /> You can continue with 'Cancel' without configuring the EMailMe app, create it afterwards, and add it then in the If -> Then configuration.\"\n}"
  },
  {
    "path": "modules/IfThen/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"IfThen\",\n\t\"version\": \"2.6.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"sourceDevice\": {},\n\t\t\"targets\": [],\n\t\t\"mail_helper\": \"__h_nomail__\",\n\t\t\"mail_button\": \"__b_createmail__\",\n\t\t\"mail_confirm\": \"__m_createmail__\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"sourceDevice\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"filterIf\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\"scene\",\n\t\t\t\t\t\t\t\"switchControl\",\n\t\t\t\t\t\t\t\"switchBinary\",\n\t\t\t\t\t\t\t\"switchMultilevel\",\n\t\t\t\t\t\t\t\"sensorBinary\",\n\t\t\t\t\t\t\t\"sensorMultilevel\",\n\t\t\t\t\t\t\t\"sensorDiscrete\"\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"sensorMultilevel\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operator\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\"<\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\"on\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scene\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"sensorDiscrete\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorDiscrete:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"switchControl\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\"on\",\n\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operator\": {\n\t\t\t\t\t\t\t\t\"dependencies\": \"status\",\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\"<\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\"dependencies\": \"status\",\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"switchMultilevel\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\"on\",\n\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operator\": {\n\t\t\t\t\t\t\t\t\"dependencies\": \"status\",\n\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\"<\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\"dependencies\": \"status\",\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"sensorBinary\": {\n\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\"dependencies\": \"filterIf\",\n\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId\",\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\"on\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"targets\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"filterThen\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\"switchBinary\",\n\t\t\t\t\t\t\t\t\"switchMultilevel\",\n\t\t\t\t\t\t\t\t\"doorlock\",\n\t\t\t\t\t\t\t\t\"scene\",\n\t\t\t\t\t\t\t\t\"thermostat\",\n\t\t\t\t\t\t\t\t\"switchRGBW\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"filterThen\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\t\"on\"\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"switchMultilevel\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"filterThen\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\t\"on\",\n\t\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\t\"dependencies\": \"status\",\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"doorlock\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"filterThen\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\"close\",\n\t\t\t\t\t\t\t\t\t\t\"open\"\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"scene\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"filterThen\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"thermostat\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"filterThen\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_thermostat:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t5,\n\t\t\t\t\t\t\t\t\t\t5.5,\n\t\t\t\t\t\t\t\t\t\t6,\n\t\t\t\t\t\t\t\t\t\t6.5,\n\t\t\t\t\t\t\t\t\t\t7,\n\t\t\t\t\t\t\t\t\t\t7.5,\n\t\t\t\t\t\t\t\t\t\t8,\n\t\t\t\t\t\t\t\t\t\t8.5,\n\t\t\t\t\t\t\t\t\t\t9,\n\t\t\t\t\t\t\t\t\t\t9.5,\n\t\t\t\t\t\t\t\t\t\t10,\n\t\t\t\t\t\t\t\t\t\t10.5,\n\t\t\t\t\t\t\t\t\t\t11,\n\t\t\t\t\t\t\t\t\t\t11.5,\n\t\t\t\t\t\t\t\t\t\t12,\n\t\t\t\t\t\t\t\t\t\t12.5,\n\t\t\t\t\t\t\t\t\t\t13,\n\t\t\t\t\t\t\t\t\t\t13.5,\n\t\t\t\t\t\t\t\t\t\t14,\n\t\t\t\t\t\t\t\t\t\t14.5,\n\t\t\t\t\t\t\t\t\t\t15,\n\t\t\t\t\t\t\t\t\t\t15.5,\n\t\t\t\t\t\t\t\t\t\t16,\n\t\t\t\t\t\t\t\t\t\t16.5,\n\t\t\t\t\t\t\t\t\t\t17,\n\t\t\t\t\t\t\t\t\t\t17.5,\n\t\t\t\t\t\t\t\t\t\t18,\n\t\t\t\t\t\t\t\t\t\t18.5,\n\t\t\t\t\t\t\t\t\t\t19,\n\t\t\t\t\t\t\t\t\t\t19.5,\n\t\t\t\t\t\t\t\t\t\t20,\n\t\t\t\t\t\t\t\t\t\t20.5,\n\t\t\t\t\t\t\t\t\t\t21,\n\t\t\t\t\t\t\t\t\t\t21.5,\n\t\t\t\t\t\t\t\t\t\t22,\n\t\t\t\t\t\t\t\t\t\t22.5,\n\t\t\t\t\t\t\t\t\t\t23,\n\t\t\t\t\t\t\t\t\t\t23.5,\n\t\t\t\t\t\t\t\t\t\t24,\n\t\t\t\t\t\t\t\t\t\t24.5,\n\t\t\t\t\t\t\t\t\t\t25,\n\t\t\t\t\t\t\t\t\t\t25.5,\n\t\t\t\t\t\t\t\t\t\t26,\n\t\t\t\t\t\t\t\t\t\t26.5,\n\t\t\t\t\t\t\t\t\t\t27\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"switchRGBW\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"filterThen\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchRGBW:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\"off\",\n\t\t\t\t\t\t\t\t\t\t\"on\",\n\t\t\t\t\t\t\t\t\t\t\"color\"\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": \"on\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"color\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\"dependencies\": \"status\",\n\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\"red\": {\n\t\t\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"maximum\": 255,\n\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"green\": {\n\t\t\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"maximum\": 255,\n\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"blue\": {\n\t\t\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\t\t\"maximum\": 255,\n\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"sourceDevice\": {\n\t\t\t\t\"label\": \"__l_event_sources__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"filterIf\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\"noneLabel\": \"__l_choose__\",\n\t\t\t\t\t\t\"label\": \"__l_filter__\",\n\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\"__toggleButton__\",\n\t\t\t\t\t\t\t\"__switchControl__\",\n\t\t\t\t\t\t\t\"__switchBinary__\",\n\t\t\t\t\t\t\t\"__switchMultilevel__\",\n\t\t\t\t\t\t\t\"__sensorBinary__\",\n\t\t\t\t\t\t\t\"__sensorMultilevel__\",\n\t\t\t\t\t\t\t\"__sensorDiscrete__\"\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t\"sensorMultilevel\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"sensorMultilevel\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operator\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_level__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"switchBinary\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\"__on__\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scene\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"scene\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"sensorDiscrete\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"sensorDiscrete\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorDiscrete:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_controller_action__\",\n\t\t\t\t\t\t\t\t\"helper\": \"__h_controller_action__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"switchControl\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"switchControl\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"label\": \"__l_level__\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\"__on__\",\n\t\t\t\t\t\t\t\t\t\"__level__\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operator\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"status\": [\n\t\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"type\": \"select\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"status\": [\n\t\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"switchMultilevel\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"switchMultilevel\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"label\": \"__l_level__\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\"__on__\",\n\t\t\t\t\t\t\t\t\t\"__level__\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"operator\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"status\": [\n\t\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"type\": \"select\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"status\": [\n\t\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"sensorBinary\": {\n\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\"filterIf\": \"sensorBinary\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\"__on__\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"targets\": {\n\t\t\t\t\"label\": \"__l_actors__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"filterThen\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose__\",\n\t\t\t\t\t\t\t\t\"label\": \"__l_filter__\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"__switchBinary__\",\n\t\t\t\t\t\t\t\t\t\"__switchMultilevel__\",\n\t\t\t\t\t\t\t\t\t\"__doorlock__\",\n\t\t\t\t\t\t\t\t\t\"__l_scene__\",\n\t\t\t\t\t\t\t\t\t\"__thermostat__\",\n\t\t\t\t\t\t\t\t\t\"__switchRGBW__\"\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"switchBinary\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"filterThen\": \"switchBinary\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_target_device__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_action__\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__on__\"\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"switchMultilevel\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"filterThen\": \"switchMultilevel\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_target_device__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_level__\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__on__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__level__\"\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"level\": {\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"status\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\"level\"\n\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"doorlock\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"filterThen\": \"doorlock\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_target_device__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_action__\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\"__close__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__open__\"\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"scene\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"filterThen\": \"scene\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_scene__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_scene__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"thermostat\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"filterThen\": \"thermostat\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_target_device__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_thermostat:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_level__\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"switchRGBW\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"filterThen\": \"switchRGBW\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"target\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_target_device__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchRGBW:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_level__\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\"__off__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__on__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__colors__\"\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"color\": {\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"status\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\"color\"\n\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__colors__\",\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"red\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_red__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_color__\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"green\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_green__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_color__\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"blue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_blue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_color__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/IfThen/patchnotes.txt",
    "content": "v2.6.0\n- removed notifications in favor of new notification system\nv2.5.1\n- allow negativ values for multilevel sensors\nv2.5.0\n- notification as part of If/Then\nv2.4.5\n- allow push and mail with same notification\nv2.4.4\n- adding push and/or mail notification\nv2.4.1\n- adding support for sensorDiscrete\n- adding support for switchRGBW\n- bugfix ON/OFF if sensorMultilevel is trigger action\nv2.1.1\n- bugfix missing change of levels switch multilevel and refactoring\n- avoid update of vDev with same level\nv2.1.0\n- add Thermostat and Multilevel Sensor support\n- add set Level to switch control and switch multilevel\nv2.0.5\n- bugfix: wrong adressing of 'if'-device if app is stopped, so that conditions are still active\n"
  },
  {
    "path": "modules/ImportRemoteHA/index.js",
    "content": "/*** ImportRemoteHA Z-Way HA module *******************************************\n\nVersion: 2.0.4\n(c) Z-Wave.Me, 2022\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Niels Roche <nir@zwave.eu>\nDescription:\n\tImports devices from remote HA engine\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction ImportRemoteHA (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tImportRemoteHA.super_.call(this, id, controller);\n}\n\ninherits(ImportRemoteHA, AutomationModule);\n\n_module = ImportRemoteHA;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nImportRemoteHA.prototype.init = function (config) {\n\tImportRemoteHA.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tvar config_url = this.config.url.indexOf('http://') > -1? this.config.url : 'http://' + this.config.url + ':8083';\n\n\tconsole.log('config_url',config_url);\n\t\n\tthis.urlPrefix = config_url + \"/ZAutomation/api/v1/devices\";\n\tthis.dT = Math.max(this.config.dT, 500); // 500 ms minimal delay between requests\n\tthis.timestamp = 0;\n\tthis.lastRequest = 0;\n\tthis.timer = null;\n\n\tthis.requestUpdate();\n};\n\nImportRemoteHA.prototype.stop = function () {\n\tvar self = this;\n\n\tif (this.timer) {\n\t\tclearTimeout(this.timer);\n\t}\n\t\n\tthis.controller.devices.filter(function(xDev) {\n\t\treturn (xDev.id.indexOf(\"RemoteHA_\" + self.id + \"_\") !== -1)\n\t}).map(function(yDev) {\n\t\treturn yDev.id\n\t}).forEach(function(item) {\n\t\tself.controller.devices.remove(item);\n\t});\n\t\n\tImportRemoteHA.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nImportRemoteHA.prototype.requestUpdate = function () {\n\tvar self = this;\n\t\n\tthis.lastRequest = Date.now();\n\n\tvar url = this.urlPrefix + \"?since=\" + this.timestamp.toString();\n\ttry {\t\n\t\thttp.request({\n\t\t\turl: url,\n\t\t\tmethod: \"GET\",\n\t\t\tasync: true,\n\t\t\tauth: {\n\t\t\t\tlogin: self.config.login,\n\t\t\t\tpassword: self.config.password\n\t\t\t},\n\t\t\tsuccess: function(response) {\n\t\t\t\tself.parseResponse(response);\n\t\t\t},\n\t\t\terror: function(response) {\n\t\t\t\tconsole.log(\"Can not make request: \" + response.statusText + \" \" + url); // don't add it to notifications, since it will fill all the notifcations on error\n\t\t\t},\n\t\t\tcomplete: function() {\n\t\t\t\tvar dt = self.lastRequest + self.dT - Date.now();\n\t\t\t\tif (dt < 0) {\n\t\t\t\t\tdt = 1; // in 1 ms not to make recursion\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (self.timer) {\n\t\t\t\t\tclearTimeout(self.timer);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tself.timer = setTimeout(function() {\n\t\t\t\t\tself.requestUpdate();\n\t\t\t\t}, dt);\n\t\t\t}\n\t\t});\n\t} catch (e) {\n\t\tself.timer = setTimeout(function() {\n\t\t\tself.requestUpdate();\n\t\t}, self.dT);\n\t}\n};\n\nImportRemoteHA.prototype.parseResponse = function (response) {\n\tvar self = this;\n\t\n\tif (response.status === 200, response.contentType === \"application/json\") {\n\t\tvar data = response.data.data;\n\t\t\n\t\tthis.timestamp = data.updateTime;\n\t\t\n\t\tdata.devices.forEach(function(item) {\n\t\t\tvar localId = \"RemoteHA_\" + self.id + \"_\" + item.id,\n\t\t\t\tvDev = self.controller.devices.get(localId);\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\tfor (var m in item.metrics) {\n\t\t\t\t\tif (vDev.get(\"metrics:\" + m) !== item.metrics[m]) {\n\t\t\t\t\t\tvDev.set(\"metrics:\" + m, item.metrics[m]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\tif (self.skipDevice(localId)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tvar dev = {\n\t\t\t\t\tdeviceId: localId,\n\t\t\t\t\tdefaults: {\n\t\t\t\t\t\tnodeId: item.nodeId === undefined ? undefined : ('R-' + self.id + (item.bindingName === undefined ? \"\" : (\"_\" + item.bindingName)) + \"_\" + item.nodeId),\n\t\t\t\t\t\tbindingName: item.bindingName === undefined ? undefined : ('R-' + item.bindingName),\n\t\t\t\t\t\ttechnology: item.technology,\n\t\t\t\t\t\tdeviceType: item.deviceType,\n\t\t\t\t\t\tprobeType: item.probeType,\n\t\t\t\t\t\tmetrics: item.metrics,\n\t\t\t\t\t\tvisibility: item.visibility || true,\n\t\t\t\t\t\tpermanently_hidden: item.permanently_hidden\n\t\t\t\t\t},\n\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\tself.handleCommand(this, command, args);\n\t\t\t\t\t},\n\t\t\t\t\toverlay: {},\n\t\t\t\t\tmoduleId: this.id\n\t\t\t\t}\n\n\t\t\t\t// add tag if activated\n\t\t\t\tif (self.config.addTag) {\n\t\t\t\t\tdev.overlay.tags = self.config.tagName && self.config.tagName !== ''? [self.config.tagName] : [\"RemoteHA_\" + self.id];\n\t\t\t\t}\n\n\t\t\t\tself.controller.devices.create(dev);\n\n\t\t\t\tself.renderDevice({deviceId: localId, deviceType: item.deviceType});\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (data.structureChanged) {\n\t\t\tvar removeList = this.controller.devices.filter(function(xDev) {\n\t\t\t\tvar found = false;\n\t\t\t\t\n\t\t\t\tif (xDev.id.indexOf(\"RemoteHA_\" + self.id + \"_\") === -1) {\n\t\t\t\t\treturn false; // not to remove devices created by other modules\n\t\t\t   \t}\n\n\t\t\t\tdata.devices.forEach(function(item) {\n\t\t\t\t\tif ((\"RemoteHA_\" + self.id + \"_\" + item.id) === xDev.id) {\n\t\t\t\t\t\tfound |= true;\n\t\t\t\t\t\treturn false; // break\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn !found;\n\t\t\t}).map(function(yDev) { return yDev.id });\n\t\t\t\n\t\t\tremoveList.forEach(function(item) {\n\t\t\t\tself.controller.devices.remove(item);\n\t\t\t});\n\t\t}\n\t}\n};\n\nImportRemoteHA.prototype.handleCommand = function(vDev, command, args) {\n\tvar self = this;\n\t\n\tvar argsFlat = \"\";\n\tif (args) {\n\t\tfor (var key in args) {\n\t\t\targsFlat = argsFlat + (argsFlat ? \"&\" : \"?\") + key.toString() + \"=\" + args[key].toString();\n\t\t}\n\t}\n\t\n\tvar remoteId = vDev.id.slice((\"RemoteHA_\" + this.id + \"_\").length);\n\t\n\tvar url = this.urlPrefix + \"/\" + remoteId + \"/command/\" + command + argsFlat;\n\t\n\thttp.request({\n\t\turl: url,\n\t\tmethod: \"GET\",\n\t\tasync: true,\n\t\tauth: {\n\t\t\tlogin: self.config.login,\n\t\t\tpassword: self.config.password\n\t\t},\n\t\terror: function(response) {\n\t\t\tconsole.log(\"Can not make request: \" + response.statusText + \" \" + url); // don't add it to notifications, since it will fill all the notifcations on error\n\t\t}\n\t});\n};\n\nImportRemoteHA.prototype.skipDevice = function(id) {\n\tvar skip = false;\n\t\n\tthis.config.skipDevices.forEach(function(skipItem) {\n\t\tif (skipItem === id) {\n\t\t\tskip |= true;\n\t\t\treturn false; // break\n\t\t}   \n\t});\n\t\n\treturn skip;\n};\n\n// check if deviceId is already added to list\nImportRemoteHA.prototype.renderDevice = function (obj) {\n\tvar skip = false;\n\t\n\tthis.config.renderDevices.forEach(function (deviceObj) {\n\t\tif (deviceObj.deviceId === obj.deviceId) {\n\t\t\tskip |= true;\n\t\t\treturn false; // break\n\t\t}\n\t});\n\t\n\tif (!skip) {\n\t\tthis.config.renderDevices.push(obj);\n\t\tthis.saveConfig();\n\t}\n};\n"
  },
  {
    "path": "modules/ImportRemoteHA/lang/de.json",
    "content": "{\n\t\"m_title\":\"Verbinde anderen Z-Way-Controller\",\n\t\"m_descr\":\"Z-Way steuert ein Z-Wave Netzwerk mit bis zu 232 Geräten. Diese App führt mehrere Z-Way Einheiten in einem User Interface zusammen. Im Grunde bildet die App Daten eines anderen Z-Way betriebenen Gateways in Ihrem Gateway ab. Die Elemente werden dargestellt und können wie das vorliegende bedient werden. Bitte beachten Sie, dass die Funktion des zweiten Gateways unberührt bleibt. Das heißt, das zweite Gateway nimmt die Elemente Ihres ersten Gateways nicht wahr, kann sie aber steuern und dessen Elemente ohne weitere Einschränkungen abrufen:<br><br>Einstellungen: <br><ul><li>Stellen Sie die IP Adresse der Remote-Box einschließlich der Port-Nummer ein.  </li><li>Definieren Sie das Abrufintervall. Empfehlenswert wäre einmal pro Sekunde.</li><li>Inkludieren Sie das fernzusteuernde Gerät in Ihre UI. </li></ul>\",\n\t\"l_url\":\"URL Z-Wave Homegateway\",\n\t\"l_login\":\"Login\",\n\t\"l_password\":\"Password\",\n\t\"l_dT\":\"Updateperiode (in Millisekunden)\",\n\t\"l_skipDevices\":\"Geräte die nicht aus dem Z-Wave Homegateway importiert werden sollen:\",\n\t\"l_renderDevices\":\"Aus dem Z-Wave Homegateway importierte Geräte (wird automatisch geladen):\",\n\t\"rl_addTag\":\"Füge einen Tag zu allen Remote Geräten hinzu\",\n\t\"l_tagName\":\"Tag\",\n\t\"ph_tagName\": \"Remote Box\",\n\t\"h_tagName\": \"RemoteHA_ID wird benutzt, wenn kein Tag angegeben ist\"\n}"
  },
  {
    "path": "modules/ImportRemoteHA/lang/en.json",
    "content": "{\n\t\"m_title\":\"Link other Z-Way controller\",\n\t\"m_descr\":\"Z-Way controls one Z-Wave network with up to 232 devices. This app will combine multiple Z-Way entities into one User Interface. Essentially the app is mapping the data of another Z-Way powered Gateway into your gateway. The elements are displayed and can be used like the local ones. Please note that the function of the second gateway remains untouched. This means that this second gateway will not see the elements for your first gateway but can control and access their own elements without any further restrictions:<br><br>Settings:<br><ul><li> You need to set the IP address of the Remote Box including the port number.</li> You need to define the polling interval.  Once a second is a quite good choice.</li> You need to manage the remoted device to be included into your UI.</li></ul>\",\n\t\"l_url\":\"URL to remote side\",\n\t\"l_login\":\"Login\",\n\t\"l_password\":\"Password\",\n\t\"l_dT\":\"Update period (in milliseconds)\",\n\t\"l_skipDevices\":\"List of devices not to import from remote side\",\n\t\"l_renderDevices\":\"List of devices imported from remote side (filled automatically)\",\n\t\"rl_addTag\":\"Add tag to all remote widgets\",\n\t\"l_tagName\":\"Tag\",\n\t\"ph_tagName\": \"Remote Box\",\n\t\"h_tagName\": \"RemoteHA_ID is used if no tag is added\"\n}"
  },
  {
    "path": "modules/ImportRemoteHA/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Импорт устройств из другой RaZberry\",\n\t\"m_descr\":\"Устройства с разных контроллеров RaZberry можно объединить в одном контроллере.\",\n\t\"l_url\":\"URL другой RaZberry\",\n\t\"l_login\":\"Логин\",\n\t\"l_password\":\"Пароль\",\n\t\"l_dT\":\"Частота опроса другой RaZberry (в миллисекундах)\",\n\t\"l_skipDevices\":\"Список устройств, которые не нужно импортировать с другой RaZberry\",\n\t\"l_renderDevices\":\"Список устройств для импорта с другой RaZberry (заполняется автоматически)\",\n\t\"rl_addTag\":\"Add tag to all remote widgets\",\n\t\"l_tagName\":\"Tag\",\n\t\"ph_tagName\": \"Remote Box\",\n\t\"h_tagName\": \"RemoteHA_ID is used if no tag is added\"\n}"
  },
  {
    "path": "modules/ImportRemoteHA/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"support_external_dev\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\": \"ImportRemoteHA\",\n\t\"version\": \"2.0.4\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"addTag\":false,\n\t\t\"tagName\":\"\",\n\t\t\"url\": \"\",\n\t\t\"login\":\"admin\",\n\t\t\"password\":\"admin\",\n\t\t\"dT\": 1000,\n\t\t\"skipDevices\": [],\n\t\t\"renderDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"addTag\":{\n\t\t\t\t\"type\" : \"boolean\",\n\t\t\t\t\"required\" : false\n\t\t\t},\n\t\t\t\"tagName\":{\n\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\"dependencies\": \"addTag\",\n\t\t\t\t\"required\" : false\n\t\t\t},\n\t\t\t\"url\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"login\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"dT\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"skipDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_all:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"renderDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"deviceId\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_all:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"deviceType\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"addTag\":{\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\":\"__rl_addTag__\"\n\t\t\t},\n\t\t\t\"tagName\":{\n\t\t\t\t\"label\": \"__l_tagName__\",\n\t\t\t\t\"placeholder\": \"__ph_tagName__\",\n\t\t\t\t\"helper\":\"__h_tagName__\"\n\t\t\t},\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__l_url__\",\n\t\t\t\t\"placeholder\": \"192.168.0.100\"\n\t\t\t},\n\t\t\t\"login\": {\n\t\t\t\t\"label\": \"__l_login__\"\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"type\": \"password\",\n\t\t\t\t\"label\": \"__l_password__\"\n\t\t\t},\n\t\t\t\"dT\": {\n\t\t\t\t\"label\": \"__l_dT__\"\n\t\t\t},\n\t\t\t\"skipDevices\": {\n\t\t\t\t\"label\": \"__l_skipDevices__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_all:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"renderDevices\": {\n\t\t\t\t\"label\": \"__l_renderDevices__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"deviceId\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"readonly\": true,\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_all:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"deviceType\": {\n\t\t\t\t\t\t\t\t\"readonly\": true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/ImportRemoteHA/patchnotes.txt",
    "content": "#v2.0.3\n- fixed: hidden and deactivated devices of remote controller were also shown\n\n#v2.0.2 (pull request #393 by xibrix)\n- fixed: RenderDevices array in storage are doubleing up when module config is edited.\n\n#v2.0.1\n - add functionality to tag all remote widgets\n - enhance url input to add ip adress only (with backward compatibility)"
  },
  {
    "path": "modules/InbandNotifications/index.js",
    "content": "/*** InbandNotifications Z-Way HA module *******************************************\n\nVersion: 1.1.2\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>, Serguei Poltorak <ps@z-wave.me>\nDescription:\n\tListens to the statuses of all devices and\n\temits notifications on changed.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction InbandNotifications (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tInbandNotifications.super_.call(this, id, controller);\n}\n\ninherits(InbandNotifications, AutomationModule);\n\n_module = InbandNotifications;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nInbandNotifications.prototype.init = function (config) {\n\tInbandNotifications.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t    lastChanges = [];\n\n\tthis.writeNotification = function (vDev) {\n\t\tif (!vDev.get('permanently_hidden')) {\n\t\t\tvar devId = vDev.get('id'),\n\t\t\t    devType = vDev.get('deviceType'),\n\t\t\t    devProbeType = vDev.get('probeType'),\n\t\t\t    devName = vDev.get('metrics:title'),\n\t\t\t    scaleUnit = vDev.get('metrics:scaleTitle'),\n\t\t\t    level = vDev.get('metrics:level');\n\t\t\t\n\t\t\tfunction getCustomIcon() {\n\t\t\t\tvar customIcons = vDev.get('customIcons');\n\t\t\t\tif (!customIcons || Object.keys(customIcons).length === 0) return undefined;\n\t\t\t\treturn customIcons.level ? customIcons.level[level] : customIcons.default;\n\t\t\t};\n\n\t\t\tfunction eventType(){\n\t\t\t\tvar probeTitle = vDev.get('metrics:probeTitle');\n\t\t\t\treturn probeTitle ? probeTitle.toLowerCase() : 'status';\n\t\t\t};\n\n\t\t\tvar lastEvent = lastChanges.filter(function(e) {\n\t\t\t\treturn e.id === devId;\n\t\t\t})[0];\n\t\t\t\n\t\t\tif (!lastEvent) {\n\t\t\t\tlastEvent = {\n\t\t\t\t\tid: devId,\n\t\t\t\t\tl: null\n\t\t\t\t};\n\t\t\t\tlastChanges.push(lastEvent);\n\t\t\t}\n\n\t\t\tvar msg = {\n\t\t\t\tdev: devName,\n\t\t\t\tl: level, // will be extended below\n\t\t\t\tlocation: vDev.get('location'),\n\t\t\t\tcustomIcon: getCustomIcon()\n\t\t\t};\n\t\t\tvar msgType = \"\";\n\t\t\t\n\t\t\tif (lastEvent.l === level && [\"battery\", \"sensorBinary\", \"sensorDiscrete\", \"toggleButton\", \"switchControl\"].indexOf(devType) === - 1)  return; // emit only for new values (not same as previous) or sensorBinary/sensorDiscrete/toggleButton/switchControl events\n\n\t\t\t// depending on device type choose the correct notification\n\t\t\tswitch(devType) {\n\t\t\t\tcase 'switchBinary':\n\t\t\t\tcase 'switchControl':\n\t\t\t\tcase 'sensorBinary':\n\t\t\t\tcase 'fan':\n\t\t\t\tcase 'doorlock':\n\t\t\t\tcase 'toggleButton':\n\t\t\t\t\tmsgType = 'device-OnOff';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'switchMultilevel':\n\t\t\t\t\tmsg.l +=  '%';\n\t\t\t\t\tmsgType = 'device-status';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'sensorDiscrete':\n\t\t\t\t\tmsgType = 'device-status';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'battery':\n\t\t\t\tcase 'sensorMultilevel':\n\t\t\t\tcase 'sensorMultiline':\n\t\t\t\tcase 'thermostat':\n\t\t\t\t\tmsg.l += (scaleUnit ? ' ' + scaleUnit : '');\n\t\t\t\t\tmsgType = 'device-' + eventType();\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'switchRGBW':\n\t\t\t\t\tmsg.color = vDev.get('metrics:color');\n\t\t\t\t\tmsgType = 'device-' + eventType();\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\treturn; // don't add the notification\n\t\t\t}\n\t\t\t\n\t\t\tlastEvent.l = level;\n\t\t\t\n\t\t\tself.controller.addNotification('device-info', msg , msgType, devId);\n\t\t}\t \n\t};\n\n\t// Setup metric update event listener\n\tself.controller.devices.on('change:metrics:level', self.writeNotification);\n};\n\nInbandNotifications.prototype.stop = function () {\n\tvar self = this;\t   \n\n\tself.controller.devices.off('change:metrics:level', self.writeNotification);\n\n\tInbandNotifications.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/InbandNotifications/lang/de.json",
    "content": "{\n\t\"m_title\":\"Ereignisprotokoll \",\n\t\"m_descr\":\"Der Inband Notifier ordnet die Darstellung der Systemereignisse im Zeitrahmen Ihres User Interface an. Es sollte die ganze Zeit aktiviert sein. In der Verwendung mit diesem Modul kann sehr viel falsch gemacht werden, daher lassen Sie es unberührt, solange es nicht wirklich benötigt wird.\",\n\t\"l_dev\":\"Geräte die überwacht werden sollen\",\n\t\"l_devT\":\"Gerätetypen die überwacht werden sollen\",\n\t\"all\":\"alle Gerätetypen\",\n\t\"battery\":\"Batterie\",\n\t\"fan\":\"Ventilator\",\n\t\"doorlock\":\"Türschloss\",\n\t\"switchBinary\":\"An/Aus Schalter \", \n\t\"switchMultilevel\":\"Dimmer/Motor Steuerung \",\n\t\"switchControl\":\"Schalter Steuerung \",\n\t\"sensorBinary\":\"An/Aus Sensor \",\n\t\"sensorMultilevel\":\"Analogsensor \",\n\t\"sensorMultiline\":\"Informations Sensor\",\n\t\"thermostat\":\"Thermostat Regler \"\n}"
  },
  {
    "path": "modules/InbandNotifications/lang/en.json",
    "content": "{\n\t\"m_title\":\"Inband Notifier\",\n\t\"m_descr\":\"The inband notifier organizes to display the events of the system into the time line of your User Interface. It should be active all the time. There is nothing to be done right with the module but a lot of things that can be done wrong. This means, don’t touch it unless its really needed. \",\n\t\"l_dev\":\"Devices to be monitored\",\n\t\"l_devT\":\"Device types to be monitored\",\n\t\"all\":\"all device types \",\n\t\"battery\":\"Battery Sensor \",\n\t\"fan\":\"Fan Switch \",\n\t\"doorlock\":\"Doorlock Switch \",\n\t\"switchBinary\":\"On/Off Switch \", \n\t\"switchMultilevel\":\"Dimmer/Motor Control \",\n\t\"switchControl\":\"Switch Control \",\n\t\"sensorBinary\":\"On/Off Sensor \",\n\t\"sensorMultilevel\":\"Analog Sensor \",\n\t\"sensorMultiline\":\"Informer \",\n\t\"thermostat\":\"Thermostat Switch \"\n}"
  },
  {
    "path": "modules/InbandNotifications/module.json",
    "content": "{\n\t\"singleton\" : true,\n\t\"dependencies\" : [],\n\t\"category\" : \"basic_gateway_modules\",\n\t\"author\" : \"Z-Wave.Me\",\n\t\"homepage\" : \"https://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"InbandNotifications\",\n\t\"version\" : \"1.1.2\",\n\t\"maturity\" : \"stable\",\n\t\"repository\" : {\n\t\t\"type\" : \"git\",\n\t\t\"source\" : \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\" : {\n\t\t\"title\" : \"__m_title__\",\n\t\t\"description\" : \"__m_descr__\"\n\t},\n\t\"schema\": {},\n\t\"options\": {}\n}"
  },
  {
    "path": "modules/InfoWidget/index.js",
    "content": "/*** InfoWidget Z-Way HA module *******************************************\n\nVersion: 1.0.1\n(c) Z-Wave.Me, 2018\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>\nChanged: Karsten Reichel <kar@zwave.eu>\nDescription:\n\tCreates a text/information widget as devicetype 'text'.\n\tIt is possible to internationalize one widget with EN,DE,RU or CN translation.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction InfoWidget (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tInfoWidget.super_.call(this, id, controller);\n}\n\ninherits(InfoWidget, AutomationModule);\n\n_module = InfoWidget;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nInfoWidget.prototype.init = function (config) {\n\tInfoWidget.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tvDev;\n\n\tthis.vDev = [];\n\n\tthis.createTextWidgets = function(lang) {\n\t\tvar lng = lang ? lang : self.controller.defaultLang;\n\n\t\tif (self.config.widgets && self.config.widgets.length > 0 && self.config.internationalize === false) {\n\n\t\t\tself.config.widgets.forEach(function (widget, indx) {\n\t\t\t\tvar devId = \"InfoWidget_\" + self.id + '_' + indx;\n\n\t\t\t\tif (self.vDev.indexOf(devId) === -1) {\n\t\t\t\t\tvDev = this.controller.devices.create({\n\t\t\t\t\t\tdeviceId: devId,\n\t\t\t\t\t\tdefaults: {\n\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\ttitle: widget.headline,\n\t\t\t\t\t\t\t\ttext: widget.text,\n\t\t\t\t\t\t\t\ticon: widget.imgURI\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\tdeviceType: \"text\",\n\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\ttitle: widget.headline,\n\t\t\t\t\t\t\t\ttext: widget.text,\n\t\t\t\t\t\t\t\ticon: widget.imgURI\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tself.vDev.push(vDev);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif (self.config.widgetsInt && self.config.widgetsInt.length > 0 && self.config.internationalize === true) {\n\n\t\t\tself.config.widgetsInt.forEach(function (widget) {\n\t\t\t\tif (widget.lang === lng) {\n\t\t\t\t\tvar devId = \"InfoWidget_\" + self.id + \"_Int\";\n\n\t\t\t\t\tif (self.vDev.indexOf(devId) === -1) {\n\t\t\t\t\t\tvDev = this.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: devId,\n\t\t\t\t\t\t\tdefaults: {\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: widget.headline,\n\t\t\t\t\t\t\t\t\ttext: widget.text,\n\t\t\t\t\t\t\t\t\ticon: widget.imgURI\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toverlay: {\n\t\t\t\t\t\t\t\tdeviceType: \"text\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: widget.headline,\n\t\t\t\t\t\t\t\t\ttext: widget.text,\n\t\t\t\t\t\t\t\t\ticon: widget.imgURI\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tself.vDev.push(vDev);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tthis.controller.on('language.changed',self.updateIntWidgets);\n\t\t}\n\t};\n\n\tthis.updateIntWidgets = function (lang) {\n\t\tvar dev = self.config.widgetsInt.filter(function(widget) {\n\t\t\t   return widget.lang === lang;\n\t\t\t});\n\t\tif (dev.length > 0 && self.vDev[0]) {\n\t\t\tself.vDev[0].set('metrics:title',dev[0].headline);\n\t\t\tself.vDev[0].set('metrics:text',dev[0].text);\n\t\t\tself.vDev[0].set('metrics:icon',dev[0].imgURI);\n\t\t}\n\t};\n\n\tthis.createTextWidgets(self.controller.defaultLang);\n\n};\n\nInfoWidget.prototype.stop = function () {\n\tvar self = this;\n\n\tthis.controller.off('language.changed',self.updateIntWidgets);\n\n\tif (self.vDev) {\n\t\tself.vDev.forEach(function (dev) {\n\t\t\tthis.controller.devices.remove(dev.id);\n\t\t});\n\n\t\tself.vDev = null;\n\t}\n\n\tInfoWidget.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/InfoWidget/lang/de.json",
    "content": "{\t\n\t\"m_title\":\"Informations Widget\",\n\t\"m_descr\":\"Diese App wird zur Darstellung einiger Textblöcke in der UI verwendet. Sie dient hauptsächlich zur einleitenden Information sowie zur Begrüßung.  Sie können sie z. B. auch als Linkliste verwenden, die es gestattet, den reinen HTML Code als Textblock umzusetzen. <br><br>Einstellungen:<br><ul><li>Erstellen Sie Ihren Text für die Darstellung in verschiedenen Sprachen. Bietet Ihre UI keine Sprachanweisungen, wird standardmäßig der Text in Englisch angezeigt.  </li></ul>\",\n\t\"l_widgets\":\"Ein oder mehrere Informations Widgets erzeugen\",\n\t\"h_widgets\":\"Klicken sie um ein Widget hinzuzufügen\",\n\t\"l_widget\": \"Widget\",\n\t\"l_headline\":\"Eingabe der Überschrift:\",\n\t\"p_headline\":\"Überschrift\",\n\t\"l_text\":\"Eingabe des Informationstextes\",\n\t\"p_text\":\"Text...\",\n\t\"l_imgURI\":\"URL des Bildes (optional):\",\n\t\"p_imgURI\":\"z.B. 'http://www.images.com/nature/tree_xy.jpg'\",\n\t\"l_translate\":\"Internationalisierung\",\n\t\"rl_translate\":\"Internationalisierung aktivieren\",\n\t\"p_translate\":\"Bei Aktivierung lassen sich mehrere Texte für die entsprechend eingestellte Benutzeroberflächensprache erstellen.\",\n\t\"l_lang\":\"Textsprache\",\n\t\"h_lang\":\"Bitte wählen Sie eine der Sprachen in der Sie Ihren Text verfassen möchten aus.\",\n\t\"en\":\"Englisch\",\n\t\"de\":\"Deutsch\",\n\t\"ru\":\"Russisch\",\n\t\"cn\":\"Chinesisch\"\n}"
  },
  {
    "path": "modules/InfoWidget/lang/en.json",
    "content": "{\n\t\"m_title\":\"Information Widget\",\n\t\"m_descr\":\"This app is used to display some text block in the UI. The main reason that this app exists is to give you some introductory information and a welcome greeting.  However you can use this e.g. as a link list since it allows defining pure HTML code as text block<br><br>Settings:<br><ul><li>Define your text to be shown in different languages. If there is no statement for the language of your UI, the English text will be used as default.</li></ul>\",\n\t\"l_widgets\":\"Create one or nore Information Widgets\",\n\t\"h_widgets\":\"Click to create a widget\",\n\t\"l_widget\": \"Widget\",\n\t\"l_headline\":\"Enter your headline:\",\n\t\"p_headline\":\"Headline\",\n\t\"l_text\":\"Enter your text:\",\n\t\"p_text\":\"Text...\",\n\t\"l_imgURI\":\"URL of your image (optional):\",\n\t\"p_imgURI\":\"e.g. 'http://www.images.com/nature/tree_xy.jpg'\",\n\t\"l_translate\":\"Internationalization\",\n\t\"rl_translate\":\"Activate Internationalization\",\n\t\"p_translate\":\"'If activated you could add different texts for each language known in user interface.\",\n\t\"l_lang\":\"Text Language\",\n\t\"h_lang\":\"Please choose one language in that you will write your text message.\",\n\t\"en\":\"English\",\n\t\"de\":\"German\",\n\t\"ru\":\"Russian\",\n\t\"cn\":\"Chinese\"\n}"
  },
  {
    "path": "modules/InfoWidget/module.json",
    "content": "{\n\t\"singleton\" : false,\n\t\"dependencies\": [],\n\t\"category\": \"device_enhancements\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"InfoWidget\",\n\t\"version\": \"1.0.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\" : {\n\t\t\"title\" : \"__m_title__\",\n\t\t\"description\" : \"__m_descr__\",\n\t\t\"widgets\":[]\n\t},\n\t\"schema\" : {\n\t\t\"type\":\"object\",\n\t\t\"properties\" : {\n\t\t\t\"internationalize\" : {\n\t\t\t\t\"type\" : \"boolean\",\n\t\t\t\t\"required\" : false\n\t\t\t},\n\t\t\t\"widgetsInt\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"$ref\": \"#/definitions/widgetInt\"\n\t\t\t\t},\n\t\t\t\t\"dependencies\": \"internationalize\"\n\t\t\t},\n\t\t\t\"widgets\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"$ref\": \"#/definitions/widget\"\n\t\t\t\t},\n\t\t\t\t\"dependencies\": \"internationalize\"\n\t\t\t}\n\t\t},\n\t\t\"definitions\":{\n\t\t\t\"widgetInt\": {\n\t\t\t\t\"type\" : \"object\",\n\t\t\t\t\"properties\":{\n\t\t\t\t\t\"lang\" : {\n\t\t\t\t\t\t\"enum\" : [\"en\",\"de\",\"ru\",\"cn\"],\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"default\": \"en\",\n\t\t\t\t\t\t\"required\" : true\n\t\t\t\t\t},\n\t\t\t\t\t\"headline\" : {\n\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\"required\" : true\n\t\t\t\t\t},\n\t\t\t\t\t\"text\" : {\n\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\"required\" : true\n\t\t\t\t\t},\n\t\t\t\t\t\"imgURI\" : {\n\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\"format\" : \"uri\",\n\t\t\t\t\t\t\"required\" : false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"widget\": {\n\t\t\t\t\"type\" : \"object\",\n\t\t\t\t\"properties\":{\n\t\t\t\t\t\"headline\" : {\n\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\"required\" : true\n\t\t\t\t\t},\n\t\t\t\t\t\"text\" : {\n\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\"required\" : true\n\t\t\t\t\t},\n\t\t\t\t\t\"imgURI\" : {\n\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\"required\" : false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\" : {\n\t\t\"fields\":{\n\t\t\t\"internationalize\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"label\":\"__l_translate__\",\n\t\t\t\t\"rightLabel\":\"__rl_translate__\",\n\t\t\t\t\"default\": false\n\t\t\t},\n\t\t\t\"widgets\":{\n\t\t\t\t\"label\":\"__l_widgets__\",\n\t\t\t\t\"helper\":\"__h_widgets__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"internationalize\": false\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"widgetsInt\":{\n\t\t\t\t\"label\":\"__l_widgets__\",\n\t\t\t\t\"helper\":\"__h_widgets__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"internationalize\": true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"definitions\":{\n\t\t\t\"fields\":{\n\t\t\t\t\"widgetInt\":{\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"lang\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_lang__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_lang__\",\n\t\t\t\t\t\t\t\"optionLabels\":[\"__en__\",\"__de__\",\"__ru__\",\"__cn__\"],\n\t\t\t\t\t\t\t\"type\" : \"select\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"headline\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_headline__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_headline__\",\n\t\t\t\t\t\t\t\"type\" : \"text\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"text\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_text__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_text__\",\n\t\t\t\t\t\t\t\"type\" : \"textarea\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"imgURI\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_imgURI__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_imgURI__\",\n\t\t\t\t\t\t\t\"type\" : \"text\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\"internationalize\": true\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"widget\":{\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"headline\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_headline__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_headline__\",\n\t\t\t\t\t\t\t\"type\" : \"text\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"text\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_text__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_text__\",\n\t\t\t\t\t\t\t\"type\" : \"textarea\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"imgURI\" : {\n\t\t\t\t\t\t\t\"label\" : \"__l_imgURI__\",\n\t\t\t\t\t\t\t\"placeholder\": \"__p_imgURI__\",\n\t\t\t\t\t\t\t\"type\" : \"text\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\"internationalize\": false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/LightMotionRockerAutocontrol/index.js",
    "content": "/*** LightMotionRockerAutocontrol Z-Way Home Automation module *************************************\n\n Version: 1.0.1\n (c) Z-Wave.Me, 2014\n\n -----------------------------------------------------------------------------\n Author: Poltorak Serguei <ps@z-wave.me>\n Description:\n\tThis module controls light via rocker, several motion sensors and light sensor.\n\tLight can be turned on and off by rocker (always) or by motion sensors\n\t(only if light level is high enough and manual control was not performed).\n\tA timer turns light off.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction LightMotionRockerAutocontrol (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tLightMotionRockerAutocontrol.super_.call(this, id, controller);\n\n\t// Light state\n\tthis.lightIs = \"unknown\";\n\t\n\t// Timers\n\tthis.rockerRelaxTimer = null;\n\tthis.motionOffTimer = null;\n\tthis.rescueOffTimer = null;\n\t\n\t// Prevent motion to trigger light after rocker operation\n\tthis.rockerRelax = false;\n\t\n\t// States of all motion sensors\n\tthis.motionsStates = {};\n\t\n\t// State of luminance sensor (true to allow trigger by motion)\n\tthis.luminanceState = true;\n};\n\ninherits(LightMotionRockerAutocontrol, AutomationModule);\n\n_module = LightMotionRockerAutocontrol;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nLightMotionRockerAutocontrol.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tLightMotionRockerAutocontrol.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\t\n\tthis.rockerHandler = function(vDev) {\n\t\tvar event = vDev.get(\"metrics:level\");\n\t\t\n\t\tif (event === \"on\") {\n\t\t\tself.turnLightsOn();\t\t// Turn on light\n\t\t\tself.rockerRelaxTimerStart();\t// Don't react on motion events for some period\n\t\t\tself.motionTimerStop();\t\t// Stop motion timer if any\n\t\t\tself.rescueTimerStart();\t// Run timer to turn off light if user forgot about it\n\t\t} else if (event === \"off\") {\n\t\t\tself.turnLightsOff();\t\t// Turn off light\n\t\t\tself.rockerRelaxTimerStart();\t// Don't react on motion events for some period\n\t\t\tself.motionTimerStop();\t\t// Stop motion timer if any\n\t\t\tself.rescueTimerStop();\t\t// Stop rescue timer\n\t\t}\n\t};\n\n\tthis.motionHandler = function(vDev) {\n\t\tvar level = vDev.get(\"metrics:level\");\n\t\tif (level === \"on\") {\n\t\t\tself.motionsStates[vDev.id] = true;\n\t\t\tself.rescueTimerStart();\t// Start rescue \n\t\t} else if (level === \"off\") {\n\t\t\tself.motionsStates[vDev.id] = false;\n\t\t} else {\n\t\t\treturn;\t\t\t\t// Don't check motion states, unknown event\n\t\t}\n\t\t\n\t\tself.checkMotions();\t\t\t// Check if all motion sensors are off\n\t};\n\n\tthis.luminanceHandler = function(vDev) {\n\t\tif (self.config.luminanceThreshold > 0) {\n\t\t\tvar _tmp = vDev.get(\"metrics:level\") < self.config.luminanceThreshold;\n\t\t\tif (_tmp !== self.luminanceState) {\n\t\t\t\tself.luminanceState = _tmp;\n\t\t\t\tself.checkMotions();\n\t\t\t}\n\t\t}\n\t};\n\t\n\tthis.config.rockers.forEach(function(rocker) {\n\t\tself.controller.devices.on(rocker, \"change:metrics:level\", self.rockerHandler);\n\t});\n\t\n\tthis.config.motions.forEach(function(motion) {\n\t\tself.controller.devices.on(motion, \"change:metrics:level\", self.motionHandler);\n\t});\n\t\n\tif (this.config.luminance) {\n\t\tself.controller.devices.on(this.config.luminance, \"change:metrics:level\", self.luminanceHandler);\n\t}\n\t\n\tvar vDevLumi = this.controller.devices.get(this.config.luminance);\n\tif (this.config.luminanceThreshold > 0 && vDevLumi) {\n\t\tthis.luminanceState = vDevLumi.get(\"metrics:level\") < this.config.luminanceThreshold;\n\t} else {\n\t\tthis.luminanceState = true; // If no device found or luminanceThreshold = 0, always work on motion\n\t}\n};\n\nLightMotionRockerAutocontrol.prototype.stop = function () {\n\tLightMotionRockerAutocontrol.super_.prototype.stop.call(this);\n\n\tvar self = this;\n\t\n\tthis.config.rockers.forEach(function(rocker) {\n\t\tself.controller.devices.off(rocker, \"change:metrics:level\", self.rockerHandler);\n\t});\n\t\n\tthis.config.motions.forEach(function(motion) {\n\t\tself.controller.devices.off(motion, \"change:metrics:level\", self.motionHandler);\n\t});\n\t\n\tif (this.config.luminance) {\n\t\tself.controller.devices.off(this.config.luminance, \"change:metrics:level\", self.luminanceHandler);\n\t}\n\t\n\tif (this.rockerRelaxTimer) {\n\t\tclearTimeout(this.rockerRelaxTimer);\n\t}\n\tif (this.motionOffTimer) {\n\t\tclearTimeout(this.motionOffTimer);\n\t}\n\tif (this.rescueOffTimer) {\n\t\tclearTimeout(this.rescueOffTimer);\n\t}\n};\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nLightMotionRockerAutocontrol.prototype.checkMotions = function() {\n\tif (this.rockerRelax) {\n\t\treturn;\n\t}\n\t\n\tvar oneMotionIsOn = false;\n\t\n\tfor (var vDevId in this.motionsStates) {\n\t\toneMotionIsOn |= this.motionsStates[vDevId];\n\t};\n\t\n\tif (oneMotionIsOn && this.luminanceState) {\n\t\tthis.turnLightsOn();\n\t\tthis.rescueTimerStart();\n\t\tthis.motionTimerStop();\n\t}\n\n\tif (!oneMotionIsOn || !this.luminanceState) {\n\t\tthis.motionTimerStart();\n\t}\n};\n\nLightMotionRockerAutocontrol.prototype.turnLights = function(action) {\n\tvar self = this;\n\n\tself.config.lights.forEach(function(device) {\n\t\tvar vDev = self.controller.devices.get(device);\n\t\tif (vDev) {\n\t\t\tvDev.performCommand(action);\n\t\t}\n\t});\n};\n\nLightMotionRockerAutocontrol.prototype.turnLightsOn = function() {\n\tif (this.lightIs !== \"on\") {\n\t\tthis.lightIs = \"on\";\n\t\tthis.turnLights(\"on\");\n\t}\n};\n\nLightMotionRockerAutocontrol.prototype.turnLightsOff = function() {\n\tif (this.lightIs !== \"off\") {\n\t\tthis.lightIs = \"off\";\n\t\tthis.turnLights(\"off\");\n\t}\n};\n\nLightMotionRockerAutocontrol.prototype.rockerRelaxTimerStart = function() {\n\tvar self = this;\n\t\n\tif (this.rockerRelaxTimer) {\n\t\tclearTimeout(this.rockerRelaxTimer);\n\t\tthis.rockerRelaxTimer = null;\n\t}\n\tthis.rockerRelaxTimer = setTimeout(function() {\n\t\tself.rockerRelax = false;\n\t\tself.rockerRelaxTimer = null;\n\t}, this.config.rockerRelaxTime * 1000);\n\n\tthis.rockerRelax = true;\n};\n\nLightMotionRockerAutocontrol.prototype.rescueTimerStart = function() {\n\tvar self = this;\n\t\n\tif (this.rescueOffTimer) {\n\t\tclearTimeout(this.rescueOffTimer);\n\t\tthis.rescueOffTimer = null;\n\t}\n\tthis.rescueOffTimer = setTimeout(function() {\n\t\tself.turnLightsOff();\n\t\tself.rescueOffTimer = null;\n\t}, this.config.rescueOffTimeout * 1000);\n};\n\nLightMotionRockerAutocontrol.prototype.motionTimerStart = function() {\n\tvar self = this;\n\t\n\tif (this.motionOffTimer) {\n\t\tclearTimeout(this.motionOffTimer);\n\t\tthis.motionOffTimer = null;\n\t}\n\tthis.motionOffTimer = setTimeout(function() {\n\t\tself.turnLightsOff();\n\t\tself.rescueTimerStop();\n\t\tself.motionOffTimer = null;\n\t}, this.config.motionOffTimeout * 1000);\n};\n\nLightMotionRockerAutocontrol.prototype.rescueTimerStop = function() {\n\tif (this.rescueOffTimer) {\n\t\tclearTimeout(this.rescueOffTimer);\n\t\tthis.rescueOffTimer = null;\n\t}\n};\n\nLightMotionRockerAutocontrol.prototype.motionTimerStop = function() {\n\tif (this.motionOffTimer) {\n\t\tclearTimeout(this.motionOffTimer);\n\t\tthis.motionOffTimer = null;\n\t}\n};\n"
  },
  {
    "path": "modules/LightMotionRockerAutocontrol/lang/en.json",
    "content": "{\n\t\"m_title\": \"Light control by motion sensors and rockers\",\n\t\"m_descr\": \"Controls ligth switches via one or many motion sensors and any number of rockers. If rocker operation happened, motion does not turn on for a short time (rocker relax time). Once all motion sensors reported no motion, wait for a defined time (motion off period) and turn off light. Motion events are ignored if luminance is lower than a defined threshold. After some long time after last motion event or rocket on event turn off light (in case of low battery in one of the motion sensors).\",\n\t\"l_lights\": \"Light switch to turn on/off\",\n\t\"l_rockers\": \"Rockers and paddles for manual opration\",\n\t\"l_rockerRelaxTime\": \"Rocker relax time, seconds\",\n\t\"l_motions\": \"Motion sensors to track\",\n\t\"l_motionOffTimeout\": \"Time to wait before turning light off after all motion sensors are off, seconds\",\n\t\"l_luminance\": \"Light sensor\",\n\t\"l_luminanceThreshold\": \"Light threshold (in same units as light sensor reports)\",\n\t\"l_rescueOffTimeout\": \"Timeout to turn light off in case of low battery in one of motion sensors, seconds\"\n}\n"
  },
  {
    "path": "modules/LightMotionRockerAutocontrol/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"complex_applications\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"LightMotionRockerAutocontrol\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"lights\": [],\n\t\t\"rockers\": [],\n\t\t\"rockerRelaxTime\": 60,\n\t\t\"motions\": [],\n\t\t\"motionOffTimeout\": 300,\n\t\t\"luminance\": null,\n\t\t\"luminanceThreshold\": 0,\n\t\t\"rescueOffTimeout\": 3600\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"lights\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"rockers\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId,namespaces:devices_toggleButton:deviceId,namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"rockerRelaxTime\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"motions\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"motionOffTimeout\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"luminance\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"luminanceThreshold\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"rescueOffTimeout\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"lights\": {\n\t\t\t\t\"label\": \"__l_lights__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"rockers\": {\n\t\t\t\t\"label\": \"__l_rockers__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName,namespaces:devices_toggleButton:deviceName,namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"rockerRelaxTime\": {\n\t\t\t\t\"label\": \"__l_rockerRelaxTime__\"\n\t\t\t},\n\t\t\t\"motions\": {\n\t\t\t\t\"label\": \"__l_motions__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"motionOffTimeout\": {\n\t\t\t\t\"label\": \"__l_motionOffTimeout__\"\n\t\t\t},\n\t\t\t\"luminance\": {\n\t\t\t\t\"label\": \"__l_luminance__\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t},\n\t\t\t\"luminanceThreshold\": {\n\t\t\t\t\"label\": \"__l_luminanceThreshold__\"\n\t\t\t},\n\t\t\t\"rescueOffTimeout\": {\n\t\t\t\t\"label\": \"__l_rescueOffTimeout__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/LightScene/index.js",
    "content": "/*** LightScene Z-Way HA module *******************************************\n\nVersion: 1.1.1\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nChanged: Michael Hensche <mh@zwave.eu>\nDescription:\n\tImplements light scene based on virtual devices of type dimmer, switch or anothe scene\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction LightScene (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tLightScene.super_.call(this, id, controller);\n}\n\ninherits(LightScene, AutomationModule);\n\n_module = LightScene;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nLightScene.prototype.init = function (config) {\n\tLightScene.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"LightScene_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"toggleButton\",\n\t\t\tmetrics: {\n\t\t\t\tlevel: \"on\", // it is always on, but usefull to allow bind\n\t\t\t\ticon: \"scene\",\n\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command) {\n\t\t\tif (command !== 'on') return;\n\n\t\t\tself.config.switches.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.config.thermostats.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.config.dimmers.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.config.locks.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.config.scenes.forEach(function(scene) {\n\t\t\t\tvar vDev = self.controller.devices.get(scene);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tself.vDev.set(\"metrics:level\", \"on\"); // update on ourself to allow catch this event\n\t\t},\n\t\tmoduleId: this.id\n\t});\n};\n\nLightScene.prototype.stop = function () {\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tLightScene.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/LightScene/lang/de.json",
    "content": "{\n\t\"m_title\":\"Szene\",\n\t\"m_descr\":\"Die Lichtszene ist eine Basisfunktion des Smart Home. Mit nur einem Klick werden mehrere Geräte in einen individuellen Status geschalten. In Verwendung weiterer Apps wie “Delayed Scene” oder “Scheduled Scene” kann diese Szene automatisch in Abhängigkeit von generierten Ereignissen im Smart Home aktiviert werden. Die App erstellt ein neues Element zur Szenenauslösung. Der Einstelldialog ermöglicht die Auswahl von mehreren Schaltern und Dimmern sowie die Definition des gewünschten Schaltzustands eines jeden ausgewählten Gerätes.Desweiteren ist es möglich, andere Szenen als Teil dieser Szene auszulösen.Bitte beachten Sie, dass Dimmer einen Wert zwischen ‘0‘ und ‘100‘ bedürfen, während dessen bei Schaltungen zwischen ‘an‘ und ‘aus‘ gewählt wird. <br><br>Einstellungen:<br><ul><li>Wählen Sie alle Schalter, die zur Szene gehören sollen und definierten Sie den Schaltstatus als ‘an’ oder ‘aus’.</li><li>Wählen Sie alle Dimmer, die zur Szene gehören sollen und definieren Sie den Dimmpegel als einen Wert zwischen 0 und 100.</li><li>Auf Wunsch wählen Sie weitere Szenen, die mit dieser Szene ausgelöst werden sollen.</li></ul><br>Anwendung: Der Button auf dem Szenenelement aktiviert die definierte Szene. \",\n\t\"l_switches\":\"Schalter:\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerungen:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"Aktionen/Szenen die aktiviert werden sollen:\",\n\t\"l_thermostats\":\"Thermostate\",\n\t\"l_temperature\":\"Temperatur\",\n\t\"l_locks\":\"Türschlösser\",\n\t\"close\":\"Verriegelt\",\n\t\"open\":\"Entriegelt\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/LightScene/lang/en.json",
    "content": "{\n\t\"m_title\":\"Scene\",\n\t\"m_descr\":\"The scene is a basic function of a smart home. Multiple devices are switched into individual status by just one click. Using other apps like “Delayed Scene” or “Scheduled Scene” this scene can also be activated automatically depending on events generated in the Smart Home.  The app will create a new element to triggering the scene. The setup dialog allows selecting a series of switches and dimmers and defining the desired switching state of each individual device selected. Additionally it is possible to trigger other scenes as part of the scene. Please note that dimmers require a value between 0 and 100, while the switches can be selected between on and off.<br><br>Setup:<br><ul><li>Select all switches that shall belong to the scene and define the switching state as ‘on’ or ‘off’</li><li>Select all dimmers that shall belong to the scene and define the dimming level as a value between 0 und 100</li><li>Optionally select other scenes that shall be trigger with this scene.</li></ul><br>Usage: The toggle button on the scene element will activate the defined scene\",\n\t\"l_switches\":\"List of switches:\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"List of scenes to activate:\",\n\t\"l_thermostats\":\"List of thermostats\",\n\t\"l_temperature\":\"Temperature\",\n\t\"l_locks\":\"List of locks:\",\n\t\"close\":\"Close\",\n\t\"open\":\"Open\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/LightScene/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Сцена\",\n\t\"m_descr\":\"В сцене можно задать уровень освещения, включить или выключить лампы, открыть или закрыть жалюзи, задать температуру для термостатов.\",\n\t\"l_switches\":\"Список выключателей\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_dimmers\":\"Список диммеров\",\n\t\"l_level\":\"Уровень\",\n\t\"l_scenes\":\"Список сцен\",\n\t\"l_thermostats\":\"Список термостатов\",\n\t\"l_temperature\":\"Температура\",\n\t\"l_locks\":\"Список замков\",\n\t\"close\":\"Закрыть\",\n\t\"open\":\"Открыть\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Нужно чтобы не забивать сеть.\"\n}"
  },
  {
    "path": "modules/LightScene/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"LightScene\",\n\t\"version\": \"1.1.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"switches\": [],\n\t\t\"dimmers\": [],\n\t\t\"thermostats\": [],\n\t\t\"locks\":[],\n\t\t\"scenes\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"switches\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"dimmers\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"thermostats\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_thermostat:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"locks\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"enum\": [\"close\", \"open\"],\n\t\t\t\t\t\t\t\"default\" : \"open\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scenes\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"switches\": {\n\t\t\t\t\"label\": \"__l_switches__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\"]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"dimmers\": {\n\t\t\t\t\"label\": \"__l_dimmers__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_level__\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"thermostats\": {\n\t\t\t\t\"label\": \"__l_thermostats__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_thermostat:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_temperature__\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"locks\": {\n\t\t\t\t\"label\": \"__l_locks__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\"__close__\", \"__open__\"]\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"scenes\": {\n\t\t\t\t\"label\": \"__l_scenes__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/LightScene/patchnotes.txt",
    "content": "v1.1.1\n- change icon type form gesture to new icon type scene\n"
  },
  {
    "path": "modules/LogicalRules/index.js",
    "content": "/*** LogicalRules Z-Way HA module *******************************************\n\nVersion: 1.5\n(c) Z-Wave.Me, 2021\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Niels Roche <nir@zwave.eu>, Yurkin Vitaliy <aivs@z-wave.me>\nDescription:\n\tImplements logical rules and activates scene on rule match.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction LogicalRules (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tLogicalRules.super_.call(this, id, controller);\n\n\tvar self = this;\n\t\n\tthis.attachedList = [];\n\t\n\tthis._testRule = function () { // wrapper to correct this and parameters in testRule\n\t\tself.testRule.call(self, null);\n\t};\n}\n\ninherits(LogicalRules, AutomationModule);\n\n_module = LogicalRules;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nLogicalRules.prototype.init = function (config) {\n\tLogicalRules.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\t\n\tthis.config.tests.forEach(function(test) {\n\t\tif (test.testType === \"binary\") {\n\t\t\tself.attachDetach(test.testBinary, true);\n\t\t} else if (test.testType === \"multilevel\") {\n\t\t\tself.attachDetach(test.testMultilevel, true);\n\t\t} else if (test.testType === \"remote\") {\n\t\t\tself.attachDetach(test.testRemote, true);\n\t\t} else if (test.testType === \"sensorDiscrete\") {\n\t\t\tself.attachDetach(test.testSensorDiscrete, true);\n\t\t} else if (test.testType === \"nested\") {\n\t\t\ttest.testNested.tests.forEach(function(xtest) {\n\t\t\t\tif (xtest.testType === \"binary\") {\n\t\t\t\t\tself.attachDetach(xtest.testBinary, true);\n\t\t\t\t} else if (xtest.testType === \"multilevel\") {\n\t\t\t\t\tself.attachDetach(xtest.testMultilevel, true);\n\t\t\t\t} else if (xtest.testType === \"remote\") {\n\t\t\t\t\tself.attachDetach(xtest.testRemote, true);\n\t\t\t\t} else if (xtest.testType === \"sensorDiscrete\") {\n\t\t\t\t\tself.attachDetach(xtest.testSensorDiscrete, true);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\tif (this.config.eventSource) {\n\t\tthis.config.eventSource.forEach(function(scene) {\n\t\t\tself.controller.devices.on(scene, \"change:metrics:level\", self._testRule);\n\t\t});\n\t}\n};\n\nLogicalRules.prototype.stop = function () {\n\tvar self = this;\n\t\n\tif (this.config.eventSource) {\n\t\tthis.config.eventSource.forEach(function(scene) {\n\t\t\tself.controller.devices.off(scene, \"change:metrics:level\", self._testRule);\n\t\t});\n\t}\n\t \n\tthis.config.tests.forEach(function(test) {\n\t\tif (test.testType === \"binary\") {\n\t\t\tself.attachDetach(test.testBinary, false);\n\t\t} else if (test.testType === \"multilevel\") {\n\t\t\tself.attachDetach(test.testMultilevel, false);\n\t\t} else if (test.testType === \"remote\") {\n\t\t\tself.attachDetach(test.testRemote, false);\n\t\t} else if (test.testType === \"sensorDiscrete\") {\n\t\t\tself.attachDetach(test.testSensorDiscrete, false);\n\t\t} else if (test.testType === \"nested\") {\n\t\t\ttest.testNested.tests.forEach(function(xtest) {\n\t\t\t\tif (xtest.testType === \"binary\") {\n\t\t\t\t\tself.attachDetach(xtest.testBinary, false);\n\t\t\t\t} else if (xtest.testType === \"multilevel\") {\n\t\t\t\t\tself.attachDetach(xtest.testMultilevel, false);\n\t\t\t\t} else if (xtest.testType === \"remote\") {\n\t\t\t\t\tself.attachDetach(xtest.testRemote, false);\n\t\t\t\t} else if (xtest.testType === \"sensorDiscrete\") {\n\t\t\t\t\tself.attachDetach(xtest.testSensorDiscrete, false);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\tthis.attachedList = [];\n\t\n\tLogicalRules.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nLogicalRules.prototype.attachDetach = function (test, attachOrDetach) {\n\tif (this.config.triggerOnDevicesChange === false) { // this condition is used to allow empty triggerOnDevicesChange if old LogicalRules is used\n\t\treturn;\n\t}\n\t\n\tif (attachOrDetach) {\n\t\tif (this.attachedList.indexOf(test.device) === -1) {\n\t\t\tthis.attachedList.push(test.device);\n\t\t\tthis.controller.devices.on(test.device, \"change:metrics:level\", this._testRule);\n\t\t\tthis.controller.devices.on(test.device, \"change:metrics:change\", this._testRule);\n\t\t}\n\t} else {\n\t\tthis.controller.devices.off(test.device, \"change:metrics:level\", this._testRule);\n\t\tthis.controller.devices.off(test.device, \"change:metrics:change\", this._testRule);\n\t}\n};\n\nLogicalRules.prototype.testRule = function (tree) {\n\tvar res = null,\n\t\ttopLevel = !tree,\n\t\tself = this,\n\t\tlangFile = self.loadModuleLang();\n\t\n\tif (!tree) {\n\t\ttree = this.config;\n\t}\n\t\n\tif (tree.logicalOperator === \"and\") {\n\t\tres = true;\n\t\n\t\ttree.tests.forEach(function(test) {\n\t\t\tif (test.testType === \"multilevel\") {\n\t\t\t\tres = res && self.op(self.controller.devices.get(test.testMultilevel.device).get(\"metrics:level\"), test.testMultilevel.testOperator, test.testMultilevel.testValue);\n\t\t\t} else if (test.testType === \"binary\") {\n\t\t\t\tres = res && (self.controller.devices.get(test.testBinary.device).get(\"metrics:level\") === test.testBinary.testValue);\n\t\t\t} else if (test.testType === \"remote\") {\n\t\t\t\tvar dev = self.controller.devices.get(test.testRemote.device);\n\t\t\t\tres = res && ((_.contains([\"on\", \"off\"], test.testRemote.testValue) && dev.get(\"metrics:level\") === test.testRemote.testValue) || (_.contains([\"upstart\", \"upstop\", \"downstart\", \"downstop\"], test.testRemote.testValue) && dev.get(\"metrics:change\") === test.testRemote.testValue));\n\t\t\t} else if (test.testType === \"sensorDiscrete\") {\n\t\t\t\tres = res && (self.controller.devices.get(test.testSensorDiscrete.device).get(\"metrics:level\") === test.testSensorDiscrete.testValue);\n\t\t\t} else if (test.testType === \"time\") {\n\t\t\t\tvar curTime = new Date(),\n\t\t\t\t\ttime_arr = test.testTime.testValue.split(\":\").map(function(x) { return parseInt(x, 10); });\n\t\t\t\tres = res && self.op(curTime.getHours() * 60 + curTime.getMinutes(), test.testTime.testOperator, time_arr[0] * 60 + time_arr[1]);\n\t\t\t} else if (test.testType === \"nested\") {\n\t\t\t\tres = res && self.testRule(test.testNested);\n\t\t\t}\n\t\t});\n\t} else if (tree.logicalOperator === \"or\") {\n\t\tres = false;\n\t\n\t\ttree.tests.forEach(function(test) {\n\t\t\tif (test.testType === \"multilevel\") {\n\t\t\t\tres = res || self.op(self.controller.devices.get(test.testMultilevel.device).get(\"metrics:level\"), test.testMultilevel.testOperator, test.testMultilevel.testValue);\n\t\t\t} else if (test.testType === \"binary\") {\n\t\t\t\tres = res || (self.controller.devices.get(test.testBinary.device).get(\"metrics:level\") === test.testBinary.testValue);\n\t\t\t} else if (test.testType === \"remote\") {\n\t\t\t\tvar dev = self.controller.devices.get(test.testRemote.device);\n\t\t\t\tres = res || ((_.contains([\"on\", \"off\"], test.testRemote.testValue) && dev.get(\"metrics:level\") === test.testRemote.testValue) || (_.contains([\"upstart\", \"upstop\", \"downstart\", \"downstop\"], test.testRemote.testValue) && dev.get(\"metrics:change\") === test.testRemote.testValue));\n\t\t\t} else if (test.testType === \"sensorDiscrete\") {\n\t\t\t\tres = res || (self.controller.devices.get(test.testSensorDiscrete.device).get(\"metrics:level\") === test.testSensorDiscrete.testValue);\n\t\t\t} else if (test.testType === \"time\") {\n\t\t\t\tvar curTime = new Date(),\n\t\t\t\t\ttime_arr = test.testTime.testValue.split(\":\").map(function(x) { return parseInt(x, 10); });\n\t\t\t\tres = res || self.op(curTime.getHours() * 60 + curTime.getMinutes(), test.testTime.testOperator, time_arr[0] * 60 + time_arr[1]);\n\t\t\t} else if (test.testType === \"nested\") {\n\t\t\t\tres = res || self.testRule(test.testNested);\n\t\t\t}\n\t\t});\n\t}\n\t\n\tif (topLevel && res) {\n\t\ttree.action.switches && tree.action.switches.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") !== devState.status)) {\n\t\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\ttree.action.dimmers && tree.action.dimmers.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") !== devState.status)) {\n\t\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\ttree.action.thermostats && tree.action.thermostats.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") !== devState.status)) {\n\t\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\ttree.action.locks && tree.action.locks.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") !== devState.status)) {\n\t\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\ttree.action.scenes && tree.action.scenes.forEach(function(scene) {\n\t\t\tvar vDev = self.controller.devices.get(scene);\n\t\t\tif (vDev) {\n\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t}\n\t\t});\n\t}\n\n\treturn res;\n};\n\nLogicalRules.prototype.op = function (dval, op, val) {\n\tif (op === \"=\") {\n\t\treturn dval === val;\n\t} else if (op === \"!=\") {\n\t\treturn dval !== val;\n\t} else if (op === \">\") {\n\t\treturn dval > val;\n\t} else if (op === \"<\") {\n\t\treturn dval < val;\n\t} else if (op === \">=\") {\n\t\treturn dval >= val;\n\t} else if (op === \"<=\") {\n\t\treturn dval <= val;\n\t}\n\t\t\n\treturn null; // error!!  \n};\n"
  },
  {
    "path": "modules/LogicalRules/lang/de.json",
    "content": "{\n\t\"m_title\":\"Logische Regel\",\n\t\"m_descr\":\"Diese App ist die bei Weitestem komplexeste aber auch leistungsfähigste App, die in Ihrem Gateway vorinstalliert ist.Sie erlaubt die logische Kombination mehrerer Zustände und Ereignisse zur Verwendung der Booleschen Befehle UND, ODER und NICHT. Zur Verwendung dieses Widgets benötigen Sie das Grundwissen über Boolesche Logik und/ oder Softwareentwicklung.Bitte beachten Sie, dass die Booleschen Logik letztendlich auf die Auslösung einer Aktion hinaus läuft. Das heißt, Sie benötigen zumindest ein (dynamisches) Ursprungsereignis, welches wesentlich mehr (statische) Statusinformation auslöst, von denen Sie die Aktion abhängig machen können. Es ist nicht angebracht, zwei Ereignisse zu kombinieren, da die finale Aktion nur eintritt, wenn beide Ereignisse zur gleichen Zeit auftreten. Das ist eher unwahrscheinlich. Der Unterschied zwischen einem dynamischen Ereignis und einem statischen Zustand kann mit der Verwendung eines einfachen Bewegungssensors erklärt werden. Das dynamische Ereignis ist der Moment, wenn der Bewegungssensor auslöst. Der statische Zustand ist die Information, dass der Bewegungssensor sich aktuell im auslösenden Status befindet (eine Bewegung erkannt hat und einige Sekunden wartet, bevor er wieder in den inaktiven Modus zurückkehrt).<br><br>Einstellungen: Wählen Sie Statusinformation und Ereignis, welche Sie sinnvoll mit einander kombinieren wollen und wählen Sie den Booleschen Befehl, diese zu verbinden.\",\n\t\"rl_options\":\"Führe eine Regelprüfung bei jeder Änderung eines Zustandes, der unter 'Bedingungen' gelisteten Geräte durch.\",\n\t\"l_eventSource\":\"Führe eine Regelprüfung bei der Aktivierung folgender Szenen durch:\",\n\t\"h_eventSource\":\"When you start any scene from the list below, this logical rule will be checked. If necessary, you can run a logical rule by time: 1) Create a scene 2) Run the scene on a schedule 3) Select the created scene from the list below.\",\n\t\"l_logicalOperator\":\"Boolescher Operator\",\n\t\"h_logicalOperator\":\"Diese Option verknüpft alle folgenden Bedingungen mit einer logischen OR (ODER) oder AND (UND) Regel. Bei OR wird die Aktion ausgeführt, wenn mindestens eine Bedingung zutrifft. Bei AND wird die Aktion nur ausgeführt, wenn alle Bedingung zutreffen.\",\n\t\"l_tests\":\"Bedingungen\",\n\t\"l_testBinary\":\"Binäre Schalter/Sensoren\",\n\t\"l_testMultilevel\":\"Dimmer/Motorsteuerung/Analoge Sensoren/Batterien\",\n\t\"l_testRemote\":\"Schaltsteuerung/Szenen\",\n\t\"l_testTime\":\"Zeit\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_testNested\":\"Verschachtelt\",\n\t\"l_action\":\"Aktionen:\",\n\t\"l_switches\":\"Binäre Schalter:\",\n\t\"l_thermostats\":\"Thermostats\",\n\t\"off\":\"Aus\",\n\t\"on\":\"An\",\n\t\"upstart\":\"Aufwärts: start\",\n\t\"upstop\":\"Aufwärts: stop\",\n\t\"downstart\":\"Abwärts: start\",\n\t\"downstop\":\"Abwärts: stop\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerung:\",\n\t\"l_status\":\"Level\",\n\t\"l_locks\":\"Türschlösser\",\n\t\"close\":\"Verriegelt\",\n\t\"open\":\"Entriegelt\",\n\t\"l_scenes\":\"Zu aktivierende Szenen/Aktionen:\",\n\t\"or\": \"OR\",\n\t\"and\": \"AND\",\n\t\"l_testType\": \"Typ der Bedingung:\",\n\t\"h_testNested\": \"Erzeugt weitere verschachtelte Bedingungen - logische Schreibweise: A AND B AND (C OR D). Die zusätzliche verschachtelte Bedingung ist (C OR D). Eine Aktion wird also nur dann ausgelöst, wenn die Bedingungen A und B sowie entweder die Bedingung C oder D gemeinsam erfüllt sind. Beispiel: Wenn außen der Lichtsensor A > 80% und der Temperatursensor B > 26°C und (Zeit < 12:00 Uhr oder Zeit > 14:00 Uhr) dann wird die Jalousie im Wohnzimmer auf 50% gesetzt.\",\n\t\"l_sendAction\":\"Sende kein 'An' Kommando, wenn das Gerät bereits aktiviert ist. Das Gleiche gilt für 'Aus'.\",\n\t\"h_sendAction\":\"Verhindert überflüssige Befehle im Netzwerk.\",\n\t\"h_testTime\":\"Diese Bedingung überprüft, ob die aktuelle Zeit Kleiner-Gleich oder Größer-Gleich der eingegebenen ist. Z.B aktuelle Zeit: 09:00 und Bedingung: >= 10:00 würde ein 'false' zurückliefern und die Regel nicht auslösen. 24-h-Format - hh:mm\",\n\t\"h_triggerOnDevicesChange\": \"Standardmäßig achtet die logische Regel auf alle Änderungen von Geräten, die unter Bedingungen aufgelistet sind. Wird eine Änderung durch die logische Regel erkannt, wird geprüft, ob eine Aktion ausgelöst werden soll oder nicht. Deaktivieren Sie diese Option, wenn die logische Regel Bedingung nur bei ausgelösten Szenen geprüft werden soll. Es wird empfohlen, dieses Feld in Kombination mit der Option' Regelprüfung bei Aktivierung der folgenden Szenen auslösen' zu verwenden.\",\n    \"l_sensorDiscrete\":\"Scene Controller\",\n    \"l_choose_dev\":\"--- Choose a device ---\",\n    \"l_controller_action\":\"Controller Actions\",\n\t\"h_controller_action\":\"The action is described with a two-digit value: The first digit is the button number, the second digit points to the action of this button (0=short press, 1=release, 2=hold, 3=short press two times, 4 = short press three times, and so on. Examples: Double Click button 2 => 23, Single Click button 1 = 10)\"\n}"
  },
  {
    "path": "modules/LogicalRules/lang/en.json",
    "content": "{\n\t\"m_title\":\"Logical Rule\",\n\t\"m_descr\":\"This app is the by far most complex but also most powerful app preloaded to your gateway. It allows to combine multiple status and events in a logical way using the Boolean operators AND, OR and NOT. You need to have basic knowledge about Boolean logic and/or software development to properly use this widget. Please note that the final target of the Boolean logic is to trigger an action. This mean you need at least one (dynamic) event source that essentially triggers but many more (static) status information that you can make the action depending on. It is not suitable to combine two events because the final action will only happen if both events would occur at the very same moment. This is quite unlikely. The difference between a dynamic event and a static status can be explained using a simple motion sensor. The dynamic event is the moment when the motion sensor trips. The static status is the information if the motion sensor is actually in tripped state (has just detected a motion and wait for a few seconds before turning back into inactivity mode).<br><br>Settings: Select the status information and the events you want to logically combine and select the Boolean operators to combine them.\",\n\t\"rl_options\":\"Trigger the rule check on change of any device mentioned in conditions.\",\n\t\"l_eventSource\":\"Trigger the rule check on activation of the following scenes:\",\n\t\"h_eventSource\":\"When you start any scene from the list below, this logical rule will be checked. If necessary, you can run a logical rule by time: 1) Create a scene 2) Run the scene on a schedule 3) Select the created scene from the list below.\",\n\t\"l_logicalOperator\":\"Boolean operator\",\n\t\"h_logicalOperator\":\"This option links all following conditions with a logical 'OR' or 'AND' rule. 'OR' will trigger an action if at least one condition is true. 'AND' will only trigger an action if all conditions are true.\",\n\t\"l_tests\":\"Conditions\",\n\t\"l_testBinary\":\"Binary condition\",\n\t\"l_testMultilevel\":\"Multilevel condition\",\n\t\"l_testRemote\":\"Remote condition\",\n\t\"l_testTime\":\"Time condition\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_testNested\":\"Nested conditions\",\n\t\"l_action\":\"Actions\",\n\t\"l_switches\":\"List of switches:\",\n\t\"l_thermostats\":\"List of thermostats\",\n\t\"off\":\"Off\",\n\t\"on\":\"On\",\n\t\"upstart\":\"Up start\",\n\t\"upstop\":\"Up stop\",\n\t\"downstart\":\"Down start\",\n\t\"downstop\":\"Down stop\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_status\":\"Level\",\n\t\"l_locks\":\"List of locks:\",\n\t\"close\":\"Close\",\n\t\"open\":\"Open\",\n\t\"l_scenes\":\"List of scenes to activate:\",\n\t\"or\": \"OR\",\n\t\"and\": \"AND\",\n\t\"l_testType\": \"Type of condition:\",\n\t\"h_testNested\": \"Add a new nested condition - like in logical notation: A AND B AND (C OR D). The additional nested condition is (C OR D). An action is only triggered if the conditions A and B and either the condition C or D are met together. Example: If outside the light sensor A > 80% and the temperature sensor B > 26°C and (time < 12:00 am or time > 02:00 pm) then the jalousie in the living room is set to 50%.\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off. Need to avoid flooding the network.\",\n\t\"h_sendAction\":\"Prevents unnecessary network commands.\",\n\t\"h_testTime\":\"This condition checks if the current time is 'less than or equal to' or 'greater than or equal to' the entered time. E.g. current time: 09:00 and condition: >= 10:00 will return 'false' and not pass the rule. 24-h-format - hh:mm\",\n\t\"h_triggerOnDevicesChange\": \"By default the logical rule listens to all changes of devices listed in conditions. If a change is recognized by the logical rule it will check the condition wether to trigger an action or not. Deactivate this option if the logical rule condition should only be checked by triggered scenes. It is recommented to use this field in combination with 'Trigger the rule check on activation of the following scenes' option.\",\n    \"l_sensorDiscrete\":\"Scene Controller\",\n    \"l_choose_dev\":\"--- Choose a device ---\",\n    \"l_controller_action\":\"Controller Actions\",\n\t\"h_controller_action\":\"The action is described with a two-digit value: The first digit is the button number, the second digit points to the action of this button (0=short press, 1=release, 2=hold, 3=short press two times, 4 = short press three times, and so on. Examples: Double Click button 2 => 23, Single Click button 1 = 10)\"\n}\n"
  },
  {
    "path": "modules/LogicalRules/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Логические правила\",\n\t\"m_descr\":\"Используя логические правила можно составлять сценарии следующих типов:<ul><li>Если сработал датчик, то выполнить действие</li><li>Если сработал датчик 1 И датчик 2, то выполнить действие</li><li>Если сработал датчик 1 ИЛИ датчик 2, то выполнить действие</li></ul>С помощью вложенных условий возможно создавать правила с более сложной логикой.\",\n\t\"rl_options\":\"Выполнить проверку при срабатывании любого устройства из условий\",\n\t\"l_eventSource\":\"Выполнить проверку при запуске любой из сцен:\",\n\t\"h_eventSource\":\"При запуске любой сцены из списка ниже будет запускаться проверка этого логического правила. Если необходимо, то можно выполнять логическое правило по времени: 1) Создайте сцену 2) Запускайте сцену по расписанию 3) Выберите созданную сцену из списка ниже.\",\n\t\"l_logicalOperator\":\"Логический оператор\",\n\t\"h_logicalOperator\":\"Все условия связываются одним из логических операторов И/ИЛИ.</br>ИЛИ вызовет действие, если хотя бы одно условие истинно.</br>И вызовет действие только в том случае, если все условия истинны.\",\n\t\"l_tests\":\"Условия\",\n\t\"l_testBinary\":\"Условие бинарных устройств\",\n\t\"l_testMultilevel\":\"Условие многоуровневых датчиков\",\n\t\"l_testRemote\":\"Условие кнопок пульта\",\n\t\"l_testTime\":\"Условие по времени\",\n\t\"timeFormat\":\"чч:мм\",\n\t\"l_testNested\":\"Вложенные условия\",\n\t\"l_action\":\"Действия\",\n\t\"l_switches\":\"Список выключателей\",\n\t\"l_thermostats\":\"Список термостатов\",\n\t\"off\":\"Выключить\",\n\t\"on\":\"Включить\",\n\t\"upstart\":\"Вверх старт\",\n\t\"upstop\":\"Вверх стоп\",\n\t\"downstart\":\"Вниз старт\",\n\t\"downstop\":\"Вниз стоп\",\n\t\"l_dimmers\":\"Список диммеров\",\n\t\"l_status\":\"Уровень\",\n\t\"l_locks\":\"Список замков\",\n\t\"close\":\"Закрыть\",\n\t\"open\":\"Открыть\",\n\t\"l_scenes\":\"Список сцен\",\n\t\"or\": \"ИЛИ\",\n\t\"and\": \"И\",\n\t\"l_testType\": \"Тип условия:\",\n\t\"h_testNested\": \"Добавьте новое вложенное условие, по аналогии с логической нотацией: (A 'И' B) 'И' (C 'ИЛИ' D). Дополнительным вложенным условием является (C 'ИЛИ' D). Действие запускается только в том случае, если условия (A 'И' B) и условия (C 'ИЛИ' D) выполняются одновременно. Пример: если (датчик освещенности A > 80%) 'И' (датчик температуры B > 26°C) 'И' (время < 12:00 'ИЛИ' время > 14:00), то жалюзи в гостиной выставляются на 50%.\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Уменьшает нагрузку на Z-Wave сеть для лучшего быстродействия.\",\n\t\"h_testTime\":\"Это условие проверяет, является ли текущее время 'меньше или равно' или 'больше или равно' введенному времени. Например, если текущее время: 09:00, а введенное время >= 10:00, то условие не выполнится. Формат 24ч - чч:мм.\",\n\t\"h_triggerOnDevicesChange\": \"Если отключить эту функцию, то проверка правила будет выполняться только при срабатывании сцен из списка ниже. Срабатывание устройств из условий не будет запускать проверку.\",\n    \"l_sensorDiscrete\":\"Условие контроллера сцен\",\n    \"l_choose_dev\":\"--- Выберите устройство ---\",\n    \"l_controller_action\":\"Событие от контроллера сцен\",\n\t\"h_controller_action\":\"Событие описывается двузначным значением: первая цифра - номер кнопки, вторая цифра - действие кнопки (0=одинарное нажатие, 1=отпускание, 2=удержание, 3=двойное нажатие, 4=тройное нажатие и т. д. Примеры: Кнопка 2 + Двойное нажатие => 23, Кнопка 1 + Одинарное нажатие => 10)\"\n\n}"
  },
  {
    "path": "modules/LogicalRules/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"LogicalRules\",\n\t\"version\": \"1.5\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"triggerOnDevicesChange\": true,\n\t\t\"eventSource\": [],\n\t\t\"logicalOperator\": \"and\",\n\t\t\"tests\": [],\n\t\t\"action\": {}\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"logicalOperator\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"and\", \"or\"],\n\t\t\t\t\"default\": \"and\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"tests\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"testType\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\"binary\",\n\t\t\t\t\t\t\t\t\"multilevel\",\n\t\t\t\t\t\t\t\t\"remote\",\n\t\t\t\t\t\t\t\t\"sensorDiscrete\",\n\t\t\t\t\t\t\t\t\"time\",\n\t\t\t\t\t\t\t\t\"nested\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"default\": \"binary\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testBinary\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testMultilevel\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_battery:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"=\", \"!=\", \">\", \">=\", \"<\", \"<=\"],\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"number\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testRemote\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchControl:deviceId,namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\", \"upstart\", \"upstop\", \"downstart\", \"downstop\"],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testSensorDiscrete\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorDiscrete:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testTime\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\">=\", \"<=\"],\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"format\": \"time\",\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testNested\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"logicalOperator\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"and\", \"or\"],\n\t\t\t\t\t\t\t\t\t\"default\": \"or\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"tests\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"testType\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"binary\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"multilevel\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"remote\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"sensorDiscrete\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"time\"\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\t\t\t\"default\": \"binary\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"testBinary\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"testMultilevel\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_battery:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\"=\", \"!=\", \">\", \">=\", \"<\", \"<=\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"number\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"testRemote\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchControl:deviceId,namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\", \"upstart\", \"upstop\", \"downstart\", \"downstop\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"testSensorDiscrete\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorDiscrete:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"testTime\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\">=\", \"<=\"],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"format\": \"time\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"action\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"switches\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"],\n\t\t\t\t\t\t\t\t\t\"default\": \"on\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dimmers\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\"maximum\": 99\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"thermostats\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_thermostat:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\"maximum\": 99\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"locks\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"enum\": [\"close\", \"open\"],\n\t\t\t\t\t\t\t\t\t\"default\": \"open\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\": false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scenes\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"triggerOnDevicesChange\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"eventSource\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"renderform\": \"true\",\n\t\t\"fields\": {\n\t\t\t\"logicalOperator\": {\n\t\t\t\t\"label\": \"__l_logicalOperator__\",\n\t\t\t\t\"optionLabels\": [\"__and__\", \"__or__\"],\n\t\t\t\t\"helper\": \"__h_logicalOperator__\",\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"tests\": {\n\t\t\t\t\"label\": \"__l_tests__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"testType\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"label\": \"__l_testType__\",\n\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\"__l_testBinary__\",\n\t\t\t\t\t\t\t\t\t\"__l_testMultilevel__\",\n\t\t\t\t\t\t\t\t\t\"__l_testRemote__\",\n\t\t\t\t\t\t\t\t\t\"__l_sensorDiscrete__\",\n\t\t\t\t\t\t\t\t\t\"__l_testTime__\",\n\t\t\t\t\t\t\t\t\t\"__l_testNested__\"\n\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\"default\": \"\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testBinary\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"binary\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\"]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testMultilevel\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"multilevel\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_battery:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"=\", \"≠\", \">\", \"≥\", \"<\", \"≤\"]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testRemote\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"remote\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchControl:deviceName,namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\", \"__upstart__\", \"__upstop__\", \"__downstart__\", \"__downstop__\"]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testSensorDiscrete\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"sensorDiscrete\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorDiscrete:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_controller_action__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_controller_action__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testTime\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"time\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"helper\": \"__h_testTime__\",\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"≥\", \"≤\"]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"time\",\n\t\t\t\t\t\t\t\t\t\t\"maskString\": \"99:99\",\n\t\t\t\t\t\t\t\t\t\t\"dateFormat\": \"HH:mm\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testNested\": {\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"nested\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"helper\": \"__h_testNested__\",\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"logicalOperator\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_logicalOperator__\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__and__\", \"__or__\"],\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_logicalOperator__\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"tests\": {\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testType\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_testType__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"__l_testBinary__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"__l_testMultilevel__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"__l_testRemote__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"__l_sensorDiscrete__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"__l_testTime__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"default\": \"\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testBinary\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testType\": \"binary\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\"]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testMultilevel\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testType\": \"multilevel\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_battery:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"=\", \"≠\", \">\", \"≥\", \"<\", \"≤\"]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testRemote\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testType\": \"remote\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchControl:deviceName,namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\", \"__upstart__\", \"__upstop__\", \"__downstart__\", \"__downstop__\"]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testSensorDiscrete\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testType\": \"sensorDiscrete\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorDiscrete:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_controller_action__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_controller_action__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"testTime\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testType\": \"time\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_testTime__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"time\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"maskString\": \"99:99\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dateFormat\": \"HH:mm\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"≥\", \"≤\"]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"action\": {\n\t\t\t\t\"label\": \"__l_action__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"switches\": {\n\t\t\t\t\t\t\"label\": \"__l_switches__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\"]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dimmers\": {\n\t\t\t\t\t\t\"label\": \"__l_dimmers__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_status__\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"integer\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"thermostats\": {\n\t\t\t\t\t\t\"label\": \"__l_thermostats__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_thermostat:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_status__\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"integer\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"locks\": {\n\t\t\t\t\t\t\"label\": \"__l_locks__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__close__\", \"__open__\"]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scenes\": {\n\t\t\t\t\t\t\"label\": \"__l_scenes__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"triggerOnDevicesChange\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_options__\",\n\t\t\t\t\"helper\": \"__h_triggerOnDevicesChange__\"\n\t\t\t},\n\t\t\t\"eventSource\": {\n\t\t\t\t\"label\": \"__l_eventSource__\",\n\t\t\t\t\"helper\": \"__h_eventSource__\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/LogicalRules/patchnotes.txt",
    "content": "v1.2.2\n- german translations added\n- helper label for time condition added\n\nv1.2.1\n- Added option to LogicalRules - don't send On command if device already turned on,similarly for Off\n\nv1.2.0\n- ui form structure refactored to reduce overhead\n- translations added (ru translations in english)\n- descriptions and examples added for a better usability\n\nv1.1.1\n- format of time input field changed (HH:mm 24h)\n- version number corrected now 1.1.1"
  },
  {
    "path": "modules/MQTTClient/index.js",
    "content": "/*** MQTT Client Z-Way HA module ****************************************************\n\nVersion: 1.3\n(c) Z-Wave.Me, 2023\n-----------------------------------------------------------------------------\nAuthor: Yurkin Vitaliy <aivs@z-wave.me>\nDescription:\n   Publishes the devices status to a MQTT topics and receives device control commands.\n *****************************************************************************/\n\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction MQTTClient(id, controller) {\n\tMQTTClient.super_.call(this, id, controller);\n\n\t// Create instance variables\n\tthis.reconnectInterval = null;\n};\n\ninherits(MQTTClient, AutomationModule);\n\n_module = MQTTClient;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nMQTTClient.prototype.init = function(config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tMQTTClient.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\tvar mqttConnected = false;\n\tvar mqttConnectionAttempts = 0;\n\n\tvar vDev = this.controller.devices.create({\n\t\tdeviceId: \"MQTTClient\" + this.id,\n\t\tdefaults: {\n\t\t\tmetrics: {\n\t\t\t\ttitle: \"MQTT Client Connection Status \" + this.config.host\n\t\t\t}\n\t\t},\n\t\toverlay: {\n\t\t\tdeviceType: \"text\",\n\t\t\tmetrics: {\n\t\t\t\ttext: \"Not connected\",\n\t\t\t\ticon: \"/ZAutomation/api/v1/load/modulemedia/MQTTClient/icon.png\"\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\n\tthis.updateSkippedDevicesList();\n\n\tvar clientId = this.config.clientId;\n\tif (this.config.clientIdRandomize)\n\t\tclientId += \"-\" + Math.random().toString(16).substr(2, 6);\n\n\t// 1 - Open MQTT Socket\n\tif (this.config.user && this.config.password)\n\t\tthis.m = new mqtt(this.config.host, this.config.port, this.config.user, this.config.password, clientId);\n\telse\n\t\tthis.m = new mqtt(this.config.host, this.config.port, clientId);\n\n\tif (this.config.security) {\n\t\ttry {\n\t\t\tthis.m.tlsset();\n\t\t} catch (e) {\n\t\t\tconsole.log(\"--- MQTTClient security error:\", e);\n\t\t}\n\t}\n\n\t// 2 - Init MQTT handlers\n\tthis.m.onconnect = function () {\n\t\tconsole.log(\"--- MQTTClient connected to\", self.config.host);\n\t\tvDev.set(\"metrics:text\", \"Connected to \" + self.config.host);\n\t\tclearInterval(self.reconnectInterval);\n\t\tself.reconnectInterval = null;\n\t\tmqttConnected = true;\n\t\tmqttConnectionAttempts = 0;\n\t\tthis.subscribe(self.config.topicPrefix + \"/\" + self.config.topicPostfixSet + \"/#\");\n\t\tself.controller.devices.on(\"change:metrics:level\", self.onLevelChanged);\n\t};\n\n\tthis.m.ondisconnect = function () {\n\t\tconsole.log(\"--- MQTTClient disconnected\");\n\t\tvDev.set(\"metrics:text\", \"Disconnected. Trying to connect every 1 second\");\n\t\tmqttConnected = false;\n\t\tmqttConnectionAttempts = 0;\n\t\tself.controller.devices.off(\"change:metrics:level\", self.onLevelChanged);\n\t};\n\n\tthis.m.onmessage = function (topic, byteArrayMsg) {\n\t\tvar msg = byteArrayToString(byteArrayMsg);\n\t\tvar channels = topic.split(\"/\"),\n\t\t\tvDevId = channels[channels.length - 1],\n\t\t\tvDevFound = false;\n\n\t\tself.controller.devices.forEach(function(vDev) {\n\t\t\tif (vDev.id === vDevId) {\n\t\t\t\tvDevFound = true;\n\t\t\t\tvar deviceType = vDev.get(\"deviceType\");\n\t\t\t\tif (deviceType === \"switchMultilevel\") {\n\t\t\t\t\tvDev.performCommand(\"exact\", {level: parseInt(msg)});\n\t\t\t\t}\n\t\t\t\telse if (deviceType === \"thermostat\") {\n\t\t\t\t\tvDev.performCommand(\"exact\", {level: parseFloat(msg)});\n\t\t\t\t}\n\t\t\t\telse if (deviceType === \"switchRGBW\") {\n\t\t\t\t\trgb = msg.split(\",\")\n\t\t\t\t\tvDev.performCommand(\"exact\", {red: rgb[0], green: rgb[1], blue: rgb[2]});\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// on, off, stop, open, close and custom command\n\t\t\t\t\tvDev.performCommand(msg);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\t\n\t\tif (!vDevFound) {\n\t\t\tconsole.log(\"--- MQTTClient: Device \" + vDevId + \" Not Found\");\n\t\t}\n\t};\n\n\tthis.onLevelChanged = function(vDev) {\n\t\t// if Not mqtt-skip, then publish device status and full data\n\t\tif (vDev.get(\"tags\").indexOf(\"mqtt-skip\") === -1) {\n\t\t\tif (self.config.topicPostfixStatus) {\n\t\t\t\tself.m.publish(self.config.topicPrefix + \"/\" + self.config.topicPostfixStatus + \"/\" + vDev.id, vDev.get(\"metrics:level\").toString());\n\t\t\t}\n\t\t\tif (self.config.topicPostfixData) {\n\t\t\t\tself.m.publish(self.config.topicPrefix + \"/\" + self.config.topicPostfixData + \"/\" + vDev.id, JSON.stringify(vDev));\n\t\t\t}\n\t\t}\n\t};\n\n\tthis.onTagsChanged = function(vDev) {\n\t\t// Add tag \"mqtt-skip\" to skipped Devices list in config\n\t\tif (vDev.get(\"tags\").indexOf(\"mqtt-skip\") !== -1 && self.config.skippedDevices.indexOf(vDev.id) === -1) {\n\t\t\tself.config.skippedDevices.push(vDev.id);\n\t\t\tself.saveConfig();\n\t  \t}\n\n\t  \t// Remove tag \"mqtt-skip\" from skipped Devices list in config\n\t  \tif (vDev.get(\"tags\").indexOf(\"mqtt-skip\") === -1 && self.config.skippedDevices.indexOf(vDev.id) !== -1) {\n\t  \t\tvar index = self.config.skippedDevices.indexOf(vDev.id);\n\t\t\tself.config.skippedDevices.splice(index, 1);\n\t\t\tself.saveConfig();\n\t  \t}\n\t};\n\n\tthis.controller.devices.on(\"change:tags\", this.onTagsChanged);\n\n\t// 3 - Connect\n\ttry {\n\t\tmqttConnectionAttempts = mqttConnectionAttempts + 1;\n\t\tconsole.log(\"--- MQTTClient attempt to connect first time...\");\n\t\tvDev.set(\"metrics:text\", \"Attempt to connect first time...\");\n\t\tself.m.connect();\n\t} catch (err) {\n\t\tconsole.log(\"--- MQTTClient connection error\", self.config.host, err, \"Reconnect after 5 seconds...\");\n\t\tvDev.set(\"metrics:text\", \"--- MQTTClient connection error: \" + err);\n\t}\n\n\t// Check connection after 5 seconds\n\tself.reconnectInterval = setInterval(function() {\n\t\tif (!mqttConnected) {\n\t\t\ttry {\n\t\t\t\tmqttConnectionAttempts = mqttConnectionAttempts + 1;\n\t\t\t\tconsole.log(\"--- MQTTClient attempts to connect \" + mqttConnectionAttempts + \" ...\");\n\t\t\t\tvDev.set(\"metrics:text\", \"Attempts to connect \" + mqttConnectionAttempts + \" ...\");\n\t\t\t\tself.m.connect();\n\t\t\t} catch (err) {\n\t\t\t\tconsole.log(\"--- MQTTClient connection error\", self.config.host, err, \"Reconnect after 5 seconds...\");\n\t\t\t\tvDev.set(\"metrics:text\", \"--- MQTTClient connection error: \" + err);\n\t\t\t}\n\t\t}\n\t}, 5000);\n};\n\nMQTTClient.prototype.stop = function () {\n\tvar self = this;\n\tthis.controller.devices.off(\"change:metrics:level\", this.onLevelChanged);\n\tthis.controller.devices.off(\"change:tags\", this.onTagsChanged);\n\tclearInterval(this.reconnectInterval);\n\tthis.reconnectInterval = null;\n\tthis.controller.devices.remove(\"MQTTClient\" + this.id);\n\n    try {\n            self.m.disconnect();\n            console.log(\"--- MQTTClient disconnected from\", self.config.host);\n    } catch (err) {\n            console.log(\"--- MQTTClient disconnect error from\", self.config.host, err);\n    }\n\n\tMQTTClient.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nMQTTClient.prototype.updateSkippedDevicesList = function () {\n\tvar self = this\n\n\t// Add tag \"mqtt-skip\" for all skipped devices from config\n\tthis.config.skippedDevices.forEach(function(vDevId) {\n\t\tvar vDev = self.controller.devices.get(vDevId);\n  \t\tif (vDev !== null && vDev.get(\"tags\").indexOf(\"mqtt-skip\") === -1 ) {\n  \t\t\tvDev.addTag(\"mqtt-skip\");\n  \t\t}\n\t});\n\n\t// Remove tag \"mqtt-skip\" if device not in skipped list\n\tthis.controller.devices.forEach(function(vDev) {\n\t\tif (vDev !== null \n\t\t\t&& vDev.get(\"tags\").indexOf(\"mqtt-skip\") !== -1\n\t\t\t&& self.config.skippedDevices.indexOf(vDev.id) === -1) {\n  \t\t\t\tvDev.removeTag(\"mqtt-skip\");\n  \t\t}\n\t});\n};\n"
  },
  {
    "path": "modules/MQTTClient/lang/en.json",
    "content": "{\n\t\"m_title\" : \"MQTT Client\",\n\t\"m_descr\" : \"Publishes the devices data to a MQTT topics and receives device control commands.<br><br>Topics for publishes devices data:<ol><li>Only device status: <b>zway/status/DEVICE_ID</b></li><li>Full device data: <b>zway/data/DEVICE_ID</b></li><li>Full data for all devices: <b>zway/data/#</b></li></ol><br>To control devices publish a message with command to the topic <b>zway/set/DEVICE_ID</b>:<ol><li>'on', 'off' - relays</li><li>'open', 'close' - door locks</li><li>'on', 'off', level (25, 80, etc) - dimmers</li><li>'on', 'off', 'stop', level (25, 80, etc) - motors</li><li>level (25, 80, etc) - thermostats</li><li>rgb '0,127,255' (Red=0, Green=127, Blue=255) - Color Lamp/Strips</li></ol><br>Topics prefix (zway) and postfix (data, status, set) can be changed in the app settings. If you don't want to publish some devices to a MQTT add <b>mqtt-skip</b> tag to that device.\",\n\t\"client_id_label\": \"Client ID\",\n\t\"client_id_randomize_label\": \"Add random number to the client ID\",\n\t\"client_id_randomize_helper\": \"Needed for some MQTT brokers.\",\n\t\"host_label\": \"Hostname or IP address\",\n\t\"port_label\": \"Port\",\n\t\"security\": \"Security\",\n\t\"user_label\": \"Username\",\n\t\"user_helper\": \"If empty, the username is not used.\",\n\t\"password_label\": \"Password\",\n\t\"password_helper\": \"If empty, the password is not used.\",\n\t\"topic_prefix_label\": \"Topic prefix\",\n\t\"topic_postfix_status_label\": \"Topic postfix for publish device status\",\n\t\"topic_postfix_status_helper\": \"Publish only device status, like: 'on', 'off', '25.5', etc.\",\n\t\"topic_postfix_data_label\":\"Topic postfix for publish device data\",\n\t\"topic_postfix_data_helper\":\"Publish all device data, like: name, status, id, room, update time, etc.\",\n\t\"topic_postfix_set_label\": \"Topic postfix for setting the value\",\n\t\"topic_postfix_set_helper\": \"Publish a message with command to the set-topic to control device.\",\n\t\"skipped_devices_label\":\"Devices that should not be published in MQTT\",\n\t\"skipped_devices_helper\":\"<b>mqtt-skip</b> tag will be added to each selected device.\"\n}\n"
  },
  {
    "path": "modules/MQTTClient/module.json",
    "content": "{\n    \"singleton\": true,\n    \"dependencies\": [],\n    \"category\": \"support_external_ui\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://razberry.z-wave.me\",\n    \"icon\": \"icon.png\",\n    \"moduleName\": \"MQTTClient\",\n    \"version\": \"1.3\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"clientId\": \"zway\",\n        \"clientIdRandomize\": false,\n        \"host\": \"127.0.0.1\",\n        \"port\": 1883,\n        \"security\": false,\n        \"user\": \"\",\n        \"password\": \"\",\n        \"topicPrefix\": \"zway\",\n        \"topicPostfixStatus\": \"status\",\n        \"topicPostfixData\": \"data\",\n        \"topicPostfixSet\": \"set\",\n        \"skippedDevices\": []\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"clientId\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"clientIdRandomize\": {\n                \"type\": \"boolean\",\n                \"required\": true\n            },\n            \"host\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"port\": {\n                \"type\": \"integer\",\n                \"required\": true\n            },\n            \"security\": {\n                \"type\": \"boolean\",\n                \"required\": true\n            },\n            \"user\": {\n                \"type\": \"string\",\n                \"required\": false\n            },\n            \"password\": {\n                \"type\": \"string\",\n                \"required\": false\n            },\n            \"topicPrefix\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"topicPostfixStatus\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"topicPostfixData\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"topicPostfixSet\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"skippedDevices\": {\n                \"type\": \"array\",\n                \"field\": \"enum\",\n                \"datasource\": \"namespaces\",\n                \"enum\": \"namespaces:devices_all:deviceId\",\n                \"required\": false\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"clientId\": {\n                \"label\": \"__client_id_label__\"\n            },\n            \"clientIdRandomize\": {\n                \"label\": \"__client_id_randomize_label__\",\n                \"helper\": \"__client_id_randomize_helper__\"\n            },\n            \"host\": {\n                \"label\": \"__host_label__\"\n            },\n            \"port\": {\n                \"label\": \"__port_label__\"\n            },\n            \"security\": {\n                \"label\": \"__security__\"\n            },\n            \"user\": {\n                \"label\": \"__user_label__\",\n                \"helper\": \"__user_helper__\"\n            },\n            \"password\": {\n                \"label\": \"__password_label__\",\n                \"helper\": \"__password_helper__\"\n            },\n            \"topicPrefix\": {\n                \"label\": \"__topic_prefix_label__\"\n            },\n            \"topicPostfixStatus\": {\n                \"label\": \"__topic_postfix_status_label__\",\n                \"helper\": \"__topic_postfix_status_helper__\"\n            },\n            \"topicPostfixData\": {\n                \"label\": \"__topic_postfix_data_label__\",\n                \"helper\": \"__topic_postfix_data_helper__\"\n            },\n            \"topicPostfixSet\": {\n                \"label\": \"__topic_postfix_set_label__\",\n                \"helper\": \"__topic_postfix_set_helper__\"\n            },\n            \"skippedDevices\": {\n                \"label\": \"__skipped_devices_label__\",\n                \"helper\": \"__skipped_devices_helper__\",\n                \"type\": \"checkbox\",\n                \"datasource\": \"namespaces\",\n                \"field\": \"optionLabels\",\n                \"optionLabels\": \"namespaces:devices_all:deviceName\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "modules/MatterGate/htdocs/js/postRender.js",
    "content": "function modulePostRender() {\r\n\tif ($(\"div[data-alpaca-field-name='pin']\").find('input').val() === \"\") {\r\n\t\t$(\"div[data-alpaca-field-name='pin']\").hide();\t\r\n\t}\t\r\n\telse {\r\n\t\t$(\"div[data-alpaca-field-name='pin']\").show();\t\t\r\n\t}\r\n};"
  },
  {
    "path": "modules/MatterGate/index.js",
    "content": "/*** MatterGate Z-Way HA module *******************************************\n \nVersion: 1.0\n(c) Z-Wave.Me, 2023\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tThis module announces Z-Way HA devices to Matter\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction MatterGate (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tMatterGate.super_.call(this, id, controller);\n};\n\ninherits(MatterGate, AutomationModule);\n\n_module = MatterGate;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nMatterGate.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tMatterGate.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.endpoints = {};\n\t\n\tif (!this.config.matterDevices) {\n\t\tthis.config.matterDevices = {};\n\t}\n\n\t// If matterDevicesArray doesn't contain an vDevId, then remove it from the matterDevices\n\tObject.keys(this.config.matterDevices).forEach(function(vDevId) {\n\t\tif (self.config.matterDevicesArray.indexOf(vDevId) == -1) {\n\t\t\tdelete self.config.matterDevices[vDevId];\n\t\t}\n\t});\n\tthis.saveConfig();\n\tupdateSkippedDevicesList();\n\n\t// define functions and helpers\n\t\n\tfunction onDeviceAddedCore(vDevT) {\n\t\tvar controller = this.controller;\n\t\t\n\t\t// defaults\n\t\tvDevT.title = vDevT.title || vDevT.id;\n\t\tvDevT.manufacturer = vDevT.manufacturer || \"Z-Wave.Me\";\n\t\tvDevT.product = vDevT.product || vDevT.deviceType;\n\t\tvDevT.firmwareRevision = vDevT.firmwareRevision || zwayVersion.release;\n\t\tvDevT.serialNumber = vDevT.serialNumber || vDevT.id;\n\n\t\t// Skip widgets\n\t\tif (vDevT.permanently_hidden || !(vDevT.visibility) || (vDevT.probeType === \"alarmSensor_general_purpose\") || (vDevT.probeType === \"thermostat_mode\") || vDevT.tags.indexOf(\"matter-skip\") !== -1 || (vDevT.deviceType === \"thermostat\" && vDevT.id.indexOf(\"ZWayVDev\") === -1))\n\t\t\treturn;\n\n\t\t// Supported widgets\n\t\tif (!((vDevT.deviceType === \"switchBinary\") || (vDevT.deviceType === \"switchMultilevel\") || (vDevT.deviceType === \"sensorMultilevel\") ||\n\t\t   (vDevT.deviceType === \"sensorBinary\") || (vDevT.deviceType === \"doorlock\") || (vDevT.deviceType === \"switchRGBW\") || (vDevT.deviceType === \"thermostat\")))\n\t\t\treturn;\n\n\t\tvar ep = self.addDevice(vDevT);\n\n\t\tif (vDevT.deviceType === \"switchBinary\") {\n\t\t\t// skip thermostat mode\n\t\t\tif (vDevT.id.slice(-2) === \"64\") return;\n\t\t\t\n\t\t\t/* TODO handle appearance\n\t\t\tvar type = Matter.Services.Switch;\n\t\t\tif (vDevT.tags.indexOf(\"type-light\") !== -1) type = Matter.Services.Lightbulb;\n\t\t\tif (vDevT.tags.indexOf(\"type-fan\") !== -1) type = Matter.Services.Fan;\n\t\t\t*/\n\n\t\t\tself.matter.addEndPointSwitchBinary(ep);\n\t\t\tself.addEndpoint(ep, vDevT.id, self.binarySwitchGet, self.binarySwitchSet);\n\t\t}\n\t\telse if (vDevT.deviceType === \"switchMultilevel\" && (vDevT.probeType !== \"motor\") ) {\n\t\t\t// skip if related to switchRGB\n\t\t\tvar rgbDevId;\n\t\t\tif (vDevT.id.slice(-2) === \"38\"){\n\t\t\t\trgbDevId = vDevT.id.substring(0, vDevT.id.indexOf(\"-\",vDevT.id.indexOf(\"-\")+1)+1) + \"51-rgb\";\n\t\t\t}\n\t\t\tvar match = rgbDevices.filter(function(el) { return el.id === rgbDevId; })[0];\n\t\t\tif (match) return;\n\n\t\t\tself.matter.addEndPointSwitchMultiLevel(ep);\n\t\t\tself.addEndpoint(ep, vDevT.id, self.multilevelSwitchGet, self.multilevelSwitchSet);\n\t\t}\n\t\telse if (vDevT.deviceType === \"sensorMultilevel\") {\n\t\t\tif (vDevT.probeType === \"temperature\" && (vDevT.scaleTitle === \"°C\" || vDevT.scaleTitle === \"°F\")) {\n\t\t\t\tself.matter.addEndPointSensorTemperature(ep, -99*100, 99*100);\n\t\t\t\tself.addEndpoint(ep, vDevT.id, self.multilevelSensor100Get);\n\t\t\t}\n\t\t\telse if (vDevT.probeType === \"humidity\" && vDevT.scaleTitle === \"%\") {\n\t\t\t\tself.matter.addEndPointSensorHumidity(ep, 0*100, 100*100);\n\t\t\t\tself.addEndpoint(ep, vDevT.id, self.multilevelSensor100Get);\n\t\t\t}\n\t\t\telse if (vDevT.probeType === \"luminosity\") {\n\t\t\t\tself.matter.addEndPointSensorLight(ep, 1, 10000);\n\t\t\t\tself.addEndpoint(ep, vDevT.id, self.multilevelSensorGet);\n\t\t\t}\n\t\t}\n\t\telse if (vDevT.deviceType === \"sensorBinary\") {\n\t\t\tif (vDevT.probeType === \"motion\") {\n\t\t\t}\n\t\t\telse if (vDevT.probeType === \"door-window\") {\n\t\t\t\tself.matter.addEndPointSensorContact(ep);\n\t\t\t\tself.addEndpoint(ep, vDevT.id, self.binarySensorGet, undefined, self.binarySensorPush);\n\t\t\t}\n\t\t}\n\t\t/*\n\t\telse if (vDevT.deviceType === \"doorlock\") {\n\t\t\tvar service = accessory.addService(Matter.Services.LockMechanism, \"Door Lock\");\n\n\t\t\tservice.addCharacteristic(Matter.Characteristics.Name, \"string\", vDevT.title);\n\t\t\tm.StateLevel = service.addCharacteristic(Matter.Characteristics.LockCurrentState, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return (!!d && d.get(\"metrics:level\") === \"close\") ? 1 : 0; }\n\t\t\t});\n\t\t\tm.level = service.addCharacteristic(Matter.Characteristics.LockTargetState, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return (!!d && d.get(\"metrics:level\") === \"close\") ? 1 : 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (d) d.performCommand(value ? \"close\" : \"open\"); }\n\t\t\t});\n\t\t}\n\t\telse if (vDevT.deviceType === \"switchRGBW\") {\n\t\t\t// Don't create rgbw widgets without brightness\n\t\t\tvar brightnessDev = null;\n\t\t\tvar brightnessDevId;\n\t\t\tif (vDevT.id.indexOf(\"RGB\") === 0) {\n\t\t\t\t// RGB module\n\t\t\t\tvar redDevice = self.controller.instances.filter(function(instance){return instance.id == vDevT.id.substring(4)})[0].params.red;\n\t\t\t\tvar before = redDevice.indexOf(\"-\")+1;\n\t\t\t\tvar after = redDevice.indexOf(\"-\",redDevice.indexOf(\"-\")+1);\n\t\t\t\tbrightnessDevId = redDevice.substring(0, before) + \"1\" + redDevice.substring(after);\n\t\t\t\tbrightnessDev = self.controller.devices.get(brightnessDevId);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// Z-Wave Device\n\t\t\t\tbrightnessDevId = vDevT.id.substring(0, vDevT.id.indexOf(\"-\",vDevT.id.indexOf(\"-\")+1)+1) + \"38\";\n\t\t\t\tbrightnessDev = self.controller.devices.get(brightnessDevId);\n\t\t\t}\n\t\t\tif (!brightnessDev) return;\n\n\t\t\tvar service = accessory.addService(Matter.Services.Lightbulb, \"Multilevel Switch\");\n\n\t\t\tservice.addCharacteristic(Matter.Characteristics.Name, \"string\", vDevT.title);\n\n\t\t\tself.onDeviceWipedOut(brightnessDevId);\n\n\t\t\tm.level = service.addCharacteristic(Matter.Characteristics.On, \"bool\", {\n\t\t\t\tget: function() { var d = controller.devices.get(brightnessDevId); return (!!d && d.get(\"metrics:level\")) ? true : false; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(brightnessDevId); if (!!d) d.performCommand(value ? \"on\" : \"off\"); }\n\t\t\t});\n\n\t\t\tm.hue = service.addCharacteristic(Matter.Characteristics.Hue, \"float\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && parseFloat(hsv(d).h) || 0.0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) exactColor(d, \"Hue\", value); }},\n\t\t\t\tundefined, {\"unit\":\"arcdegrees\", \"maxValue\":360, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\n\t\t\tm.saturation = service.addCharacteristic(Matter.Characteristics.Saturation, \"float\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); return !!d && parseFloat(hsv(d).s) || 0.0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) exactColor(d, \"Saturation\", value); }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":100, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\n\t\t\tm.brightness = service.addCharacteristic(Matter.Characteristics.Brightness, \"int\", {\n\t\t\t\tget: function() { var d = controller.devices.get(brightnessDevId); if (!d) return 0; var value = d.get(\"metrics:level\"); return value > 99 ? 99 : value || 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (!!d) { exactColor(d, \"Brightness\", value); var b = controller.devices.get(brightnessDevId); if (!!b) b.performCommand(\"exact\", { level: value }); }}},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\n\t\t\t// dirty hack to handle in OnLevelChange, but not to create a Matter accessory\n\t\t\tif (brightnessDev) {\n\t\t\t\tself.mapping[brightnessDev.id] = {\n\t\t\t\t\t$accessory: m.$accessory,\n\t\t\t\t\tlevel: m.level,\n\t\t\t\t\tbrightness: m.brightness\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\telse if (vDevT.deviceType === \"thermostat\") {\n\t\t\tvar service = accessory.addService(Matter.Services.Thermostat, \"Thermostat\");\n\t\t\tservice.addCharacteristic(Matter.Characteristics.Name, \"string\", vDevT.title);\n\t\t\tvar deviceID = vDevT.id.substring(vDevT.id.lastIndexOf(\"_\")+1,vDevT.id.indexOf(\"-\"));\n\n\t\t\t// If Matter thermostat already generated, exit.\n\t\t\tvar match = thermostats.filter(function(el) { return el === deviceID; })[0];\n\t\t\t\n\t\t\tif (match) {\n\t\t\t\tself.onDeviceWipedOut(vDevT.id);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tthermostats.push(deviceID);\n\n\t\t\t// Get all thermostat modes\n\t\t\tvar thermostatModes = [1]; // For danfoss LC and Secure without ThermostatMode CC\n\t\t\tif (zway.devices[deviceID].ThermostatMode && zway.devices[deviceID].ThermostatMode.data.supported.value) {\n\t\t\t\tthermostatModes = Object.keys(zway.devices[deviceID].ThermostatMode.data).filter(function(mode) {return !isNaN(parseInt(mode))});\n\t\t\t}\n\n\t\t\t// Use in Matter only Off, Cool, Heat, Auto\n\t\t\tvar supportedMatterModes = [0,1,2,3];\n\t\t\tvar modes = [];\n\t\t\tsupportedMatterModes.forEach(function(validMode) {\n\t\t\t\tthermostatModes.forEach(function(mode) {\n\t\t\t\t\tif (validMode == mode)\n\t\t\t\t\t\tmodes.push(validMode);\n\t\t\t\t\tif (validMode == 3 && mode == 10)\n\t\t\t\t\t\tmodes.push(validMode);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// Remove mode 3 (Auto) if exist\n\t\t\tvar modesWithOutAuto = modes.filter(function(mode) {return mode != 3});\n\n\t\t\tvar currentMaxMode = Math.max.apply(null, modesWithOutAuto);\n\t\t\tvar currentMinMode = Math.min.apply(null, modesWithOutAuto);\n\n\t\t\tvar targetMaxMode = Math.max.apply(null, modes);\n\t\t\tvar targetMinMode = Math.min.apply(null, modes);\n\n\t\t\tm.currentThermostatMode = service.addCharacteristic(Matter.Characteristics.CurrentHeatingCoolingState, \"uint8\",  {\n\t\t\t\tget: function() { return modesWithOutAuto.length > 1 ? getCurrentMode(deviceID) : modesWithOutAuto[0]; }},\n\t\t\t\tundefined, {\"valid-values\": modesWithOutAuto, \"maxValue\": currentMaxMode, \"minValue\": currentMinMode}\n\t\t\t);\n\n\t\t\tm.targetThermostatMode = service.addCharacteristic(Matter.Characteristics.TargetHeatingCoolingState, \"uint8\", {\n\t\t\t\tget: function() { return modesWithOutAuto.length > 1 ? getTargetMode(deviceID) : modesWithOutAuto[0];; },\n\t\t\t\tset: function(mode) { zway.devices[deviceID].ThermostatMode.Set(mode == 3 ? 10 : mode); }},\n\t\t\t\tundefined, {\"valid-values\": modes, \"maxValue\":targetMaxMode, \"minValue\":targetMinMode}\n\t\t\t);\n\n\t\t\tm.currentTemperature = service.addCharacteristic(Matter.Characteristics.CurrentTemperature, \"float\",  {\n\t\t\t\tget: function() { return getCurrentTemperature(deviceID); }},\n\t\t\t\tundefined, {\"unit\":\"celsius\", \"maxValue\":999, \"minValue\":-999, \"minStep\":0.1}\n\t\t\t);\n\n\t\t\tm.targetTemperature = service.addCharacteristic(Matter.Characteristics.TargetTemperature, \"float\", {\n\t\t\t\tget: function() { return getTargetTemperature(deviceID); },\n\t\t\t\tset: function(temperature) {\n\t\t\t\t\tif (modesWithOutAuto.length > 1)\n\t\t\t\t\t\tzway.devices[deviceID].ThermostatMode.Set(lastSupportedThermostatMode == 3 ? 10 : lastSupportedThermostatMode);\n\t\t\t\t\telse \n\t\t\t\t\t\tlastSupportedThermostatMode = modesWithOutAuto[0];\n\t\t\t\t\tzway.devices[deviceID].ThermostatSetPoint.Set(lastSupportedThermostatMode, temperature);\n\t\t\t\t}},\n\t\t\t\tundefined, {\"unit\":\"celsius\", \"maxValue\":40, \"minValue\":5, \"minStep\":0.5}\n\t\t\t);\n\n\t\t\t// { 0:\"Celsius\", 1:\"Fahrenheit\" }\n\t\t\tservice.addCharacteristic(Matter.Characteristics.TemperatureDisplayUnits, \"uint8\", 0,\n\t\t\t\t[\"pr\", \"pw\", \"ev\"], {\"valid-values\":[0, 1], \"maxValue\":1, \"minValue\":0}\n\t\t\t);\n\t\t}\n\t\telse if (vDevT.probeType === \"motor\") {\n\t\t\tvar service = accessory.addService(Matter.Services.WindowCovering, \"Blind Control\");\n\t\t\tservice.addCharacteristic(Matter.Characteristics.Name, \"string\", vDevT.title);\n\n\t\t\tm.targetPosition = service.addCharacteristic(Matter.Characteristics.TargetPosition, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); if (!d) return 0; var value = parseInt(d.get(\"metrics:level\")); return value > 99 ? 99 : value || 0; },\n\t\t\t\tset: function(value) { var d = controller.devices.get(vDevT.id); if (d) d.performCommand(\"exact\", { level: value }); }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\t\t\tm.currentPosition = service.addCharacteristic(Matter.Characteristics.CurrentPosition, \"uint8\", {\n\t\t\t\tget: function() { var d = controller.devices.get(vDevT.id); if (!d) return 0; var value = parseInt(d.get(\"metrics:level\")); return value > 99 ? 99 : value || 0; }},\n\t\t\t\tundefined, {\"unit\":\"percentage\", \"maxValue\":99, \"minValue\":0, \"minStep\":1}\n\t\t\t);\n\t\t\tm.positionState = service.addCharacteristic(Matter.Characteristics.PositionState, \"uint8\", {\n\t\t\t\tget: function() { return 2; }}, // Stopped\n\t\t\t\tundefined, {\"valid-values\":[0, 1, 2], \"maxValue\":2, \"minValue\":0}\n\t\t\t);\n\t\t}\n\t\t*/\n\t};\n\n\t/***************** THERMOSTAT HELPERS *****************/\n\t\n\t/*\n\tfunction getCurrentTemperature(deviceID) {\n\t\tvar ccSensorMultilevel = zway.devices[deviceID].SensorMultilevel;\n\t\tif  (ccSensorMultilevel && ccSensorMultilevel.data[1] && ccSensorMultilevel.data[1].val && ccSensorMultilevel.data[1].val.value) {\n\t\t\tvar temperature = ccSensorMultilevel.data[1].val.value;\n\t\t\tif (temperature >= -999 && temperature <= 999) {\n\t\t\t\treturn temperature;\n\t\t\t}\n\t\t\telse {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tif (lastSupportedThermostatMode == 3){\n\t\t\t\tlastSupportedThermostatMode = 10;\n\t\t\t}\n\t\t\telse if (lastSupportedThermostatMode == 0) {\n\t\t\t\tlastSupportedThermostatMode = 1;\n\t\t\t}\n\t\t\treturn zway.devices[deviceID].ThermostatSetPoint.data[lastSupportedThermostatMode].val.value;\n\t\t}\n\t};\n\n\tfunction getTargetTemperature(deviceID) {\n\t\tvar targetTemperature;\n\t\tif (zway.devices[deviceID].ThermostatMode) {\n\t\t\tvar mode = zway.devices[deviceID].ThermostatMode.data.mode.value;\n\t\t\tif (mode == 1 || mode == 2 || mode == 3) {\n\t\t\t\ttargetTemperature = zway.devices[deviceID].ThermostatSetPoint.data[mode].val.value;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (lastSupportedThermostatMode == 0) {\n\t\t\t\t\ttargetTemperature = 10;\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\ttargetTemperature = zway.devices[deviceID].ThermostatSetPoint.data[lastSupportedThermostatMode == 3 ? 10 : lastSupportedThermostatMode].val.value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (targetTemperature < 5)\n\t\t\t\ttargetTemperature = 5;\n\t\t\tif (targetTemperature > 40)\n\t\t\t\ttargetTemperature = 40;\n\t\t}\n\t\telse {\n\t\t\ttargetTemperature = zway.devices[deviceID].ThermostatSetPoint.data[1].val.value; // Danfoss LC\n\t\t}\n\n\t\treturn targetTemperature;\n\t};\n\n\tfunction getTargetMode(deviceID) {\n\t\tvar mode = zway.devices[deviceID].ThermostatMode.data.mode.value;\n\t\tif (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 10) {\n\t\t\tlastSupportedThermostatMode = mode == 10 ? 3 : mode; // Transform ZW Auto(10) mode to Matter Auto(3) mode\n\t\t}\n\t\treturn lastSupportedThermostatMode;\n\t}\n\n\tfunction getCurrentMode(deviceID) {\n\t\tvar mode = zway.devices[deviceID].ThermostatMode.data.mode.value;\n\t\tif (mode == 0 || mode == 1 || mode == 2 || mode == 3 || mode == 10) {\n\t\t\tif (mode == 3 || mode == 10){\n\t\t\t\tlastSupportedThermostatMode = 1; // CurrentHeatingCoolingState not support Auto(10) mode, change it to Heat(1)\n\t\t\t}\n\t\t\telse {\n\t\t\t\tlastSupportedThermostatMode = mode;\n\t\t\t}\n\t\t}\n\t\treturn lastSupportedThermostatMode;\n\t}\n\t*/\n\n\t/***************** RGB HELPERS *****************/\n\t\n\t/*\n\tfunction exactColor(vDev, valueName, value) {\n\t\tvar match = rgbDevices.filter(function(el) { return el.id === vDev.id; })[0];\n\n\t\t// If vDev already in rgbDevices array, set propertie\n\t\tif (match) {\n\t\t\tif (valueName === \"Hue\") {\n\t\t\t\tmatch.hue = value;\n\t\t\t\tmatch.valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Saturation\") {\n\t\t\t\tmatch.saturation = value;\n\t\t\t\tmatch.valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Brightness\") {\n\t\t\t\tmatch.brightness = value;\n\t\t\t}\n\n\t\t\t// Wait 2 Characteristics: \"Hue, Saturation\" to exact color\n\t\t\tif (valueName !== \"Brightness\" && match.valueCount == 2) {\n\t\t\t\tmatch.valueCount = 0;\n\t\t\t\tvar colors = hsv2rgb({h:match.hue, s:match.saturation, v:match.brightness});\n\t\t\t\tvDev.performCommand(\"exact\", {red: colors.r, green: colors.g, blue: colors.b});\n\t\t\t}\n\t\t}\n\t\t// If vDev not in rgbDevices array, add vDev and set propertie\n\t\telse {\n\t\t\tvar last = (rgbDevices.push({\"id\":vDev.id, hue: 0, saturation: 0, brightness: 100, valueCount:0}) - 1);\n\t\t\tif (valueName === \"Hue\") {\n\t\t\t\trgbDevices[last].hue = value;\n\t\t\t\trgbDevices[last].valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Saturation\") {\n\t\t\t\trgbDevices[last].saturation = value;\n\t\t\t\trgbDevices[last].valueCount += 1;\n\t\t\t}\n\t\t\telse if (valueName === \"Brightness\") {\n\t\t\t\trgbDevices[last].brightness = value;\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction hsv(vDev){\n\t\treturn rgb2hsv({r:vDev.get(\"metrics:color:r\"), g:vDev.get(\"metrics:color:g\"), b:vDev.get(\"metrics:color:b\")});\n\t}\n\n\tfunction hsv2rgb(obj) {\n\t\t// H: 0-360; S,V: 0-100; RGB: 0-255\n\t\tvar r, g, b;\n\t\tvar sfrac = obj.s / 100;\n\t\tvar vfrac = obj.v / 100;\n\n\t\tif(sfrac === 0){\n\t\t\tvar vbyte = Math.round(vfrac*255);\n\t\t\treturn { r: vbyte, g: vbyte, b: vbyte };\n\t\t}\n\n\t\tvar hdb60 = (obj.h % 360) / 60;\n\t\tvar sector = Math.floor(hdb60);\n\t\tvar fpart = hdb60 - sector;\n\t\tvar c = vfrac * (1 - sfrac);\n\t\tvar x1 = vfrac * (1 - sfrac * fpart);\n\t\tvar x2 = vfrac * (1 - sfrac * (1 - fpart));\n\t\tswitch(sector){\n\t\t\tcase 0:\n\t\t\t\tr = vfrac; g = x2;\tb = c;\t  break;\n\t\t\tcase 1:\n\t\t\t\tr = x1;\tg = vfrac; b = c;\t  break;\n\t\t\tcase 2:\n\t\t\t\tr = c;\t g = vfrac; b = x2;\t break;\n\t\t\tcase 3:\n\t\t\t\tr = c;\t g = x1;\tb = vfrac;  break;\n\t\t\tcase 4:\n\t\t\t\tr = x2;\tg = c;\t b = vfrac;  break;\n\t\t\tcase 5:\n\t\t\tdefault:\n\t\t\t\tr = vfrac; g = c;\t b = x1;\t break;\n\t\t}\n\n\t\treturn { \"r\": Math.round(255 * r), \"g\": Math.round(255 * g), \"b\": Math.round(255 * b) };\n\t}\n\n\tfunction rgb2hsv(obj) {\n\t\t// RGB: 0-255; H: 0-360, S,V: 0-100\n\t\tvar r = obj.r/255, g = obj.g/255, b = obj.b/255;\n\t\tvar max, min, d, h, s, v;\n\n\t\tmin = Math.min(r, Math.min(g, b));\n\t\tmax = Math.max(r, Math.max(g, b));\n\n\t\tif (min === max) {\n\t\t\t// shade of gray\n\t\t\treturn {h: 0, s: 0, v: r * 100};\n\t\t}\n\n\t\tvar d = (r === min) ? g - b : ((b === min) ? r - g : b - r);\n\t\th = (r === min) ? 3 : ((b === min) ? 1 : 5);\n\t\th = 60 * (h - d/(max - min));\n\t\ts = (max - min) / max;\n\t\tv = max;\n\t\treturn {\"h\": h, \"s\": s * 100, \"v\": v * 100};\n\t}\n\t*/\n\n\tfunction updateSkippedDevicesList() {\n\t\t// Add tag \"matter-skip\" for all skipped devices from config\n\t\tself.config.skippedDevices.forEach(function(vDevId) {\n\t\t\tdelete self.config.matterDevices[vDevId];\n\t\t\tremoveFromMatterDevicesArray(vDevId);\n\t\t\tvar vDev = self.controller.devices.get(vDevId);\n\t  \t\tif (vDev !== null && vDev.get(\"tags\").indexOf(\"matter-skip\") === -1 ) {\n\t  \t\t\tvDev.addTag(\"matter-skip\");\n\t  \t\t}\n\t\t});\n\t\tself.saveConfig();\n\n\t\t// Remove tag \"matter-skip\" if device not in skipped list\n\t\tself.controller.devices.forEach(function(vDev) {\n\t\t\tif (vDev !== null \n\t\t\t\t&& vDev.get(\"tags\").indexOf(\"matter-skip\") !== -1\n\t\t\t\t&& self.config.skippedDevices.indexOf(vDev.id) === -1) {\n\t  \t\t\t\tvDev.removeTag(\"matter-skip\");\n\t  \t\t}\n\t\t});\n\t}\n\n\tfunction removeFromMatterDevicesArray(vDevid) {\n\t\tvar index = self.config.matterDevicesArray.indexOf(vDevid);\n\t\tif  (index !== -1) {\n\t\t\tself.config.matterDevicesArray.splice(index, 1);\n\t\t}\n\t}\n\n\tthis.matterDeviceRemove = function (vDevId) {\n\t\t// TODO call matter.remove\t\t\t\n\t}\n\n\tthis.onDeviceAdded = function (vDev) {\n\t   \tconsole.log(\"Matter: added\", vDev.id);\n\t   \t\n\t\tonDeviceAddedCore(self.vDevToTemplate(vDev));\n\t}\n\t\n\tthis.onDeviceRemoved = function (vDev) {\n\t\tconsole.log(\"Matter: removed\", vDev.id);\n\t\t\t\n\t\t// TODO self.matter.setReachable(ep, m[\"reachable\"]);\n\t}\n\t\n\tthis.onDeviceWipedOut = function (vDevId) {\n\t\tconsole.log(\"Matter: wipe out\", vDevId);\n\t\t\n\t\tself.matterDeviceRemove(vDevId);\n\t\t\n\t\t// update device tree\n\t\t// TODO self.matter.update();\n\t}\n\t\n\tthis.onLevelChanged = function (vDev) {\n\t\tconsole.log(\"Matter: updated\", vDev.id);\n\t\t\n\t\tself.devicePush(vDev.id);\n\t}\n\n\tthis.onTagsChanged = function (vDev) {\n\t\t// Add tag \"matter-skip\" to skipped Devices list in config and remove device from Homekit\n\t\tif (vDev.get(\"tags\").indexOf(\"matter-skip\") !== -1 && self.config.skippedDevices.indexOf(vDev.id) === -1) {\n\t\t\tself.config.skippedDevices.push(vDev.id);\n\t\t\tdelete self.config.matterDevices[vDev.id];\n\t\t\tremoveFromMatterDevicesArray(vDev.id);\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceWipedOut(vDev.id);\n\t  \t}\n\n\t  \t// Remove tag \"matter-skip\" from skipped Devices list in config and add device to Homekit\n\t  \tif (vDev.get(\"tags\").indexOf(\"matter-skip\") === -1 && self.config.skippedDevices.indexOf(vDev.id) !== -1) {\n\t  \t\tvar index = self.config.skippedDevices.indexOf(vDev.id);\n\t\t\tself.config.skippedDevices.splice(index, 1);\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceAdded(vDev);\n\t  \t}\n\t}\n\n\tthis.onPermanentlyHiddenChanged = function (vDev) {\n\t\t// Remove device from Homekit\n\t\tif (vDev.get(\"permanently_hidden\") === true) {\n\t\t\tdelete self.config.matterDevices[vDev.id];\n\t\t\tremoveFromMatterDevicesArray(vDev.id);\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceWipedOut(vDev.id);\n\t\t}\n\n\t\t// Add device to Homekit\n\t\tif (vDev.get(\"permanently_hidden\") === false) {\n\t\t\tself.saveConfig();\n\t\t\tself.onDeviceAdded(vDev);\n\t\t}\n\n\t}\n\n\tvar rgbDevices = [];\n\t\n\t/*\n\tvar thermostats = [];\n\tvar lastSupportedThermostatMode = 1; // Default Heat\n\t*/\n\n\tvar pin = this.config.pin; // if undefined or empty, will be autogenerated\n\t\n\tthis.matter = new Matter(\n\t\tthis.config.name, \n\t\tfunction(arg) {\n\t\t\tdebugPrint(\"Getter \" + JSON.stringify(arg));\n\t\t\tvar ep = parseInt(arg[\"end_point_id\"], 10);\n\t\t\tvar epObj = self.endpoints[ep];\n\t\t\treturn !!epObj && epObj.getter.call(self, epObj.id);\n\t\t},\n\t\tfunction(arg) {\n\t\t\tdebugPrint(\"Setter \" + JSON.stringify(arg));\n\t\t\tvar ep = parseInt(arg[\"end_point_id\"], 10);\n\t\t\tvar val = parseInt(arg[\"value_0\"], 10);\n\t\t\tvar epObj = self.endpoints[ep];\n\t\t\treturn !!epObj && epObj.setter.call(self, epObj.id, val);\n\t\t}\n\t\t//,,\n\t\t//pin\n\t);\n\n\t// prepare the structure holders\n\t\n\tthis.mapping = {}\n\n\t// load saved devices in case vDevs are not yet loaded to make sure Matter always receives the full list of device\n\tthis.preloadDevices();\n\n\t// add existing devices\n\tthis.controller.devices.each(function(d) { onDeviceAddedCore(self.vDevToTemplate(d)); });\n\t\n\t// listen for future device collection changes\n\tthis.controller.devices.on(\"created\", this.onDeviceAdded);\n\tthis.controller.devices.on(\"removed\", this.onDeviceRemoved);\n\tthis.controller.devices.on(\"wipedOut\", this.onDeviceWipedOut);\n\tthis.controller.devices.on(\"change:metrics:level\", this.onLevelChanged);\n\tthis.controller.devices.on(\"change:metrics:isFailed\", this.onLevelChanged);\n\tthis.controller.devices.on(\"change:tags\", this.onTagsChanged);\n\tthis.controller.devices.on(\"change:permanently_hidden\", this.onPermanentlyHiddenChanged);\n\t\n\t// update device tree\n\t//TODO//this.matter.update();\n\t\n\tconsole.log(\"Matter PIN:\", this.matter.pin);\n\tself.config.pin = this.matter.pin;\n\tthis.controller.addNotification(\"notification\", \"Matter PIN: \" + this.matter.pin, \"module\", \"MatterGate\");\n};\n\nMatterGate.prototype.stop = function () {\n\tMatterGate.super_.prototype.stop.call(this);\n\n\tthis.controller.devices.off(\"created\", this.onDeviceAdded);\n\tthis.controller.devices.off(\"removed\", this.onDeviceRemoved);\n\tthis.controller.devices.off(\"wipedOut\", this.onDeviceWipedOut);\n\tthis.controller.devices.off(\"change:metrics:level\", this.onLevelChanged);\n\tthis.controller.devices.off(\"change:metrics:isFailed\", this.onLevelChanged);\n\tthis.controller.devices.off(\"change:tags\", this.onTagsChanged);\n\tthis.controller.devices.off(\"change:permanently_hidden\", this.onPermanentlyHiddenChanged);\n\n\tif (this.matter) {\n\t\tthis.matter.stop();\n\t}\n\t\n\tdelete this.endpoints;\n\tdelete this.onDeviceAdded;\n\tdelete this.onDeviceRemoved;\n\tdelete this.onDeviceWipedOut;\n\tdelete this.onLevelChanged;\n\tdelete this.onTagsChanged;\n\tdelete this.onPermanentlyHiddenChanged;\n};\n\n\nMatterGate.prototype.addDevice = function(vDevT) {\n\tvar self = this;\n\t\n\t// clean old structure if any\n\tthis.matterDeviceRemove(vDevT.id);\n\t\n\tif (!_.isEqual(_.omit(this.config.matterDevices[vDevT.id], \"ep\"), _.omit(vDevT, \"ep\"))) {\n\t\tvar ep = (this.config.matterDevices[vDevT.id] && this.config.matterDevices[vDevT.id].ep) || (1 + Math.max(2, Math.max.apply(null, Object.keys(this.config.matterDevices).map(function(k) { return self.config.matterDevices[k].ep; }))));\n\t\tthis.config.matterDevices[vDevT.id] = vDevT;\n\t\tif (this.config.matterDevicesArray.indexOf(vDevT.id) == -1)\n\t\t\tthis.config.matterDevicesArray.push(vDevT.id);\n\t\tthis.config.matterDevices[vDevT.id].ep = ep;\n\t\tthis.saveConfig();\n\t}\n\t\n\tvar ep = this.config.matterDevices[vDevT.id].ep;\n\t\n\treturn ep;\n};\n\nMatterGate.prototype.preloadDevices = function() {\n\tvar self = this;\n\t\n\tObject.keys(this.config.matterDevices).forEach(function(vDevId) {\n\t\tself.addDevice(self.config.matterDevices[vDevId]);\n\t});\n};\n\nMatterGate.prototype.vDevToTemplate = function(vDev) {\n\treturn {\n\t\tid: vDev.id,\n\t\tdeviceType: vDev.get(\"deviceType\"),\n\t\tprobeType: vDev.get(\"probeType\"),\n\t\ttags: vDev.get(\"tags\"),\n\t\tpermanently_hidden: vDev.get('permanently_hidden'),\n\t\tvisibility: vDev.get('visibility'),\n\t\ttitle: vDev.get(\"metrics:title\"),\n\t\tscaleTitle: vDev.get(\"metrics:scaleTitle\"),\n\t\tprobeTitle: vDev.get(\"metrics:probeTitle\"),\n\t\tmanufacturer: vDev.get(\"manufacturer\"),\n\t\tproduct: vDev.get(\"product\"),\n\t\tfirmwareRevision: vDev.get(\"firmware\"),\n\t\tserialNumber: undefined\n\t};\n};\n\nMatterGate.prototype.addEndpoint = function(ep, id, getter, setter, pusher) {\n\tthis.endpoints[ep] = {\n\t\tid: id,\n\t\tgetter: getter,\n\t\tsetter: setter,\n\t\tpusher: pusher\n\t};\n};\n\nMatterGate.prototype.epById = function(id) {\n\tfor (var ep in this.endpoints) {\n\t\tif (this.endpoints[ep].id === id) {\n\t\t\treturn parseInt(ep, 10);\n\t\t}\n\t};\n\t\n\treturn null;\n};\n\nMatterGate.prototype.devicePush = function(id) {\n\tvar ep = this.epById(id);\n\tif (!ep) return;\n\t\n\tvar pusher = this.endpoints[ep].pusher;\n\tif (!pusher) return;\n\t\n\tpusher.call(this, id, ep);\n};\n\n// Getters and setters\n\nMatterGate.prototype.binarySwitchGet = function(id) {\n\tvar dev = this.controller.devices.get(id);\n\tif (!dev) return false;\n\t\n\treturn dev.get(\"metrics:level\") === \"on\" ? 0xFF : 0x00;\n};\n\nMatterGate.prototype.binarySwitchSet = function(id, value) {\n        var dev = this.controller.devices.get(id);\n        if (!dev) return false;\n\n       \tdev.performCommand(value ? \"on\" : \"off\");\n       \treturn true;\n};\n\nMatterGate.prototype.multilevelSwitchGet = function(id) {\n\tvar dev = this.controller.devices.get(id);\n\tif (!dev) return false;\n\t\n\tvar level = dev.get(\"metrics:level\") ;\n\tif (level === \"on\") level === 99;\n\tif (level === \"off\") level = 0;\n\tif (level < 0) level = 0;\n\tif (level >= 99) level = 100;\n\treturn level;\n};\n\nMatterGate.prototype.multilevelSwitchSet = function(id, value) {\n        var dev = this.controller.devices.get(id);\n        if (!dev) return false;\n\n       \tdev.performCommand(\"exact\", { level: value });\n       \treturn true;\n};\n\nMatterGate.prototype.multilevelSensorGet = function(id) {\n        var dev = this.controller.devices.get(id);\n        if (!dev) return false;\n\n        return Math.round(dev.get(\"metrics:level\"));\n};\n\nMatterGate.prototype.multilevelSensor100Get = function(id) {\n        var dev = this.controller.devices.get(id);\n        if (!dev) return false;\n\n        return Math.round(dev.get(\"metrics:level\") * 100);\n};\n\nMatterGate.prototype.binarySensorGet = function(id) {\n        var dev = this.controller.devices.get(id);\n        if (!dev) return false;\n\n        return dev.get(\"metrics:level\") === \"on\" ? 0x01 : 0x00;\n};\n\nMatterGate.prototype.binarySensorPush = function(id, ep) {\n        var dev = this.controller.devices.get(id);\n        if (!dev) return;\n\n        this.matter.setEndPointSensorContactState(ep, dev.get(\"metrics:level\") === \"on\" ? 0x01 : 0x00);\n};\n"
  },
  {
    "path": "modules/MatterGate/lang/en.json",
    "content": "{\n\t\"m_title\":\"Matter Bridge\",\n\t\"m_descr\":\"The Matter protocol allows to control Z-Way from Apple Home, Google Home, Amazon Alexa and many other Matter-compatible controllers\",\n\t\"l_options\":\"Name the bridge will appears with in Matter\",\n\t\"l_pin\":\"Pin code\",\n\t\"l_skipped_devices\":\"Devices that don't need to be displayed in Matter\",\n\t\"h_skipped_devices\":\"<b>matter-skip</b> tag will be added to each selected device.\",\n\t\"l_hkDevicesArray\": \"Devices exported to Matter (autogenerated)\"\n}"
  },
  {
    "path": "modules/MatterGate/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Matter Шлюз\",\n\t\"m_descr\":\"Интеграция с контроллерами, поддерживающими Matter.\",\n\t\"l_options\":\"Имя под которым шлюз будет отображаться в контроллерах Matter\",\n\t\"l_pin\":\"Пин-код\",\n\t\"l_skipped_devices\":\"Устройства, которые не нужно отображать в Matter\",\n\t\"h_skipped_devices\":\"<b>matter-skip</b> тэг будет добавлен каждому выбранному устройству.\",\n\t\"l_hkDevicesArray\": \"Устройства, экспортированные в Matter (заполняется автоматически)\"\n}"
  },
  {
    "path": "modules/MatterGate/module.json",
    "content": "{\n    \"singleton\": true,\n    \"dependencies\": [],\n    \"category\": \"support_external_ui\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://z-wave.me\",\n    \"icon\": \"icon.svg\",\n    \"moduleName\": \"MatterGate\",\n    \"version\": \"1.0\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"name\": \"RaZberry\",\n        \"pin\": \"\",\n        \"matterDevicesArray\": [],\n        \"skippedDevices\": []\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"name\": {\n                \"type\": \"string\",\n                \"required\": true\n            },\n            \"pin\": {\n                \"type\": \"string\",\n                \"readonly\": true\n            },\n            \"skippedDevices\": {\n                \"type\": \"array\",\n                \"field\": \"enum\",\n                \"datasource\": \"namespaces\",\n                \"enum\": \"namespaces:devices_all:deviceId\",\n                \"required\": false\n            },\n            \"matterDevicesArray\" : {\n                \"type\": \"array\",\n                \"items\": {\n                    \"type\": \"string\",\n                    \"required\": false\n                }\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"name\": {\n                \"label\": \"__l_options__\"\n            },\n            \"pin\": {\n                \"label\": \"__l_pin__\"\n            },\n            \"skippedDevices\": {\n                \"label\": \"__l_skipped_devices__\",\n                \"helper\": \"__h_skipped_devices__\",\n                \"type\": \"checkbox\",\n                \"datasource\": \"namespaces\",\n                \"field\": \"optionLabels\",\n                \"optionLabels\": \"namespaces:devices_all:deviceName\"\n            },\n            \"matterDevicesArray\": {\n                \"label\": \"__l_matterDevicesArray__\",\n                \"fields\": {\n                    \"item\": {\n                        \"type\": \"text\",\n                        \"readonly\": true\n                    }\n                }\n            }\n        }\n    },\n    \"postRender\": \"loadFunction:postRender.js\"\n}\n"
  },
  {
    "path": "modules/MobileAppSupport/index.js",
    "content": "/* Mobile App Support\n *\n * Z-Wave.Me, 2022\n * Version 3.0.0\n *\n * Author: Poltorak Serguei\n */\n\n/* Module configuration format:\n\tconfig\n\t\tapps[]\t\t\t\tlist of phones\n\t\t\ttoken\t\tstr\tphone FCM token\n\t\t\ttitle\t\tstr\tphone name\n\t\t\tprofileName\tstr\tname of the profile in the phone app\n\t\t\tos\t\tstr\ttarget OS: ios/android\n\t\t\tapp_profile\tstr\tUUID of the profile in the app in case of multiple profiles\n\t\t\tuser\t\tint\tuser Id\n\t\t\tuserName\tstr\tuser name\n\t\t\tauth_token\tstr\tfirst digits of auth token to revoke it on delete\n\t\t\tlast_seen\tint\tlast seen date\n\t\t\tcreated\t\tint\tcreation date\n*/\n\nfunction MobileAppSupport(id, controller) {\n\tMobileAppSupport.super_.call(this, id, controller);\n\n\tthis.PNS = \"https://pns.z-wave.me:5010/v1.0/push\";\n\tthis.URL = \"/smarthome/#/events\"; // TODO make URL specific to the event\n}\n\ninherits(MobileAppSupport, AutomationModule);\n\n_module = MobileAppSupport;\n\nMobileAppSupport.prototype.init = function(config) {\n\tMobileAppSupport.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.defineHandlers();\n\tthis.externalAPIAllow(\"MobileAppSupportAPI\");\n\t\n\tthis.config.apps.forEach(this.announceApp, this);\n}\n\nMobileAppSupport.prototype.stop = function() {\n\tthis.config.apps.forEach(this.unannounceApp, this);\n\t\n\tthis.externalAPIRevoke(\"MobileAppSupportAPI\");\n\n\tMobileAppSupport.super_.prototype.stop.call(this);\n};\n\nMobileAppSupport.prototype.channelID = function(token, app_profile) {\n\treturn this.getName() + \"_\" + this.id + \"_\" + token + \"_\" + app_profile;\n};\n\nMobileAppSupport.prototype.announceApp = function(app) {\n\tvar self = this;\n\t\n\tthis.controller.registerNotificationChannel(this.channelID(app.token, app.app_profile), app.user, app.title + \"(\" + app.profileName + \")\", function(message) {\n\t\tself.sendNotification(app.token, app.app_profile, message);\n\t});\n};\n\nMobileAppSupport.prototype.unannounceApp = function(app) {\n\tthis.controller.unregisterNotificationChannel(this.channelID(app.token, app.app_profile));\n};\n\nMobileAppSupport.prototype.getAppByToken = function(token) {\n\treturn _.findWhere(this.config.apps, {\n\t\ttoken: token\n\t});\n};\n\nMobileAppSupport.prototype.getAppByTokenAppProfile = function(token, app_profile) {\n\treturn _.findWhere(this.config.apps, {\n\t\ttoken: token,\n\t\tapp_profile: app_profile\n\t});\n};\n\nMobileAppSupport.prototype.getApps = function(user) {\n\treturn this.config.apps.filter(function(app) { return user === undefined || app.user === user; });\n};\n\nMobileAppSupport.prototype.registerApp = function(token, title, profileName, os, app_profile, user, authToken) {\n\tvar found_app = _.findWhere(this.config.apps, {\n\t\ttoken: token,\n\t\tapp_profile: app_profile\n\t});\n\t\n\tif (!found_app) {\n\t\t// new app\n\t\tvar app = this.generateApp(token, title, profileName, os, app_profile, user, authToken);\n\t\t\n\t\tthis.config.apps.push(app);\n\t\t\n\t\tthis.announceApp(app);\n\t\t\n\t\tvar profile = this.controller.getProfile(user) || {};\n\t\tvar lang = this.loadModuleLang();\n\t\tthis.addNotification(\"notification\", lang.m_welcome + \": \" + app.title + \" (\" + profile.name + \" / \" + profile.login + \", \" + profileName + \")\", \"module\");\n\t\t\n\t\tthis.permanentAuthToken(user, authToken);\n\t\t\n\t\t// optimization - already done in permanentAuthToken // this.saveConfig();\n\t} else {\n\t\t// existing\n\t\tif (found_app.user === user) {\n\t\t\tif (found_app.auth_token != authToken) {\n\t\t\t\t// just a re-login - no need to re-announce the channel - only update the auth token\n\t\t\t\tthis.removeAuthToken(user, found_app.auth_token);\n\t\t\t\tfound_app.auth_token = authToken;\n\t\t\t\tthis.permanentAuthToken(user, found_app.auth_token);\n\t\t\t}\n\t\t\t\n\t\t\tfound_app.title = title;\n\t\t\tfound_app.profileName = profileName;\n\t\t\tfound_app.last_seen = Date.now();\n\t\t} else {\n\t\t\t// re-register under new token\n\t\t\tvar lang = this.loadModuleLang();\n\t\t\tthis.unregisterApp(token, app_profile);\n\t\t\tthis.registerApp(token, title, profileName, os, app_profile, user);\n\t\t}\n\t}\n\t\n\treturn true;\n};\n\nMobileAppSupport.prototype.unregisterApp = function(token, app_profile) {\n\tvar app = _.findWhere(this.config.apps, {\n\t\ttoken: token,\n\t\tapp_profile: app_profile\n\t});\n\n\tif (app) {\n\t\tvar profile = this.controller.getProfile(app.user) || {};\n\t\tvar lang = this.loadModuleLang();\n\t\tthis.addNotification(\"notification\", lang.m_goodby + \": \" + app.title + \" (\" + profile.name + \" / \" + profile.login + \", \" + profile.profileName + \")\", \"module\");\n\t\t\n\t\tthis.config.apps = _.without(this.config.apps, _.findWhere(this.config.apps, app));\n\t\tthis.saveConfig();\n\t\t\n\t\tthis.unannounceApp(app);\n\t\t\n\t\tthis.removeAuthToken(app.user, app.auth_token);\n\t\t\n\t\treturn true;\n\t}\n\treturn false;\n};\n\nMobileAppSupport.prototype.generateApp = function(token, title, profileName, os, app_profile, user, authToken) {\n\treturn {\n\t\ttoken: token,\n\t\ttitle: title,\n\t\tprofileName: profileName,\n\t\tos: os,\n\t\tapp_profile: app_profile,\n\t\tuser: user,\n\t\tauth_token: authToken,\n\t\tlast_seen: Date.now(),\n\t\tcreated: Date.now()\n\t}\n};\n\nMobileAppSupport.prototype.permanentAuthToken = function(user, authToken) {\n\tvar profile = this.controller.getProfile(user);\n\tif (profile) {\n\t\tthis.controller.permanentToken(profile, authToken);\n\t}\n};\n\nMobileAppSupport.prototype.removeAuthToken = function(user, authToken) {\n\tvar profile = this.controller.getProfile(user);\n\tif (profile) {\n\t\tthis.controller.removeToken(profile, authToken);\n\t}\n};\n\nMobileAppSupport.prototype.sendNotification = function(token, app_profile, notification) {\n\tvar app = this.config.apps.filter(function(app) { return app.token === token && app.app_profile === app_profile; })[0];\n\t\n\tif (app && app.os) {\n\t\tvar message = {\n\t\t\tto: token,\n\t\t\tos: app.os,\n\t\t\tprofileId: app.app_profile,\n\t\t\turl: this.URL,\n\t\t\ttitle: (app.profileName ? app.profileName : \"Smart Home\") + \" \" + this.controller.getRemoteId(),\n\t\t\tbody: notification\n\t\t};\n\t\t\n\t\tconsole.log(\"(Mobile App Support) send notification: \" + JSON.stringify(notification));\n\t\tthis.sendPushMessage(message);\n\t};\n};\n\nMobileAppSupport.prototype.sendPushMessage = function(message) {\n\tvar req = {\n\t\turl: this.PNS,\n\t\tmethod: \"POST\",\n\t\tasync: true,\n\t\tdata: JSON.stringify(message),\n\t\tsuccess: function(response) {\n\t\t\tconsole.log(\"(Mobile App Support) Notification sent\");\n\t\t},\n\t\terror: function(response) {\n\t\t\tconsole.log(\"(Mobile App Support) Notification send failed: \" + JSON.stringify(response));\n\t\t}\n\t};\n\n\ttry {\n\t\thttp.request(req);\n\t} catch (e) {\n\t\tconsole.log(\"(Mobile App Support) Exception during notify listener.\");\n\t}\n};\n\n// --------------- Public HTTP API -------------------\n\nMobileAppSupport.prototype.externalAPIAllow = function (_name) {\n\tws.allowExternalAccess(_name, this.controller.auth.ROLE.USER);\n\tws.allowExternalAccess(_name + \".app\", this.controller.auth.ROLE.USER);\n\t\n\tglobal[_name] = this[_name];\n};\n\nMobileAppSupport.prototype.externalAPIRevoke = function (_name) {\n\tdelete global[_name];\n\t\n\tws.revokeExternalAccess(_name);\n\tws.revokeExternalAccess(_name + \".app\");\n};\n\nMobileAppSupport.prototype.defineHandlers = function () {\n\tvar self = this;\n\n\tthis.MobileAppSupportAPI = function () {\n\t\treturn {status: 400, body: \"Bad MobileAppSupportAPI request \"};\n\t};\n\n\tthis.MobileAppSupportAPI.app = function(url, request) {\n\t\tif (request.method == 'GET') {\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: _.clone(self.getApps(request.role === self.controller.auth.ROLE.ADMIN ? undefined : request.user)).map(function(app) {\n\t\t\t\t\tvar profile = self.controller.getProfile(app.user);\n\t\t\t\t\tapp.userName = profile ? profile.name : '';\n\t\t\t\t\treturn app;\n\t\t\t\t})\n\t\t\t};\n\t\t} else if (request.method == 'POST') {\n\t\t\tvar reqObj;\n\t\t\ttry {\n\t\t\t\treqObj = parseToObject(request.body);\n\t\t\t} catch (e) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tbody: e.toString()\n\t\t\t\t};\n\t\t\t}\n\t\t\t\n\t\t\tif (\n\t\t\t\treqObj &&\n\t\t\t\treqObj.hasOwnProperty('os') && reqObj.os != '' &&\n\t\t\t\treqObj.hasOwnProperty('profileId') && reqObj.profileId != '' &&\n\t\t\t\treqObj.hasOwnProperty('token') && reqObj.token != '' &&\n\t\t\t\treqObj.hasOwnProperty('title') && reqObj.title != ''\n\t\t\t) {\n\t\t\t\tif (self.registerApp(reqObj.token, reqObj.title, reqObj.profileName, reqObj.os, reqObj.profileId, request.user, request.authToken)) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: 'Registrated'\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tbody: 'Already registrated'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tbody: 'Missing arguments os, token, title'\n\t\t\t\t};\n\t\t\t}\n\t\t} else if (request.method == 'DELETE') {\n\t\t\tvar reqObj;\n\t\t\ttry {\n\t\t\t\treqObj = parseToObject(request.body);\n\t\t\t} catch (e) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tbody: e.toString()\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\treqObj &&\n\t\t\t\treqObj.hasOwnProperty('token') && reqObj.token != '' &&\n\t\t\t\treqObj.hasOwnProperty('profileId') && reqObj.profileId != ''\n\t\t\t) {\n\t\t\t\tvar app = self.getAppByTokenAppProfile(reqObj.token, reqObj.profileId);\n\t\t\t\t\n\t\t\t\tif (\n\t\t\t\t\tapp &&\n\t\t\t\t\t(request.role === self.controller.auth.ROLE.ADMIN || request.user == app.user) &&\n\t\t\t\t\tself.unregisterApp(reqObj.token, reqObj.profileId)\n\t\t\t\t) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: 'Deleted'\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 400,\n\t\t\t\t\t\tbody: 'Phone not found'\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tbody: 'Missing argument token or profileId'\n\t\t\t\t};\n\t   \t\t}\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tstatus: 405,\n\t\t\t\tbody: 'Method Not Allowed'\n\t\t\t}\n\t\t}\n\t};\n\tthis.MobileAppSupportAPI.registerApp = this.MobileAppSupportAPI.app; // alias\n};\n"
  },
  {
    "path": "modules/MobileAppSupport/lang/de.json",
    "content": "{\n\t\"m_title\":\"Handy App Unterstützung\",\n\t\"m_descr\":\"Dieses Modul wird von der Z-Way Handy App (Android und iOS) benötigt fur Push Benachrichtigungen\",\n\t\"m_welcome\": \"Phone connected to Z-Way\",\n\t\"m_goodby\": \"Phone disconnected from Z-Way\"\n}"
  },
  {
    "path": "modules/MobileAppSupport/lang/en.json",
    "content": "{\n\t\"m_title\":\"Mobile App Support\",\n\t\"m_descr\":\"This module is required for Z-Way mobile app (Android and iOS) for Push Notification.\",\n\t\"m_welcome\": \"Phone connected to Z-Way\",\n\t\"m_goodby\": \"Phone disconnected from Z-Way\",\n\t\"l_title\": \"Phone name\",\n\t\"l_user\": \"User\",\n\t\"l_os\": \"Type\"\n}"
  },
  {
    "path": "modules/MobileAppSupport/module.json",
    "content": "{\n    \"singleton\": true,\n    \"dependencies\": [],\n    \"category\": \"support_external_ui\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://z-wave.me\",\n    \"icon\": \"icon.png\",\n    \"moduleName\": \"MobileAppSupport\",\n    \"version\": \"2.0.0\",\n    \"maturity\": \"beta\",\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"apps\": []\n    },\n    \"schema\" : {\n        \"type\": \"object\",\n        \"properties\": {\n            \"apps\": {\n                \"type\": \"array\",\n                \"items\": {\n                    \"type\": \"object\",\n                    \"properties\": {\n                        \"token\": {\n                            \"type\": \"string\",\n                            \"readonly\": true\n                        },\n                        \"title\": {\n                            \"type\": \"string\",\n                            \"readonly\": true\n                        },\n                        \"os\": {\n                            \"type\": \"string\",\n                            \"readonly\": true\n                        },\n                        \"app_profile\": {\n                            \"type\": \"string\",\n                            \"readonly\": true\n                        },\n                        \"user\": {\n                            \"type\": \"integer\",\n                            \"field\": \"enum\",\n                            \"datasource\": \"namespaces\",\n                            \"enum\": \"users:id\",\n                            \"readonly\": true\n                        },\n                        \"userName\": {\n                            \"type\": \"string\",\n                            \"readonly\": true\n                        },\n                        \"auth_token\": {\n                            \"type\": \"string\",\n                            \"readonly\": true\n                        },\n                        \"last_seen\": {\n                            \"type\": \"integer\",\n                            \"readonly\": true\n                        },\n                        \"created\": {\n                            \"type\": \"integer\",\n                            \"readonly\": true\n                        }\n                    }\n                }\n            }\n        }\n    },\n    \"options\" : {\n        \"fields\": {\n            \"apps\": {\n                \"items\": {\n                    \"fields\": {\n                        \"token\": {\n                            \"type\": \"hidden\"\n                        },\n                        \"title\": {\n                            \"type\": \"text\",\n                            \"label\": \"__l_title__\"\n                        },\n                        \"os\": {\n                            \"type\": \"text\",\n                            \"label\": \"__l_os__\"\n                        },\n                        \"app_profile\": {\n                            \"type\": \"hidden\"\n                        },\n                        \"user\": {\n                            \"type\": \"select\",\n                            \"datasource\": \"namespaces\",\n                            \"optionLabels\": \"users:title\",\n                            \"label\": \"__l_user__\"\n                        },\n                        \"userName\": {\n                            \"type\": \"hidden\"\n                        },\n                        \"auth_token\": {\n                            \"type\": \"hidden\"\n                        },\n                        \"last_seen\": {\n                            \"type\": \"hidden\"\n                        },\n                        \"created\": {\n                            \"type\": \"hidden\"\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "modules/MultilineSensor/index.js",
    "content": "/*** MultilineSensor Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>\nDescription:\n\tChoose different sensors to merge them into one virtual device.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction MultilineSensor (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tMultilineSensor.super_.call(this, id, controller);\n}\n\ninherits(MultilineSensor, AutomationModule);\n\n_module = MultilineSensor;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nMultilineSensor.prototype.init = function (config) {\n\tMultilineSensor.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tdevices = [],\n\t\tdeviceMetrics = [],\n\t\titem = {},\n\t\tfirstDevice = {},\n\t\tallSensors = [];\n\n\tthis.vDev = null;\n\n\tthis.updateAttributes = function(dev) {\n\t\tvar sensors = [],\n\t\t\tsensor = [],\n\t\t\tindx = null,\n\t\t\tuT = 0;\n\t\t\n\t\tsensors = self.vDev.get('metrics:sensors');\n\n\t\tsensor = sensors.filter(function(sensor){\n\t\t\treturn sensor.id === dev.get('id');\n\t\t});\n\n\t\tif(sensor[0]){\n\t\t\tuT = dev.get('updateTime');\n\t\t\t// update sensor metrics\n\t\t\tsensor[0].metrics = dev.get('metrics');\n\t\t\t\n\t\t\tif (uT > 0) {\n\t\t\t\tsensor[0].updateTime = uT;\n\t\t\t}\t\t\t\n\n\t\t\t// get first sensor\n\t\t\tfirstDevice = sensors[0];\n\t\t}\n\n\t\t// update vDev metrics with values of first sensor\n\t\tself.vDev.set('metrics:icon', self.getIcon(firstDevice));\n\t\tself.vDev.set('metrics:level', self.getLevel(firstDevice));\n\t\tself.vDev.set('metrics:scaleTitle', self.getScaleTitle(firstDevice));\n\t\t\n\t\tif (uT > 0) {\n\t\t\tself.vDev.set('updateTime', uT);\n\t\t}\n\t};\n\n\tthis.createVDevIfSensorsAreCreated = function(dev){\n\t\tvar indx = self.config.devices.map(function(e) { return e.selectedDevice; }).indexOf(dev.id);\n\t\t\n\t\tif(indx > -1 && deviceMetrics.map(function(e) { return e.selectedDevice; }).indexOf(dev.id) === -1){\n\t\t\titem = {\n\t\t\t\tid: dev.id,\n\t\t\t\tdeviceType: dev.get('deviceType'),\n\t\t\t\tmetrics: dev.get('metrics'),\n\t\t\t\thasHistory: dev.get('hasHistory'),\n\t\t\t\tupdateTime: dev.get('updateTime')\n\t\t\t};\n\n\t\t\tdeviceMetrics.push(item);\n\n\t\t\tif(self.config.devices[indx].hide === true) {\n\t\t\t\tdev.set({'visibility': false});\n\t\t\t}else{\n\t\t\t\tdev.set({'visibility': true});\n\t\t\t}\n\n\t\t\tif(deviceMetrics.length > 0){\n\t\t\t\tfirstDevice = deviceMetrics[0];\n\t\t\t}\n\n\t\t\t// update vDev metrics \n\t\t\tself.vDev.set('metrics:icon', self.getIcon(firstDevice));\n\t\t\tself.vDev.set('metrics:level', self.getLevel(firstDevice));\n\t\t\tself.vDev.set('metrics:scaleTitle', self.getScaleTitle(firstDevice));\n\n\t\t\t// listen to sensor changes\n\t\t\tself.controller.devices.on(dev.id, 'change:metrics:level', self.updateAttributes);\n\t\t\tself.controller.devices.on(dev.id, 'change:[object Object]', self.updateAttributes);\n\t\t\tself.controller.devices.on(dev.id, 'change:updateTime', self.updateAttributes);\n\t\t}\n\t};\n\n\tself.controller.devices.filter(function (dev){\n\t\treturn self.config.devices.map(function(e) { return e.selectedDevice; }).indexOf(dev.id) > -1;\n\t}).forEach(function (dev){\n\t\tvar indx = self.config.devices.map(function(e) { return e.selectedDevice; }).indexOf(dev.id);\n\t\t\t \n\t\titem = {\n\t\t\tid: dev.id,\n\t\t\tdeviceType: dev.get('deviceType'),\n\t\t\tmetrics: dev.get('metrics'),\n\t\t\thasHistory: dev.get('hasHistory'),\n\t\t\tupdateTime: dev.get('updateTime')\n\t\t};\n\n\t\tdeviceMetrics.push(item);\n\n\t\tif(self.config.devices[indx].hide === true) {\n\t\t\tdev.set({'visibility': false});\n\t\t}else{\n\t\t\tdev.set({'visibility': true});\n\t\t}\n\n\t\t// listen to sensor changes\n\t\tself.controller.devices.on(dev.id, 'change:metrics:level', self.updateAttributes);\n\t\tself.controller.devices.on(dev.id, 'change:[object Object]', self.updateAttributes);\n\t\tself.controller.devices.on(dev.id, 'change:updateTime', self.updateAttributes);\n\t});\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"Multiline_\" + this.id,\n\t\tdefaults: {\n\t\t\tmetrics: {\n\t\t\t\tmultilineType: 'multilineSensor',\n\t\t\t\ttitle: self.getInstanceTitle(),\n\t\t\t\ticon: self.getIcon(deviceMetrics[0]),\n\t\t\t\tlevel: self.getLevel(deviceMetrics[0]),\n\t\t\t\tscaleTitle: self.getScaleTitle(deviceMetrics[0])\n\t\t\t}\n\t\t},\n\t\toverlay: {\n\t\t\tdeviceType: 'sensorMultiline',\n\t\t\tmetrics: {\n\t\t\t\ttitle: self.getInstanceTitle(),\n\t\t\t\tsensors: deviceMetrics,\n\t\t\t\ticon: self.getIcon(deviceMetrics[0]),\n\t\t\t\tlevel: self.getLevel(deviceMetrics[0]),\n\t\t\t\tscaleTitle: self.getScaleTitle(deviceMetrics[0])\n\t\t\t}\n\t\t},\n\t\thandler: function(command){\n\t\t\tif(command === 'update' && deviceMetrics.length > 0){\n\t\t\t\tdeviceMetrics.forEach(function(sensor){\n\t\t\t\t\tgetDev = self.controller.devices.filter(function(vDev){\n\t\t\t\t\t\t\t\treturn sensor.id === vDev.id;\n\t\t\t\t\t\t\t});\n\t\t\t\t\ttry{\n\t\t\t\t\t\tgetDev[0].performCommand('update');\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tself.controller.addNotification('device-info', 'Update has failed. Error:' + e , 'device-status', getDev[0].id);\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\t// refresh/create virtual device if sensors are created (after restart)\n\tself.controller.devices.on('created', self.createVDevIfSensorsAreCreated);\n};\n\nMultilineSensor.prototype.stop = function () {\n\tvar self = this;\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tself.controller.devices.filter(function (dev){\n\t\treturn self.config.devices.map(function(e) { return e.selectedDevice; }).indexOf(dev.id) > -1;\n\t}).forEach(function (dev){\n\t\t\n\t\tif(dev.get('visibility') === false) {\n\t\t\tdev.set({'visibility': true});\n\t\t}\n\n\t\tself.controller.devices.off(dev.id, 'change:metrics:level', self.updateAttributes);\n\t\tself.controller.devices.off(dev.id, 'change:[object Object]', self.updateAttributes);\n\t\tself.controller.devices.off(dev.id, 'change:updateTime', self.updateAttributes);\n\t\tself.controller.devices.off('created', self.createVDevIfSensorsAreCreated);\n\t});\n\n\tMultilineSensor.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nMultilineSensor.prototype.getIcon = function (device) {\n\treturn device && device.metrics.icon? device.metrics.icon : '';\n};\n\nMultilineSensor.prototype.getScaleTitle = function (device) {\n\treturn device && device.metrics.scaleTitle? device.metrics.scaleTitle : '';\n};\n\nMultilineSensor.prototype.getLevel = function (device) {\n\treturn device && device.metrics.level? device.metrics.level : '';\n};\n\nMultilineSensor.prototype.getTitle = function (device) {\n\treturn device && device.metrics.title? device.metrics.title : '';\n};"
  },
  {
    "path": "modules/MultilineSensor/lang/de.json",
    "content": "{\n\t\"m_title\":\"Multi-Sensor\",\n\t\"m_descr\":\"(Führt mehrere Sensoren in einem Element zusammen.)<br>Diese App bündelt bis zu 10 Sensorwerte in einem UI Element. Der erste ausgewählte Sensor wird als Elementwert angezeigt. Jeder weitere ausgewählte Sensorwert erscheint in einem Splash-Screen, der bei Klick auf das Element sichtbar wird. Außerdem kann das ursprünglich für die erwählten Sensoren erstellte Element ausgeblendet werden. Diese App hilft zur Optimierung der Benutzeroberfläche durch Entfernung einiger zur Verwendung empfohlener Sensorelemente ohne den Zugang zu deren zur Nutzung zu blockieren. Das gilt zum Beispiel für die Zusammenfassung von Sensoren zu einer logischen Gruppe (Bsp.: ein intelligenter Stromzähler, der sowohl den Stromverbrauch aller Geräte sowie einige individuelle Werte, z. B. für die 3 Phasen im Haus liefert)<br><br>Einstellungen: Bestimmen Sie die Sensoren, welche Sie zusammenführen möchten und entscheiden Sie, ob diese als Einzelelement ausgeblendet werden sollen. \",\n\t\"l_devices\":\"Erzeuge ein neues virtuelles Gerät aus den folgenden Sensoren:\",\n\t\"h_devices\":\"Es lassen sich maximal bis zu 10 Sensoren kombinieren.\",\n\t\"rl_hidden\":\"Gerät in 'Elementeübersicht' ausblenden\",\n\t\"l_choose_dev\":\"--- Gerät wählen ---\"\n}"
  },
  {
    "path": "modules/MultilineSensor/lang/en.json",
    "content": "{\n\t\"m_title\":\"Multi Sensor\",\n\t\"m_descr\":\"(Combine multiple sensors into one element) <br>This app allows grouping up to 10 sensor values into one element of the UI. The first selected sensor will be shown as the value of the element. Every additional selected sensor value will appear in a splash screen visible when clicking on the element.  Additionally the element originally created for the selected sensors may be hidden.This app helps improve the User Interface by removing some sensor elements without blocking access to its recommended to use this e.g. for sensors that form a logical group (like a smart power meter that provides both power draw for all devices plus some individual values e.g. for the three phases in the house)<br><br>Settings: Select the sensors you like to combine and decide if they shall be hidden as individual element.\",\n\t\"l_devices\":\"Create a new virtual device with the sensors choosen below:\",\n\t\"h_devices\":\"You can only combine up to 10 sensors with each other.\",\n\t\"rl_hidden\":\"Do not show device in elements view\",\n\t\"l_choose_dev\":\"--- Choose a device ---\"\n}"
  },
  {
    "path": "modules/MultilineSensor/module.json",
    "content": "{\n\t\"singleton\" : false,\n\t\"dependencies\": [],\n\t\"category\" : \"device_enhancements\",\n\t\"author\" : \"Z-Wave.Me\",\n\t\"homepage\" : \"http://razberry.z-wave.me\",\n\t\"icon\" : \"icon.png\",\n\t\"moduleName\":\"MultilineSensor\",\n\t\"version\" : \"1.1.0\",\n\t\"maturity\" : \"stable\",\n\t\"repository\" : {\n\t\t\"type\" : \"git\",\n\t\t\"source\" : \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\" : {\n\t\t\"title\" : \"__m_title__\",\n\t\t\"description\" : \"__m_descr__\",\n\t\t\"devices\": []\n\t},\n\t\"schema\": {\n\t\t\"properties\": {\n\t\t\t\"devices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"maxItems\":10,\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"$ref\": \"#/definitions/device\"\t\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"definitions\":{\n\t\t\t\"device\": {\n\t\t\t\t\"type\":\"object\",\n\t\t\t\t\"properties\":{\n\t\t\t\t\t\"selectedDevice\":{\n\t\t\t\t\t\t\"field\":\"enum\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId\"\n\t\t\t\t\t},\n\t\t\t\t\t\"hide\" : {\n\t\t\t\t\t\t\"type\" : \"boolean\",\n\t\t\t\t\t\t\"dependencies\": \"selectedDevice\",\n\t\t\t\t\t\t\"required\" : false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"devices\": {\n\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\"helper\": \"__h_devices__\"\n\t\t\t}\n\t\t},\n\t\t\"definitions\":{\n\t\t\t\"fields\":{\n\t\t\t\t\"device\":{\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"selectedDevice\" : {\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"removeDefaultNone\": false,\n\t\t\t\t\t\t\t\"noneLabel\": \"__l_choose_dev__\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName\"\t\t\t\t\t\t\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"hide\": {\n\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\"rightLabel\":\"__rl_hidden__\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\t\t\t\t\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/NotificationChannelEmail/htdocs/js/postRender.js",
    "content": "function modulePostRender() {\r\n\t$.ajax(\"/ZAutomation/api/v1/profiles\")\r\n\t\t.done(function(profilesResponse) {\r\n\t\t\tif (profilesResponse.data && profilesResponse.data.length) {\r\n\t\t\t\tvar list = $(\"<ul></ul>\");\r\n\t\t\t\tvar content = [];\r\n\t\t\t\tprofilesResponse.data.forEach(function(p) {\r\n\t\t\t\t\tif (p.email) {\r\n\t\t\t\t\t\tcontent.push($(\"<li>\" + p.email + \" (\" + p.name + \")</li>\"));\r\n\t\t\t\t\t}\r\n\t\t\t\t});\r\n\t\t\t\tif (content.length) {\r\n\t\t\t\t\tcontent.forEach(function(row) { list.append(row); });\r\n\t\t\t\t\t$(\"#alpaca_data legend\").first().append(list);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t});\r\n};\r\n"
  },
  {
    "path": "modules/NotificationChannelEmail/index.js",
    "content": "/*** NotificationChannelEmail Z-Way HA module *******************************************\n\n Version: 3.0.0\n (c) Z-Wave.Me, 2020\n -----------------------------------------------------------------------------\n Author: Serguei Poltorak <ps@z-wave.me>\n Description:\n Add notification channel and send notifications via e-mail.\n\n ******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction NotificationChannelEmail (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tNotificationChannelEmail.super_.call(this, id, controller);\n\n\tthis.emailRe = /^(([^<>()\\[\\]\\.,;:\\s@\\\"]+(\\.[^<>()\\[\\]\\.,;:\\s@\\\"]+)*)|(\\\".+\\\"))@(([^<>()[\\]\\.,;:\\s@\\\"]+\\.)+[^<>()[\\]\\.,;:\\s@\\\"]{2,})$/i;\n}\n\ninherits(NotificationChannelEmail, AutomationModule);\n\n_module = NotificationChannelEmail;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nNotificationChannelEmail.prototype.init = function (config) {\n\tNotificationChannelEmail.super_.prototype.init.call(this, config);\n\n\tthis.remote_id = this.controller.getRemoteId();\n\n\tthis.disabled = false;\n\t\n\tthis.collectedMessages = [];\n\n\tthis.subscribe(config);\n\n\tvar self = this;\n\t\n\tthis.onProfileUpdate = function(profile) {\n\t\tself.unsubscribe();\n\t\tself.subscribe(config);\n\t}\n\t\n\tthis.controller.on('profile.updated', this.onProfileUpdate);\n};\n\nNotificationChannelEmail.prototype.stop = function () {\n\tif (this.timer) {\n\t\tclearInterval(this.timer);\n\t\tthis.timer = undefined;\n\t}\n\t\n\tif (this.onProfileUpdate) {\n\t\tthis.controller.off('profile.updated', this.onProfileUpdate);\n\t}\n\t\n\tthis.unsubscribe();\n\t\n\tNotificationChannelEmail.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nNotificationChannelEmail.prototype.subscribe = function(config) {\n\tvar self = this;\n\t\n\t// Loop thru all configured mails\n\tconfig.channels.forEach(function (channel) {\n\t\tif (self.emailRe.test(channel.email)) {\n\t\t\tvar user = channel.user || 0;\n\t\t\tself.controller.registerNotificationChannel(self.channelID(user, channel.email), user, \"E-Mail to \" + channel.email, function(message) {\n\t\t\t\tself.sender(channel.email, message);\n\t\t\t});\n\t\t} else if (channel.email) {\n\t\t\tself.addNotification('error', 'Invalid e-mail addrress ' + channel.email, 'module');\n\t\t}\n\t});\n\t\n\t// Loop thru mails of all users\n\tthis.controller.profiles.forEach(function (user) {\n\t\tif (self.emailRe.test(user.email)) {\n\t\t\tself.controller.registerNotificationChannel(self.channelID(user.id, user.email), user.id, \"E-Mail to \" + user.name + \" (\" + user.email + \")\", function(message) {\n\t\t\t\tself.sender(user.email, message);\n\t\t\t});\n\t\t} else if (user.email) {\n\t\t\tself.addNotification('error', 'invalid e-mail addrress ' + user.email, 'module');\n\t\t}\n\t});\n};\n\nNotificationChannelEmail.prototype.unsubscribe = function() {\n\tvar self = this;\n\t\n\t// uregister all in one shot by prefix\n\tObject.keys(this.controller.notificationChannels).forEach(function (id) {\n\t\tvar prefix = self.channelIDPrefix();\n\t\t\n\t\tif (id.lastIndexOf(prefix) === 0) {\n\t\t\tself.controller.unregisterNotificationChannel(id);\n\t\t}\n\t});\n};\n\nNotificationChannelEmail.prototype.channelIDPrefix = function() {\n\treturn this.getName() + \"_\" + this.id + \"_\";\n};\n\nNotificationChannelEmail.prototype.channelID = function(profileId, email) {\n\treturn this.channelIDPrefix() + profileId + \"_\" + email;\n};\n\nNotificationChannelEmail.prototype.sender = function(to, message) {\n\tif (this.disabled) return;\n\t\n\t// check mail validity\n\tif (!this.emailRe.test(to)) {\n\t\tthis.addNotification('error', 'invalid e-mail addrress ' + to, 'module');\n\t\treturn;\n\t}\n\t\n\tthis.collectedMessages.push({\n\t\tmail_to: to,\n\t\tmessage: message\n\t});\n\t\n\tif (!this.timer) {\n\t\tthis.sendSendMessageWithDelay();\n\t}\n}\n\nNotificationChannelEmail.prototype.sendSendMessageWithDelay = function () {\n\tvar self = this,\n\t\tmailObject = {};\n\n\tthis.timer = setInterval( function() {\n\n\t\tif (self.collectedMessages.length > 0) {\n\t\t\tmailObject = self.collectedMessages.shift();\n\n\t\t\tconsole.log(self.getName() + \" Sending a message to \" + mailObject.mail_to);\n\t\t\thttp.request({\n\t\t\t\tmethod: \"POST\",\n\t\t\t\turl: \"https://service.z-wave.me/emailnotification/index.php\",\n\t\t\t\tasync: true,\n\t\t\t\tdata: {\n\t\t\t\t\tremote_id: self.remote_id,\n\t\t\t\t\tmail_to: mailObject.mail_to,\n\t\t\t\t\tsubject: mailObject.message,\n\t\t\t\t\tmessage: mailObject.message + \"<br>\" + (new Date()),\n\t\t\t\t\tlanguage: self.controller.defaultLang\n\t\t\t\t},\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\"\n\t\t\t\t},\n\t\t\t\terror: function(response) {\n\t\t\t\t\tconsole.log(\"NotificationChannelEmail error: \" + (typeof response !== 'string'? JSON.stringify(response) : response));\n\t\t\t\t\tself.disabled = true; // disable infinite loop sending e-mail notification about faulure to send e-mail notification\n\t\t\t\t\tself.addNotification('error', 'NotificationChannelEmail error' + (typeof response === 'string'? ': ' + JSON.stringify(response) : ''), 'module');\n\t\t\t\t\tself.disabled = false;\n\t\t\t\t}\n\t\t\t});\n\t\t} else {\n\t\t\tif (self.timer) {\n\t\t\t\tclearInterval(self.timer);\n\t\t\t\tself.timer = undefined;\n\t\t\t}\n\t\t}\n\t}, 5000);\n};\n"
  },
  {
    "path": "modules/NotificationChannelEmail/lang/en.json",
    "content": "{\n  \"m_title\": \"Notifications by E-mail\",\n  \"m_descr\": \"This app sends notifications by e-mail.\",\n  \"l_emails\": \"Recepients\",\n  \"h_emails\": \"User's E-mails are registered automatically. Add here additional recipients.\",\n  \"l_email\": \"E-mail\",\n  \"l_assignedToUser\": \"Assign this E-Mail to a user\",\n  \"h_assignedToUser\": \"If set, this E-Mail will be also used to send notifications to the user\",\n  \"l_not_assigned_to_user\": \"Don't assign to a user\",\n  \"m_subject\": \"Z-Way Notification\",\n  \"l_subject\": \"Subject\",\n  \"h_subject\": \"The subject for E-mail messages\"\n}"
  },
  {
    "path": "modules/NotificationChannelEmail/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"notifications\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"NotificationChannelEmail\",\n\t\"version\": \"3.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"subject\": \"__m_subject__\",\n\t\t\"channels\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"subject\": {\n\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\"required\" : true\n\t\t\t},\n\t\t\t\"channels\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"email\": {\n\t\t\t\t\t\t\t\"type\" : \"string\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"user\": {\n\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"users:id\",\n\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"subject\": {\n\t\t\t\t\"label\": \"__l_subject__\",\n\t\t\t\t\"helper\": \"__h_subject__\"\n\t\t\t},\n\t\t\t\"channels\": {\n\t\t\t\t\"label\": \"__l_emails__\",\n\t\t\t\t\"helper\": \"__h_emails__\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"email\": {\n\t\t\t\t\t\t\t\"label\": \"__l_email__\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"user\": {\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"optionLabels\": \"users:title\",\n\t\t\t\t\t\t\t\"noneLabel\": \"__l_not_assigned_to_user__\",\n\t\t\t\t\t\t\t\"label\": \"__l_assignedToUser__\",\n\t\t\t\t\t\t\t\"helper\": \"__h_assignedToUser__\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"postRender\": \"loadFunction:postRender.js\"\n}"
  },
  {
    "path": "modules/NotificationFiltering/index.js",
    "content": "/*** NotificationFiltering Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction NotificationFiltering (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tNotificationFiltering.super_.call(this, id, controller);\n}\n\ninherits(NotificationFiltering, AutomationModule);\n\n_module = NotificationFiltering;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nNotificationFiltering.prototype.init = function (config) {\n\tNotificationFiltering.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.normalizeConfig();\n\tthis.readConfig();\n\n\tthis.handler = function(notice) {\n\t\tself.onNotificationHandler(notice);\n\t};\n\tthis.controller.on('notifications.push', this.handler);\n\t\n\t// automaitcally delete and add default notification for devices\n\tif (this.config.autogenOnDeviceListUpdate) {\n\t\tthis.handleDeviceListUpdate = function(params) {\n\t\t\tself.onDeviceListUpdate(params);\n\t\t};\n\t\tthis.controller.on('profile.deviceListUpdated', this.handleDeviceListUpdate);\n\t}\n\t\n\tthis.handlerUserConfigUpdate = function(user, config) {\n\t\tself.userConfigUpdate(user, config);\n\t};\n\tthis.controller.on('notificationFiltering.userConfigUpdate', this.handlerUserConfigUpdate);\n};\n\nNotificationFiltering.prototype.stop = function () {\n\tNotificationFiltering.super_.prototype.stop.call(this);\n\t\n\tif (this.config.autogenOnDeviceListUpdate) {\n\t\tthis.controller.off('profile.deviceListUpdated', this.handleDeviceListUpdate);\n\t}\n\tthis.controller.off('notifications.push', this.handler);\n\tthis.controller.off('notificationFiltering.userConfigUpdate', this.handlerUserConfigUpdate);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nNotificationFiltering.prototype.prepareMessage = function(message, devId) {\n\tvar regex = /<([^:<> ]*):([^<> ]*)>/; // match <devId:metrics:level> or <:metrics:level>\n\twhile ((search = regex.exec(message))) {\n\t\tvar vDev = this.controller.devices.get(search[1] ? search[1] : devId);\n\t\tif (vDev) {\n\t\t\tmessage = message.replace(search[0], vDev.get(search[2]) || \"\")\n\t\t}\n\t}\n\treturn message;\n}\n\n\nNotificationFiltering.prototype.onNotificationHandler = function (notice) {\n\tvar self = this;\n\n\tif (!notice || !notice.message) return;\n\t\n\tvar sendTo = [];\n\tvar defaultMessage = typeof notice.message === 'string' ? notice.message : (notice.message.dev + \" : \" + notice.message.l);\n\t\n\tdefaultMessage = this.prepareMessage(defaultMessage, notice.source);\n\t\n\tObject.keys(self.logLevels).forEach(function (level) {\n\t\tif (\n\t\t\t(level === \"errors\" && (notice.level === \"critical\"|| notice.level === \"error\")) ||\n\t\t\t(level === \"notifications\" && (notice.level == \"notification\" || notice.level == \"device-info\" || notice.level == \"info\")) ||\n\t\t\t(level === \"warnings\" && notice.level == \"warning\")\n\t\t) {\n\t\t\tself.logLevels[level].forEach(function(ch) {\n\t\t\t\tsendTo.push({\n\t\t\t\t\ttype: ch.type,\n\t\t\t\t\tuser: ch.user,\n\t\t\t\t\tchannel: ch.channel,\n\t\t\t\t\tmessage: defaultMessage\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t});\n\t\n\tself.devices.forEach(function (device) {\n\t\tif (notice.source == device.id) {\n\t\t\tvar send = true;\n\t\t\tif (device.comparator !== null) {\n\t\t\t\tvar value = parseFloat(notice.message.l);\n\t\t\t\tif (isNaN(value)) {\n\t\t\t\t\tif (eval(\"'\" + notice.message.l + \"'\" + device.comparator) === false) {\n\t\t\t\t\t\tsend = false;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (eval(value + device.comparator) === false) {\n\t\t\t\t\t\tsend = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (send) {\n\t\t\t\tsendTo.push({\n\t\t\t\t\ttype: device.type,\n\t\t\t\t\tuser: device.user,\n\t\t\t\t\tchannel: device.channel,\n\t\t\t\t\tmessage: device.message ? self.prepareMessage(device.message, device.id) : defaultMessage\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t});\n\n\tsendTo.forEach(function(to) {\n\t\tif (to.type === \"user\") {\n\t\t\tself.controller.notificationUserChannelsSend(to.user, to.message);\n\t\t} else if (to.type === \"channel\") {\n\t\t\tself.controller.notificationChannelSend(to.channel, to.message);\n\t\t} else {\n\t\t\tself.controller.notificationAllChannelsSend(to.message);\n\t\t}\n\t});\n};\n\nNotificationFiltering.prototype.normalizeConfig = function() {\n\tvar self = this;\n\t\n\tif (this.config.normalizeRules) {\n\t\tvar users = _.compact(_.uniq(this.config.rules.filter(function(rule) { return rule.user && rule.recipient_type === \"user\"; }).map(function(rule) { return rule.user; })));\n\t\tvar channels = _.compact(_.uniq(this.config.rules.filter(function(rule) { return rule.channel && rule.recipient_type === \"channel\"; }).map(function(rule) { return rule.channel; })));\n\t\t\n\t\tvar newRules = [];\n\t\t\n\t\tusers.forEach(function(user) {\n\t\t\tvar userRules = self.config.rules.filter(function(rule) { return rule.user === user; });\n\t\t\t\n\t\t\tvar logLevel = _.uniq(_.compact(_.flatten(userRules.map(function(rule) { return rule.logLevel ? rule.logLevel.split(',') : [\"\"]; })))).join(',');\n\t\t\tvar devices = [];\n\t\t\t\n\t\t\tuserRules.forEach(function(rule) {\n\t\t\t\trule.devices.forEach(function(dev) {\n\t\t\t\t\tdevices = devices.concat(dev);\n\t\t\t\t});\n\t\t\t});\n\t\t\tnewRules.push({\n\t\t\t\trecipient_type: \"user\",\n\t\t\t\tuser: user,\n\t\t\t\tlogLevel: logLevel,\n\t\t\t\tdevices: devices\n\t\t\t});\n\t\t});\n\t\t\n\t\tchannels.forEach(function(channel) {\n\t\t\tvar channelRules = self.config.rules.filter(function(rule) { return rule.channel === channel; });\n\t\t\t\n\t\t\tvar logLevel = _.uniq(_.compact(_.flatten(channelRules.map(function(rule) { return rule.logLevel ? rule.logLevel.split(',') : [\"\"]; })))).join(',');\n\t\t\tvar devices = [];\n\t\t\t\n\t\t\tchannelRules.forEach(function(rule) {\n\t\t\t\trule.devices.forEach(function(dev) {\n\t\t\t\t\tdevices = devices.concat(dev);\n\t\t\t\t});\n\t\t\t});\n\t\t\tnewRules.push({\n\t\t\t\trecipient_type: \"channel\",\n\t\t\t\tchannel: channel,\n\t\t\t\tlogLevel: logLevel,\n\t\t\t\tdevices: devices\n\t\t\t});\n\t\t});\n\t\t\n\t\tvar allRules = this.config.rules.filter(function(rule) { return rule.recipient_type === \"all\"; });\n\t\tif (allRules.length) {\n\t\t\tvar logLevel = _.uniq(_.compact(_.flatten(allRules.map(function(rule) { return rule.logLevel ? rule.logLevel.split(',') : [\"\"]; })))).join(',');\n\t\t\tvar devices = [];\n\t\t\t\n\t\t\tallRules.forEach(function(rule) {\n\t\t\t\trule.devices.forEach(function(dev) {\n\t\t\t\t\tdevices = devices.concat(dev);\n\t\t\t\t});\n\t\t\t});\n\t\t\tnewRules.push({\n\t\t\t\trecipient_type: \"all\",\n\t\t\t\tlogLevel: logLevel,\n\t\t\t\tdevices: devices\n\t\t\t});\n\t\t}\n\t\t\n\t\tthis.config.rules = newRules;\n\t}\n\tthis.saveConfig();\n};\n\nNotificationFiltering.prototype.readConfig = function () {\n\tvar self = this;\n\n\tthis.devices = [];\n\tthis.logLevels = {};\n\t\n\t// normalize rules (keep each user/channel/all only once)\n\t// TODO\n\t\n\t// parse rules\n\tthis.config.rules.forEach(function(rule) {\n\t\tvar recipientType = rule.recipient_type,\n\t\t    user = rule.user,\n\t\t    channel = rule.channel;\n\t\t\n\t\tif (rule.logLevel) {\n\t\t\trule.logLevel.split(',').forEach(function(logLevel) {\n\t\t\t\tif (!self.logLevels[logLevel]) self.logLevels[logLevel] = [];\n\t\t\t\tself.logLevels[logLevel].push({type: recipientType, user: user, channel: rule.channel});\n\t\t\t});\n\t\t}\n\t\t\n\t\trule.devices.forEach(function(device) {\n\t\t\tvar d, ml = false;\n\t\t\t\n\t\t\tif (device.dev_toggleButton) {\n\t\t\t\td = device.dev_toggleButton;\n\t\t\t} else if (device.dev_switchControl) {\n\t\t\t\td = device.dev_switchControl;\n\t\t\t\tml = true;\n\t\t\t} else if (device.dev_switchBinary) {\n\t\t\t\td = device.dev_switchBinary;\n\t\t\t} else if (device.dev_switchMultilevel) {\n\t\t\t\td = device.dev_switchMultilevel;\n\t\t\t\tml = true;\n\t\t\t} else if (device.dev_sensorBinary) {\n\t\t\t\td = device.dev_sensorBinary;\n\t\t\t} else if (device.dev_sensorMultilevel) {\n\t\t\t\td = device.dev_sensorMultilevel;\n\t\t\t\tml = true;\n\t\t\t} else if (device.dev_sensorMultiline) {\n\t\t\t\td = device.dev_sensorMultiline;\n\t\t\t\tml = true;\n\t\t\t} else if (device.dev_fan) {\n\t\t\t\td = device.dev_fan;\n\t\t\t\tml = true;\n\t\t\t} else if (device.dev_doorlock) {\n\t\t\t\td = device.dev_doorlock;\n\t\t\t\tml = true;\n\t\t\t} else if (device.dev_thermostat) {\n\t\t\t\td = device.dev_thermostat;\n\t\t\t\tml = true;\n\t\t\t} else {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tvar comparator = null;\n\t\t\tif (ml) {\n\t\t\t\tif (d.dev_matchValue && d.dev_matchValue.dev_matchValueOperation && d.dev_matchValue.dev_matchValue !== 'all' && d.dev_matchValue.dev_matchValueOperand) {\n\t\t\t\t\tcomparator = d.dev_matchValue.dev_matchValueOperation + d.dev_matchValue.dev_matchValueOperand;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (d.dev_matchValue && d.dev_matchValue !== 'all') {\n\t\t\t\t\tcomparator = \"=='\" + d.dev_matchValue + \"'\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\t// each device can be present multiple times with different channels\n\t\t\tself.devices.push({\n\t\t\t\t\"id\": d.dev_select,\n\t\t\t\t\"message\": d.dev_message,\n\t\t\t\t\"comparator\": comparator,\n\t\t\t\t\"type\": recipientType,\n\t\t\t\t\"user\": user,\n\t\t\t\t\"channel\": channel\n\t\t\t});\n\t\t});\n\t});\n};\n\nNotificationFiltering.prototype.addRule = function(userId, deviceId, deviceType, matchValueOperation, matchValue) {\n\tvar dev = {};\n\t\n\tdev[\"dev_filter\"] = deviceType;\n\tdev[deviceType] = {};\n\tdev[deviceType][\"dev_select\"] =  deviceId;\n\tif (matchValueOperation) dev[deviceType][\"dev_matchValueOperation\"] = matchValueOperation;\n\tif (matchValue) dev[deviceType][\"dev_matchValue\"] = matchValue;\n\t\n\tconsole.log(\"Adding rule for user \" + userId + \" for device \" + deviceId);\n\tthis.config.rules.push({\n\t\trecipient_type: \"user\",\n\t\tuser: userId,\n\t\tdevices: [dev]\n\t});\n};\n\nNotificationFiltering.prototype.removeUserDeviceRules = function(userId, deviceId) {\n\tvar self = this;\n\t\n\tthis.config.rules.forEach(function(rule) {\n\t\tif (rule.recipient_type === \"user\" && rule.user === userId || rule.recipient_type === \"channel\" && self.controller.getNotificationChannel(rule.channel) && self.controller.getNotificationChannel(rule.channel).user === userId) {\n\t\t\tconsole.log(\"Removing rule for user \" + userId + \" for device \" + deviceId);\n\t\t\trule.devices = rule.devices.filter(function(dev) { return dev[dev[\"dev_filter\"]][\"dev_select\"] !== deviceId });\n\t\t}\n\t});\n\t// clean empty\n\tthis.config.rules = this.config.rules.filter(function(rule) { return rule.devices.length || rule.logLevel });\n};\n\nNotificationFiltering.prototype.onDeviceListUpdate = function (params) {\n\tvar self = this;\n\t\n\tvar userId = params.profile.id;\n\t\n\tparams.deleted.forEach(function(id) {\n\t\tself.removeUserDeviceRules(userId, id);\n\t});\n\t\n\tparams.added.forEach(function(id) {\n\t\tvar dev = self.controller.devices.get(id)\n\t\t\n\t\tif (dev.get(\"permanently_hidden\") || !dev.get(\"visibility\")) return;\n\t\t\n\t\tvar dt = dev.get('deviceType'),\n\t\t    pt = dev.get('probeType');\n\t\t\n\t\t// Notify on alarm trigger\n\t\tif (\n\t\t\tdt === \"sensorBinary\" && [\"general_purpose\", \"smoke\", \"co\", \"flood\", \"door-window\", \"tamper\", \"motion\"].indexOf(pt) > -1 ||\n\t\t\tdt === \"sensorBinary\" && [\"alarmSensor_general_purpose\", \"alarmSensor_smoke\", \"alarmSensor_co\", \"alarmSensor_coo\", \"alarmSensor_heat\", \"alarmSensor_flood\", \"alarmSensor_door\", \"alarmSensor_burglar\", \"alarmSensor_power\", \"alarmSensor_system\", \"alarmSensor_emergency\", \"alarmSensor_clock\"].indexOf(pt) > -1 ||\n\t\t\tdt === \"sensorBinary\" && [\"alarm_smoke\", \"alarm_co\", \"alarm_coo\", \"alarm_heat\", \"alarm_flood\", \"alarm_burglar\", \"alarm_power\", \"alarm_system\", \"alarm_emergency\", \"alarm_clock\", \"siren\", \"gas\"].indexOf(pt) > -1\n\t\t) {\n\t\t\tself.addRule(userId, id, \"dev_sensorBinary\", null, \"on\");\n\t\t}\n\t\t\n\t\t// Notify on siren on\n\t\tif (dt === \"switchBinary\" && pt === \"siren\") {\n\t\t\tself.addRule(userId, id, \"dev_switchBinary\", null, \"on\");\n\t\t}\n\t\t\n\t\t\n\t\t// Notify on valve open/close\n\t\tif (dt === \"switchBinary\" && pt === \"valve\") {\n\t\t\tself.addRule(userId, id, \"dev_switchBinary\", null, \"all\");\n\t\t}\n\t\t\n\t\t// Notify on doorlock open/close\n\t\tif (dt === \"switchBinary\" && pt === \"doorlock\") {\n\t\t\tself.addRule(userId, id, \"dev_doorlock\", null, \"all\");\n\t\t}\n\t\t\n\t\t// Notify on low battery\n\t\tif (dt === \"sensorMultilevel\" && pt === \"battery\" || dt === \"battery\") {\n\t\t\tself.addRule(userId, id, \"dev_sensorMultilevel\", \"<\", 10);\n\t\t}\n\t});\n\t\n\tthis.normalizeConfig();\n\tthis.readConfig();\n};\n\nNotificationFiltering.prototype.userConfigUpdate = function(user, config) {\n\tvar self = this;\n\tvar devsStruct = [];\n\t\n\t// remove all rules for that user and his channels (keep global flags)\n\tvar toRemove = [];\n\tthis.config.rules.forEach(function(rule, index) {\n\t\tvar chUser;\n\t\tif (\n\t\t   (rule.recipient_type === \"user\" && rule.user == user) || // non-strict == because might be as string in module params\n\t\t   (rule.recipient_type === \"channel\" && (chUser = self.controller.getNotificationChannel(rule.channel)) && chUser.user == user) // non-strict == because might be as string in module params\n\t\t) {\n\t\t\trule.devices = [];\n\t\t\tif (!rule.logLevel) { // if no global flags, remove\n\t\t\t\ttoRemove.unshift(index); // add to remove list in reverse order\n\t\t\t}\n\t\t}\n\t});\n\t\n\ttoRemove.forEach(function(i) {\n\t\tself.config.rules.splice(i, 1);\n\t});\n\t\n\tvar userDevices = this.controller.devicesByUser(user).map(function(dev) { return dev.id; });\n\t\n\tconfig.forEach(function(rule) {\n\t\tvar channel = self.controller.getNotificationChannel(rule.channel);\n\t\t\n\t\t// validity and access checks\n\t\t\n\t\tif (rule.recipient_type === \"channel\") {\n\t\t\tif (!rule.channel || !channel) return; // invalid format\n\t\t\tif (channel.user != user) return; // access violation\n\t\t}\n\t\tif (rule.recipient_type === \"user\") {\n\t\t\tif (!rule.user) return; // invalid format\n\t\t\tif (rule.user != user) return; // access violation\n\t\t}\n\t\t// filter by device validity and access\n\t\trule.devices = rule.devices.filter(function(d) {\n\t\t\tif (!d[\"dev_filter\"]) return false; // invalid format\n\t\t\tif (!d[d[\"dev_filter\"]] || !d[d[\"dev_filter\"]][\"dev_select\"]) return false; // invalid format\n\t\t\treturn userDevices.indexOf(d[d[\"dev_filter\"]][\"dev_select\"]) > -1;\n\t\t});\n\t\t\n\t\t\n\t\tself.config.rules.push(rule);\n\t});\n\n\tthis.normalizeConfig();\n\tthis.readConfig();\t\t\t\n}\n"
  },
  {
    "path": "modules/NotificationFiltering/lang/en.json",
    "content": "{\n  \"m_title\": \"Notification Filtering\",\n  \"m_descr\": \"<p>Defines which notifications to send to notification channels (push, e-mail, SMS, ...)</p>\",\n  \"rl_autogenOnDeviceListUpdate\": \"Generate and delete rules on user device list update\",\n  \"h_autogenOnDeviceListUpdate\": \"Automatically add most important notifications for users when new device is granted to the user. Delete rules for devices with revoked access.\",\n  \"rl_normalizeRules\": \"Normalize rules\",\n  \"h_normalizeRules\": \"Aggregate all rules for each user/channel in one block. Can be turned on to let system normalize all rules and then can be turned off again.\",\n  \"unselected\": \"--- please select ---\",\n  \"errors\": \"all error messages\",\n  \"warnings\": \"all warnings\",\n  \"notifications\": \"all notifications\",\n  \"none\": \"nothing\",\n  \"l_recipient_type\": \"Recipient\",\n  \"l_all\": \"All users\",\n  \"l_user\": \"User\",\n  \"h_user\": \"Select the user to notify\",\n  \"l_channel\": \"A specific communication channel\",\n  \"h_channel\": \"Select the notifciation channel to use.\",\n  \"l_logLevel\": \"Global notifications\",\n  \"h_logLevel\": \"Select, which kind of notifications to inform about. Useful to inform admin or installer about problems\",\n  \"l_devices\": \"Devices specific notifications\",\n  \"h_devices\": \"Select devices that will generate notifications.\",\n  \"l_dev_message\" : \"Device specific message\",\n  \"h_dev_message\" : \"Enter a message that should be sent instead of the default notification. Empty to keep the default. Use &lt;devId:property&gt; to refer to a property of a specific device. For example, &lt;DummyDevice_44:metrics:level&gt; or &lt;ZWayVDev_zway5_7-0-38:metrics:title&gt; (see API structure below). If devId is empty, the device on which the event has fired is used. For example, &laquo;&lt;:metrics:title&gt; is &lt;:metrics:level&gt;, while &lt;DummyDevice_44:metrics:title&gt; is &lt;DummyDevice_44:metrics:level&gt;&raquo; will produce &laquo;Light is on, while Door sensor is off&raquo;\",\n  \"l_dev_matchValue\": \"Condition\",\n  \"h_dev_matchValue\": \"Send the message only if the device reports the following state.\",\n  \"l_dev_matchValueOperation\": \"Operator\",\n  \"h_dev_matchValueOperation\": \"Select an operator that should be used to compare the device state with the following value.\",\n  \"l_dev_matchValueOperand\": \"Value\",\n  \"h_dev_matchValueOperand\": \"Enter a numeric value that should be compared to the device state. A notification is send if the comparison return true.\",  \n  \"dev_toggleButton\": \"Toggle Button\",\n  \"dev_switchControl\": \"Switch Control\",\n  \"dev_switchBinary\": \"Switch Binary\",\n  \"dev_switchMultilevel\": \"Switch Multilevel\",\n  \"dev_sensorBinary\": \"Sensor Binary\",\n  \"dev_sensorMultilevel\": \"Sensor Multilevel\",\n  \"dev_sensorMultiline\": \"Sensor Multiline\",\n  \"dev_fan\": \"Fan\",\n  \"dev_doorlock\": \"Doorlock\",\n  \"dev_thermostat\": \"Thermostat\",\n  \"l_ToggleButton\": \"Toggle Button\",\n  \"l_switchControl\": \"Switch Control\",\n  \"l_switchBinary\": \"Switch Binary\",\n  \"l_switchMultilevel\": \"Switch Multilevel\",\n  \"l_sensorBinary\": \"Sensor Binary\",\n  \"l_sensorMultilevel\": \"Sensor Multilevel\",\n  \"l_sensorMultiline\": \"Sensor Multiline\",\n  \"l_fan\": \"Fan\",\n  \"l_doorlock\": \"Doorlock\",\n  \"l_thermostat\": \"Thermostat\"\n}"
  },
  {
    "path": "modules/NotificationFiltering/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"notifications\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"NotificationFiltering\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"rules\": [{\"recipient_type\": \"user\", \"user\": 1, \"logLevel\": \"errors,warnings\"}],\n\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\"normalizeRules\": true\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n                \t\"rules\": {\n                \t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"recipient_type\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\"all\",\n\t\t\t\t\t\t\t\t\"user\",\n\t\t\t\t\t\t\t\t\"channel\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"default\": \"all\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"channel\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"dependencies\": \"recipient_type\",\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:notificationChannels:channelId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"user\": {\n\t\t\t\t\t\t\t\"type\": \"number\",\n\t\t\t\t\t\t\t\"dependencies\": \"recipient_type\",\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"users:id\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"logLevel\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\"errors\",\n\t\t\t\t\t\t\t\t\"warnings\",\n\t\t\t\t\t\t\t\t\"notifications\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"devices\": {\n\t\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\"dev_filter\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\"unselected\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_toggleButton\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_switchControl\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_switchBinary\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_switchMultilevel\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_sensorBinary\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_sensorMultilevel\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_sensorMultiline\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_doorlock\",\n\t\t\t\t\t\t\t\t\t\t\t\"dev_thermostat\"\n\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_toggleButton\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_switchControl\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_matchValueOperation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"pattern\": \"[0-9]*\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_switchBinary\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"on\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"off\"\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_switchMultilevel\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_matchValueOperation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"pattern\": \"[0-9]*\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_sensorBinary\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"on\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"off\"\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_sensorMultilevel\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_matchValueOperation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"pattern\": \"[0-9]*\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_sensorMultiline\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultiline:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_matchValueOperation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"pattern\": \"[0-9]*\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_doorlock\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"all\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"open\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"close\"\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_thermostat\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_filter\",\n\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_thermostat:deviceId\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"enum\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"title\": \"__l_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": \"dev_matchValueOperation\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"pattern\": \"[0-9]*\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"autogenOnDeviceListUpdate\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"normalizeRules\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"rules\": {\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"recipient_type\": {\n\t\t\t\t\t\t\t\"label\": \"__l_recipient_type__\",\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\"__l_all__\",\n\t\t\t\t\t\t\t\t\"__l_user__\",\n\t\t\t\t\t\t\t\t\"__l_channel__\"\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"channel\": {\n\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\"recipient_type\": \"channel\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:notificationChannels:channelNameEx\",\n\t\t\t\t\t\t\t\"label\": \"__l_channel__\",\n\t\t\t\t\t\t\t\"helper\": \"__h_channel__\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"user\": {\n\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\"recipient_type\": \"user\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"optionLabels\": \"users:title\",\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"label\": \"__l_user__\",\n\t\t\t\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\t\t\t\"title\": \"__t_user__\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"logLevel\": {\n\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\"__errors__\",\n\t\t\t\t\t\t\t\t\"__warnings__\",\n\t\t\t\t\t\t\t\t\"__notifications__\"\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\"label\": \"__l_logLevel__\",\n\t\t\t\t\t\t\t\"helper\": \"__h_logLevel__\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"devices\": {\n\t\t\t\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\t\t\t\"helper\": \"__h_devices__\",\n\t\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"dev_filter\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\"__unselected__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_toggleButton__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_switchControl__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_switchBinary__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_switchMultilevel__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_sensorBinary__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_sensorMultilevel__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_sensorMultiline__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_doorlock__\",\n\t\t\t\t\t\t\t\t\t\t\t\"__dev_thermostat__\"\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_toggleButton\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_ToggleButton__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_toggleButton\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_switchControl\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_switchControl__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_switchControl\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≤\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≥\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≠\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperation__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperand__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperand__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_switchBinary\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_switchBinary__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_switchBinary\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"On\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Off\"\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_switchMultilevel\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_switchMultilevel__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_switchMultilevel\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≤\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≥\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≠\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperation__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperand__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperand__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_sensorBinary\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_sensorBinary__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_sensorBinary\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"On\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Off\"\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_sensorMultilevel\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_sensorMultilevel__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_sensorMultilevel\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≤\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≥\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≠\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperation__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperand__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperand__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_sensorMultiline\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_sensorMultiline__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_sensorMultiline\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultiline:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≤\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≥\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≠\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperation__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperand__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperand__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_doorlock\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_doorlock__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_doorlock\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Open\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"Close\"\n\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"dev_thermostat\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_thermostat__\",\n\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_filter\": \"dev_thermostat\"\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\"dev_select\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_thermostat:deviceName\"\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValue\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValue__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≤\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≥\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"≠\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"noneLabel\": \"All\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperation__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperation__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperand\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"dev_matchValueOperation\": [\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"==\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"<=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\">=\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"!=\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_matchValueOperand__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_matchValueOperand__\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\"dev_message\": {\n\t\t\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_dev_message__\",\n\t\t\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_dev_message__\"\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"autogenOnDeviceListUpdate\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_autogenOnDeviceListUpdate__\",\n\t\t\t\t\"helper\": \"__h_autogenOnDeviceListUpdate__\"\n\t\t\t},\n\t\t\t\"normalizeRules\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_normalizeRules__\",\n\t\t\t\t\"helper\": \"__h_normalizeRules__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/NotificationSend/index.js",
    "content": "/*** NotificationSend Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tSend a custom notification\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction NotificationSend(id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tNotificationSend.super_.call(this, id, controller);\n}\n\ninherits(NotificationSend, AutomationModule);\n\n_module = NotificationSend;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nNotificationSend.prototype.init = function(config) {\n\tNotificationSend.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: this.getName() + \"_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"toggleButton\",\n\t\t\tmetrics: {\n\t\t\t\tlevel: \"on\", // it is always on, but usefull to allow bind\n\t\t\t\ticon: \"/ZAutomation/api/v1/load/modulemedia/\" + this.getName() + \"/icon.png\",\n\t\t\t\ttitle: this.getInstanceTitle()\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function(command) {\n\t\t\tif (command !== 'on') return;\n\t\t\t\n\t\t\tif (self.config.recipient_type === \"user\") {\n\t\t\t\tself.controller.notificationUserChannelsSend(self.config.user, self.config.message);\n\t\t\t} else if (self.config.recipient_type === \"channel\") {\n\t\t\t\tself.controller.notificationChannelSend(self.config.channel, self.config.message);\n\t\t\t} else {\n\t\t\t\tself.controller.notificationAllChannelsSend(self.config.message);\n\t\t\t}\n\n\t\t\t// update on ourself to allow catch this event\n\t\t\tself.vDev.set(\"metrics:level\", \"on\");\n\t\t},\n\t\tmoduleId: this.id\n\t});\n};\n\nNotificationSend.prototype.stop = function() {\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tScenes.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------"
  },
  {
    "path": "modules/NotificationSend/lang/en.json",
    "content": "{\n\t\"m_title\":\"Send a notification\",\n\t\"m_descr\":\"Send a notification to all, to a user or to a specific channel\",\n\t\"l_recipient_type\": \"Recipient\",\n\t\"l_all\": \"All users\",\n\t\"l_user\": \"User\",\n\t\"h_user\": \"Select the user to notify\",\n\t\"l_channel\": \"A specific communication channel\",\n\t\"h_channel\": \"Select the notifciation channel to use.\",\n\t\"l_message\" : \"Device specific message\",\n\t\"h_message\" : \"Enter a message that should be sent instead of the default notification. Empty to keep the default.\"\n}"
  },
  {
    "path": "modules/NotificationSend/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"notifications\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"NotificationSend\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"recipient_type\": \"all\",\n\t\t\"message\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"recipient_type\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\n\t\t\t\t\t\"all\",\n\t\t\t\t\t\"user\",\n\t\t\t\t\t\"channel\"\n\t\t\t\t],\n\t\t\t\t\"default\": \"all\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"channel\": {\n\t\t\t\t\"dependencies\": \"recipient_type\",\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:notificationChannels:channelId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"dependencies\": \"recipient_type\",\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"users:id\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"recipient_type\": {\n\t\t\t\t\"label\": \"__l_recipient_type__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [\n\t\t\t\t\t\"__l_all__\",\n\t\t\t\t\t\"__l_user__\",\n\t\t\t\t\t\"__l_channel__\"\n\t\t\t\t]\n\t\t\t},\n\t\t\t\"channel\": {\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"recipient_type\": \"channel\"\n\t\t\t\t},\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:notificationChannels:channelName\",\n\t\t\t\t\"label\": \"__l_channel__\",\n\t\t\t\t\"helper\": \"__h_channel__\"\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"recipient_type\": \"user\"\n\t\t\t\t},\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"optionLabels\": \"users:title\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"label\": \"__l_user__\",\n\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\"title\": \"__t_user__\"\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\t\"label\": \"__l_message__\",\n\t\t\t\t\"helper\": \"__h_message__\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/OpenRemoteHelpers/index.js",
    "content": "/* RaZOR\n *\n * OpenRemote, the Home of the Digital Home.\n * Adopted for Z-Wave.Me Z-Way\n * Copyright 2008-2013, OpenRemote Inc.\n *\n * See the contributors.txt file in the distribution for a\n * full listing of individual contributors.\n *\n * This program is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Affero General Public License as\n * published by the Free Software Foundation, either version 3 of the\n * License, or (at your option) any later version.\n *\n * This program is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU Affero General Public License for more details.\n *\n * You should have received a copy of the GNU Affero General Public License\n * along with this program. If not, see <http://www.gnu.org/licenses/>.\n */\n\n/*** OpenRemoteHelpers Z-Way HA module *******************************************\n\nDescription:\n\tThis module provides HTTP helpers for OpenRemote integration.\n\nAuthor: Pieter E. Zanstra\nConverted into Z-Way HA module: Poltorak Serguei\n\nVersion 1.01.02\t   2015-02-12 (Pieter E. Zanstra)\nAdded a second argument to metrics command, so the user can select other attributes than the\ndefault level-attribute (http://192.168.0.85:8083/OpenRemote/metrics/ZWayVDev_zway_26-0-37/icon)\nWithout the second argument the call returns all device attributes as json.\nClosed the Switch statement with keyword default: to cater for erroneous function calls \n\nVersion 1.01.01\t   2014-09-09 (Yurkin Vitaliy aivs@z-wave.me)\nAdded metrics command to get metrics (http://192.168.0.85:8083/OpenRemote/metrics/ZWayVDev_zway_26-0-37)\n\nVersion 1.01.01\t\t  2014-02-28\nTesting all functions and bugfixing (Yurkin Vitaliy aivs@z-wave.me)\n\nVersion 1.01.00\t   2013-12-11\nConverted into Z-Way HA module\n\nVersion 1.00.009\t  2013-09-27\nUpdated installation instruction in this file\n\nVersion 1.00.008\t  2013-09-25\nAdaptations for RazBerry v1.4 release\n- .SetWithDuration has been abandoned so DimmerSet has been changed again.\n\n\nVersion 1.00.007\t  2013-08-07\n- Added a number of SensorMultilevel variants (Humidity, Luminescence)\n\nVersion 1.00.006\t  2013-07-31\n- Fixed error with DimmerSet function\n\nVersion 1.00.005\t  2013-07-21\n- Fixed error in DimmerLevel\n- Now use .SetWithDuration (0) instead of .Set in DimmerSet function\n- Added function DimmerStatus (author Velouria)\t   \n\nUSAGE\nGeneral parameters used in the calls are:\nN\t\tthe number that designates a Z-Wave device\nI\t\tthe number that refers to an instance (e.g. a channel in a dual binary switch\n\t\t Use 0 for single binary switches. For dual switches use 1 and 2 for \n\t\t channels 1 and 2 respectively)\n${param} This variable is an OpenRemote system parameter that is used e.g. for \n\t\t passing values from a slider.\nS\t\t Scale (e.g. Watt, kWh, etc.)\n\nStatus functions that return the value \"on\" or \"off\" are to be used in OpenRemote with \nsensors of the type:switch. Apply Regular expression: on|off in the http call. \t\t \n\nOpenRemote usage: http://IP:8083/OpenRemote/<Command>/N/I/...\n\nSwitchBinaryOn/N/I\nSwitchBinaryOff/N/I\nSwitchBinaryStatus/N/I\n\tAdd Regular Expression on|off in http call specification \n\tDo use Sensor type:switch with this command\nSwitchMultilevelSet/N/I/${param}\nSwitchMultilevelLevel/N/I\n\tReturns exact dimmer level\nSwitchMultilevelStatus/N/I\n\tAdd Regular Expression on|off in http call specification \n\tDo use Sensor type:switch with this command\nAlarmStatus/N\n\toff means not triggered\nSensorBinaryStatus/N/I/Type\n\toff means not triggered\nThermostatLevel/N\nThermostatSet/N/${param}\nThermostatSetMode/N/Mode\nThermostatModeName/N\n\tDo use RexExp [\\w\\s]{1,} in the http-call to get rid of quotes\nBatteryLevel/N\n\tDo use Sensor type:Range with this command for use in slider\nMeterLevel/N/I/S\n\tUse S=0 for kWh; S=2 for Watts;  \nMeterReset/N/I\nTemperatureLevel/N/I\nHumidityLevel/N/I\nSensorMultilevel/N/I/S\nDoorLock/N\nDoorUnlock/N\n\nTODO:\n- Add helpers for vDevs\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction OpenRemoteHelpers (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tOpenRemoteHelpers.super_.call(this, id, controller);\n}\n\ninherits(OpenRemoteHelpers, AutomationModule);\n\n_module = OpenRemoteHelpers;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nOpenRemoteHelpers.prototype.init = function (config) {\n\tOpenRemoteHelpers.super_.prototype.init.call(this, config);\n\n\t// define global handler for HTTP requests\n\tOpenRemote = function(url, request) {\n\t\tvar params = url.split(\"/\");\n\t\tparams.shift(); // shift empty string before first /\n\t\tvar cmd = params.shift();\n\t\tvar N = params.shift();\n\t\tvar I = params.shift();\n\n\t\tswitch(cmd) {\n\t\t\tcase \"SwitchBinaryOn\":\n\t\t\t\tzway.devices[N].instances[I].SwitchBinary.Set(255);\n\t\t\t\treturn \"on\";\n\t\t\t\t\n\t\t\tcase \"SwitchBinaryOff\":\n\t\t\t\tzway.devices[N].instances[I].SwitchBinary.Set(0);\n\t\t\t\treturn \"off\";\n\t\t\t\t\n\t\t\tcase \"SwitchBinaryStatus\":\n\t\t\t\treturn zway.devices[N].instances[I].SwitchBinary.data.level.value ? \"on\" : \"off\";\n\n\t\t\tcase \"SwitchMultilevelSet\":\n\t\t\t\tvar level = params.shift();\n\t\t\t\tzway.devices[N].instances[I].SwitchMultilevel.Set(level);\n\t\t\t\treturn level;\n\t\t\t\t\n\t\t\tcase \"SwitchMultilevelStatus\":\n\t\t\t\treturn zway.devices[N].instances[I].SwitchMultilevel.data.level.value ? \"on\" : \"off\";\n\t\t\t\t\n\t\t\tcase \"SwitchMultilevelLevel\":\n\t\t\t\treturn zway.devices[N].instances[I].SwitchMultilevel.data.level.value;\n\t\t\t\n\t\t\tcase \"StartLevelChange\":\n\t\t\t   var dir = params.shift();\n\t\t\t   return zway.devices[N].instances[I].SwitchMultilevel.StartLevelChange(dir);\n\n\t\t\tcase \"StopLevelChange\":\n\t\t\t   return zway.devices[N].instances[I].SwitchMultilevel.StopLevelChange();\n\t\t\t\n\t\t\tcase \"AlarmStatus\":\n\t\t\t\t// there are usually no instances for alarms\n\t\t\t\treturn (zway.devices[N].AlarmSensor.data.level.value == 0) ? \"off\" : \"on\" ;\n\t\t\t\n\t\t\tcase \"SensorBinaryStatus\":\n\t\t\t\tvar T = params.shift(); // sensor type\n\t\t\t\treturn (zway.devices[N].instances[I].SensorBinary.data[T].level.value == 0) ? \"off\" : \"on\" ;\n\n\t\t\tcase \"ThermostatLevel\":\n\t\t\t\tvar temp = I; // there are usually no instances for thermostats\n\t\t\t\tvar mode = zway.devices[N].ThermostatMode ? zway.devices[N].ThermostatMode.data.mode.value : null;\n\t\t\t\tif (mode === null) {\n\t\t\t\t\t// no ThemorstatMode CC - pick up first mode\n\t\t\t\t\tfor (var key in zway.devices[N].ThermostatSetPoint.data) {\n\t\t\t\t\t\tvar _modeId = parseInt(key, 10);\n\t\t\t\t\t\tif (!isNaN(_modeId)) {\n\t\t\t\t\t\t\tmode = _modeId;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (mode !== null) {\n\t\t\t\t\treturn zway.devices[N].ThermostatSetPoint.data[mode].setVal.value;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\n\t\t\tcase \"ThermostatSet\":\n\t\t\t\tvar temp = I; // there are usually no instances for thermostats\n\t\t\t\tvar mode = zway.devices[N].ThermostatMode ? zway.devices[N].ThermostatMode.data.mode.value : null;\n\t\t\t\tif (mode === null) {\n\t\t\t\t\t// no ThemorstatMode CC - pick up first mode\n\t\t\t\t\tfor (var key in zway.devices[N].ThermostatSetPoint.data) {\n\t\t\t\t\t\tvar _modeId = parseInt(key, 10);\n\t\t\t\t\t\tif (!isNaN(_modeId)) {\n\t\t\t\t\t\t\tmode = _modeId;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (mode !== null) {\n\t\t\t\t\tzway.devices[N].ThermostatSetPoint.Set(mode, temp);\n\t\t\t\t\treturn temp;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\n\t\t\tcase \"ThermostatSetMode\":\n\t\t\t\tvar mode = I; // there are usually no instances for thermostats\n\t\t\t\tif (! zway.devices[N].ThermostatMode.data[mode]) {\n\t\t\t\t\tfor (var m in zway.devices[N].ThermostatMode.data) {\n\t\t\t\t\t\tif (zway.devices[N].ThermostatMode.data[m] && zway.devices[N].ThermostatMode.data[m].modeName && zway.devices[N].ThermostatMode.data[m].modeName.value.toLowerCase() == mode.toLowerCase()) {\n\t\t\t\t\t\t\tmode = m;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\tzway.devices[N].ThermostatMode.Set(mode);\n\t\t\t\treturn mode;\n\n\t\t\tcase \"ThermostatModeName\":\n\t\t\t\t// there are usually no instances for thermostats\n\t\t\t\tif (zway.devices[N].ThermostatMode) {\n\t\t\t\t\tvar mode = zway.devices[N].ThermostatMode.data.mode.value;\n\t\t\t\t\treturn zway.devices[N].ThermostatMode.data[mode].modeName.value;\n\t\t\t\t} else {\n\t\t\t\t\t// no ThemorstatMode CC - pick up first mode\n\t\t\t\t\tfor (var key in zway.devices[N].ThermostatSetPoint.data) {\n\t\t\t\t\t\tvar _modeId = parseInt(key, 10);\n\t\t\t\t\t\tif (!isNaN(_modeId)) {\n\t\t\t\t\t\t\tvar mode = _modeId;\n\t\t\t\t\t\t\treturn zway.devices[N].ThermostatSetPoint.data[mode].modeName.value\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn \"?\";\n\n\t\t\tcase \"BatteryLevel\":\n\t\t\t\t// Battery is never in instances\n\t\t\t\tzway.devices[N].Battery.Get();\n\t\t\t\treturn zway.devices[N].Battery.data.last.value;\n\t\t\t\n\t\t\tcase \"MeterLevel\":\n\t\t\t\tvar S = params.shift();\n\t\t\t\tzway.devices[N].instances[I].Meter.Get();\n\t\t\t\treturn zway.devices[N].instances[I].Meter.data[S].val.value;\n\t\t\t\n\t\t\tcase \"MeterReset\":\n\t\t\t\tzway.devices[N].instances[I].Meter.Reset();\n\t\t\t\treturn 0; // just to return something\n\t\t\t\n\t\t\tcase \"TemperatureLevel\":\n\t\t\t\tvar S = 1;\n\t\t\t\tzway.devices[N].instances[I].SensorMultilevel.Get();\n\t\t\t\treturn zway.devices[N].instances[I].SensorMultilevel.data[S].val.value;\n\t\t\t\t\n\t\t\tcase \"HumidityLevel\":\n\t\t\t\tvar S = 5;\n\t\t\t\tzway.devices[N].instances[I].SensorMultilevel.Get();\n\t\t\t\treturn zway.devices[N].instances[I].SensorMultilevel.data[S].val.value;\n\n\t\t\tcase \"SensorMultilevel\":\n\t\t\t\tvar S = params.shift();\n\t\t\t\tzway.devices[N].instances[I].SensorMultilevel.Get();\n\t\t\t\treturn zway.devices[N].instances[I].SensorMultilevel.data[S].val.value;\n\n\t\t\tcase \"DoorLock\":\n\t\t\t\t// there are usually no instances for door locks\n\t\t\t\tzway.devices[N].DoorLock.Set(255);\n\t\t\t\treturn \"on\";\n\n\t\t\tcase \"DoorUnLock\":\n\t\t\t\t// there are usually no instances for door locks\n\t\t\t\tzway.devices[N].DoorLock.Set(0);\n\t\t\t\treturn \"off\";\n\n\t\t\tcase \"DoorStatus\":\n\t\t\t\t// there are usually no instances for door locks\n\t\t\t\treturn zway.devices[N].DoorLock.data.level.value ? \"on\" : \"off\";\n\n\t\t\tcase \"DeviceName\":\n\t\t\t\treturn zway.devices[N].instances[I].NodeNaming.data.nodename.value;\n\n\t\t\tcase \"DeviceLocation\":\n\t\t\t   \treturn zway.devices[N].instances[I].NodeNaming.data.location.value;\n\n\t\t\tcase \"metrics\":\n\t\t\t\t// used HA API for all device to get metrics\n\t\t\t\tif (I !== \"\") {\n\t\t\t\t  attrib = \"metrics:\" + I;\n\t\t\t\t  }\n\t\t\t\telse {\n\t\t\t\t   attrib = \"metrics\";\n\t\t\t\t  }\n\t\t\t   return this.controller.devices.get(N).get(attrib);\n\n// Your \"case\" statements may go after this line, but before keyword default:  !\n\t\t\t\t\n\t\t\tdefault:\n\t\t\t\t return \"Error: Function \" + cmd  + \" is not defined in OpenRemoteHelpers\";\n\t\t}\n\t};\n\tws.allowExternalAccess(\"OpenRemote\", this.controller.auth.ROLE.USER); // login required\n};\n\nOpenRemoteHelpers.prototype.stop = function () {\n\tOpenRemoteHelpers.super_.prototype.stop.call(this);\n\t\n\tws.revokeExternalAccess(\"OpenRemote\");\n\tOpenRemote = null;\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n\n"
  },
  {
    "path": "modules/OpenRemoteHelpers/lang/de.json",
    "content": "{\n\t\"m_title\":\"OpenRemote Assistent\",\n\t\"m_descr\":\"„Open Remote” ist ein sehr schönes generisches Benutzeroberflächensystem für Smart Home. Weitere Informationen dazu finden Sie auf http://www.openremote.org/. Diese App liefert die Daten Ihres Smart Home in einer Weise, die durch „Open Remote“ inkludiert werden. Weitere Informationen zur Anwendung von „Open Remote“ entnehmen Sie bitte der Open Remote Webseite.<br><br>Einstellungen: Keine weiteren Einstellungen<br>Usage: The OpenRemote UI will show the devices included. \"\n}"
  },
  {
    "path": "modules/OpenRemoteHelpers/lang/en.json",
    "content": "{\n\t\"m_title\":\"OpenRemote Helper\",\n\t\"m_descr\":\"Open remote is a very nice generic User Interface System for Smart Homes. You find more information about this service on http://www.openremote.org/. This app provides the data of your smart home into a way to be included by openremote. For more information how to use open remote please refer to the open remote website.<br><br>Settings: No further settings.<br>Usage: The OpenRemote UI will show the devices included.\"\n}\n"
  },
  {
    "path": "modules/OpenRemoteHelpers/lang/ru.json",
    "content": "{\n\t\"m_title\":\"OpenRemote функции помощники\",\n\t\"m_descr\":\"Набор функций помощников для сервера OpenRemote.\"\n}"
  },
  {
    "path": "modules/OpenRemoteHelpers/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"support_external_ui\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"OpenRemoteHelpers\",\n\t\"version\": \"1.01.02\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\"\n\t},\n\t\"schema\": {\n\t},\n\t\"options\": {\n\t}\n}\n"
  },
  {
    "path": "modules/OpenWeather/index.js",
    "content": "/*** OpenWeather Extended Z-Way HA module *******************************************\n\nVersion: 1.2.0\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>, Niels Roche <nir@z-wave.me>, Michael Pruefer\nDescription:\n\tThis module creates weather widget that shows you \n\tin addition to the temperature also humidity, pressure etc.\n\tYou can also add a daylight widget that delivers on/off based on sunrise/sunset\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction OpenWeather (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tOpenWeather.super_.call(this, id, controller);\n}\n\ninherits(OpenWeather, AutomationModule);\n\n_module = OpenWeather;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nOpenWeather.prototype.init = function (config) {\n\tOpenWeather.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.vDevWeather = self.controller.devices.create({\n\t\tdeviceId: \"OpenWeather_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"sensorMultiline\",\n\t\t\tmetrics: {\n\t\t\t\tmultilineType: 'openWeather',\n\t\t\t\tprobeTitle: 'Temperature'\n\t\t\t}\n\t\t},\n\t\toverlay: {\n\t\t\tmetrics: {\n\t\t\t\tscaleTitle: this.config.units === \"celsius\" ? '°C' : '°F',\n\t\t\t\ttitle: this.config.city\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\tif (config.show_daylight) {\n\t\tthis.vDevDayLight = self.controller.devices.create({\n\t\t\t deviceId: \"OpenWeatherDaylight_\" + this.id,\n\t\t\t defaults: {\n\t\t\t\t deviceType: \"sensorBinary\",\n\t\t\t\t metrics: {\n\t\t\t\t\t probeTitle: 'daylight'\n\t\t\t\t }\n\t\t\t },\n\t\t\t overlay: {\n\t\t\t\t metrics: {\n\t\t\t\t\t title: this.config.city + \" Daylight\"\n\t\t\t\t }\n\t\t\t },\n\t\t\t moduleId: this.id\n\t\t });\n\t}\n\n\tif (config.show_temp_hum) {\n\t\tthis.vDevTemp = self.controller.devices.create({\n\t\t\t deviceId: \"OpenWeatherTemp\" + this.id,\n\t\t\t defaults: {\n\t\t\t\t deviceType: \"sensorMultilevel\",\n\t\t\t\t metrics: {\n\t\t\t\t\t probeTitle: 'Temperature'\n\t\t\t\t }\n\t\t\t },\n\t\t\t overlay: {\n\t\t\t\t metrics: {\n\t\t\t\t\t title: this.config.city + \" Temperature\",\n\t\t\t\t\t scaleTitle: this.config.units === \"celsius\" ? '°C' : '°F'\n\t\t\t\t }\n\t\t\t },\n\t\t\t moduleId: this.id\n\t\t });\n\t\tthis.vDevHum = self.controller.devices.create({\n\t\t\t deviceId: \"OpenWeatherHum\" + this.id,\n\t\t\t defaults: {\n\t\t\t\t deviceType: \"sensorMultilevel\",\n\t\t\t\t metrics: {\n\t\t\t\t\t probeTitle: 'Humidity'\n\t\t\t\t }\n\t\t\t },\n\t\t\t overlay: {\n\t\t\t\t metrics: {\n\t\t\t\t\t title: this.config.city + \" Humidity\",\n\t\t\t\t\t scaleTitle: \"%\"\n\t\t\t\t }\n\t\t\t },\n\t\t\t moduleId: this.id\n\t\t });\n\t}\n\n\tif (config.show_wind) {\n\t\tthis.vDevWindSpeed = self.controller.devices.create({\n\t\t\t deviceId: \"OpenWeatherWindspeed\" + this.id,\n\t\t\t defaults: {\n\t\t\t\t deviceType: \"sensorMultilevel\",\n\t\t\t\t metrics: {\n\t\t\t\t\t probeTitle: 'WindSpeed'\n\t\t\t\t }\n\t\t\t },\n\t\t\t overlay: {\n\t\t\t\t metrics: {\n\t\t\t\t\t title: this.config.city + \" wind speed\",\n\t\t\t\t\t scaleTitle: this.config.units_wind \n\t\t\t\t }\n\t\t\t },\n\t\t\t moduleId: this.id\n\t\t });\n\t\tthis.vDevWindGust = self.controller.devices.create({\n\t\t\t deviceId: \"OpenWeatherWindGust\" + this.id,\n\t\t\t defaults: {\n\t\t\t\t deviceType: \"sensorMultilevel\",\n\t\t\t\t metrics: {\n\t\t\t\t\t probeTitle: 'WindGust'\n\t\t\t\t }\n\t\t\t },\n\t\t\t overlay: {\n\t\t\t\t metrics: {\n\t\t\t\t\t title: this.config.city + \" wind gust\",\n\t\t\t\t\t scaleTitle: this.config.units_wind\n\t\t\t\t }\n\t\t\t },\n\t\t\t moduleId: this.id\n\t\t });\n\t\tthis.vDevWindDegree = self.controller.devices.create({\n\t\t\t deviceId: \"OpenWeatherWindDegree\" + this.id,\n\t\t\t defaults: {\n\t\t\t\t deviceType: \"sensorMultilevel\",\n\t\t\t\t metrics: {\n\t\t\t\t\t probeTitle: 'WindDegree'\n\t\t\t\t }\n\t\t\t },\n\t\t\t overlay: {\n\t\t\t\t metrics: {\n\t\t\t\t\t title: this.config.city + \" wind degree\",\n\t\t\t\t\t scaleTitle: \"°\"\n\t\t\t\t }\n\t\t\t },\n\t\t\t moduleId: this.id\n\t\t });\n\t}\n\t\n\trefresh_rate = self.config.refresh_rate *60 *1000; \n\n\tthis.timer = setInterval(function() {\n\t\tself.fetchExtendedWeather(self);\n\t}, refresh_rate);\n\tself.fetchExtendedWeather(self);\n};\n\nOpenWeather.prototype.stop = function () {\n\tOpenWeather.super_.prototype.stop.call(this);\n\n\tif (this.timer)\n\t\tclearInterval(this.timer);\n\t\t\n\tif (this.vDevWeather) {\n\t\tthis.controller.devices.remove(this.vDevWeather.id);\n\t\tthis.vDevWeather = null;\n\t}\n\t\n\tif (this.vDevDayLight) {\n\t\t this.controller.devices.remove(this.vDevDayLight.id);\n\t\t this.vDevDayLight = null;\n\t }\n\n\tif (this.vDevTemp) {\n\t\t this.controller.devices.remove(this.vDevTemp.id);\n\t\t this.vDevTemp = null;\n\t }\n\tif (this.vDevHum) {\n\t\t this.controller.devices.remove(this.vDevHum.id);\n\t\t this.vDevHum = null;\n\t }\n\tif (this.vDevWindSpeed) {\n\t\t this.controller.devices.remove(this.vDevWindSpeed.id);\n\t\t this.vDevWindSpeed = null;\n\t }\n\tif (this.vDevWindGust) {\n\t\t this.controller.devices.remove(this.vDevWindGust.id);\n\t\t this.vDevWindGust = null;\n\t }\n\tif (this.vDevWindDegree) {\n\t\t this.controller.devices.remove(this.vDevWindDegree.id);\n\t\t this.vDevWindDegree = null;\n\t }\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nOpenWeather.prototype.fetchExtendedWeather = function(instance) {\n\tvar self = instance,\n\t\tlangFile = self.loadModuleLang(),\n\t\tlang = self.controller.defaultLang;\n\t\n\thttp.request({\n\t\turl: \"https://api.openweathermap.org/data/2.5/weather?q=\" + encodeURIComponent(self.config.city) + \",\" + encodeURIComponent(self.config.country) +\"&lang=\" + lang + \"&appid=\" + encodeURIComponent(self.config.api),\n\t\tasync: true,\n\t\tsuccess: function(res) {\n\t\t\ttry {\n\t\t\t\tvar main = res.data.main,\n\t\t\t\t\tweather = res.data.weather,\n\t\t\t\t\twind = res.data.wind,\n\t\t\t\t\twindspeed = wind.speed,\n\t\t\t\t\twindgust = wind.gust,\n\t\t\t\t\twinddeg = wind.deg,\n\t\t\t\t\tclouds = res.data.clouds,\n\t\t\t\t\tcountry = res.data.sys.country,\n\t\t\t\t\tweatherData = {'main': main,'weather': weather, 'wind': wind, 'clouds': clouds},\n\t\t\t\t\ttemp = Math.round((self.config.units === \"celsius\" ? main.temp - 273.15 : main.temp * 1.8 - 459.67) * 10) / 10,\n\t\t\t\t\thum = main.humidity,\n\t\t\t\t\ticon = \"https://openweathermap.org/img/w/\" + weather[0].icon + \".png\",\n\t\t\t\t\tflag = \"https://openweathermap.org/images/flags/\" + country.toLowerCase() + \".png\",\n\t\t\t\t\tsunrise = Math.round(res.data.sys.sunrise) * 1000,\n\t\t\t\t\ticon_sunrise = \"https://openweathermap.org/img/w/01d.png\",\n\t\t\t\t\tsunset = Math.round(res.data.sys.sunset) * 1000,\n\t\t\t\t\ticon_sunset = \"https://openweathermap.org/img/w/01n.png\";\n\t\t\t\t\n\t\t\t\tif (typeof windgust === 'undefined') windgust = windspeed;\n\t\t\t\tif (self.config.units_wind === \"km/h\") {\n\t\t\t\t\twindspeed = Math.round(windspeed * 3.6);\n\t\t\t\t\twindgust = Math.round(windgust * 3.6);\n\t\t\t\t} else if (self.config.units_wind === \"mph\")  {\n\t\t\t\t\twindspeed = Math.round(windspeed * 2.237);\n\t\t\t\t\twindgust = Math.round(windgust * 2.237);\n\t\t\t\t}\t\n\n\t\t\t\tif (self.vDevDayLight) {\n\t\t\t\t\tvar now = Date.now();\n\t\t\t\t\t\n\t\t\t\t\tif (now > sunrise && now < sunset) {\n\t\t\t\t\t\tself.vDevDayLight.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\tself.vDevDayLight.set(\"metrics:icon\", icon_sunrise);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.vDevDayLight.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\tself.vDevDayLight.set(\"metrics:icon\", icon_sunset);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (self.vDevTemp) {\n\t\t\t\t\tself.vDevTemp.set(\"metrics:level\", temp);\n\t\t\t\t\tself.vDevTemp.set(\"metrics:icon\", \"temperature\");\n\t\t\t\t}\n\t\t\t\tif (self.vDevHum) {\n\t\t\t\t\tself.vDevHum.set(\"metrics:level\", hum);\n\t\t\t\t\tself.vDevHum.set(\"metrics:icon\", \"humidity\");\n\t\t\t\t}\n\t\t\t\tif (self.vDevWindSpeed) {\n\t\t\t\t\tself.vDevWindSpeed.set(\"metrics:level\", windspeed);\n\t\t\t\t\tself.vDevWindSpeed.set(\"metrics:icon\", icon);\n\t\t\t\t }\n\t\t\t\tif (self.vDevWindGust) {\n\t\t\t\t\tself.vDevWindGust.set(\"metrics:level\", windgust);\n\t\t\t\t\tself.vDevWindGust.set(\"metrics:icon\", icon);\n\t\t\t\t }\n\t\t\t\tif (self.vDevWindDegree) {\n\t\t\t\t\tself.vDevWindDegree.set(\"metrics:level\", winddeg);\n\t\t\t\t\tself.vDevWindDegree.set(\"metrics:icon\", icon);\n\t\t\t\t }\n\n\t\t\t\tself.vDevWeather.set(\"metrics:zwaveOpenWeather\", weatherData);\n\t\t\t\tself.vDevWeather.set(\"metrics:level\", temp);\n\t\t\t\tself.vDevWeather.set(\"metrics:icon\", icon);\n\t\t\t\tself.vDevWeather.set(\"metrics:country\", country);\n\t\t\t\tself.vDevWeather.set(\"metrics:flag\", flag);\n\t\t\t} catch (e) {\n\t\t\t\tself.addNotification(\"error\", langFile.err_parse, \"module\");\n\t\t\t}\n\t\t},\n\t\terror: function() {\n\t\t\tself.addNotification(\"error\", langFile.err_fetch, \"module\");\n\t\t}\n\t});\n};"
  },
  {
    "path": "modules/OpenWeather/lang/de.json",
    "content": "{\n\t\"m_title\":\"Lokales Wetter\",\n\t\"m_descr\": \"Die App zur Wettervorhersage erstellt ein Element, welches die vom Internetservice https://openweathermap.org/. aufbereiteten lokalen Wetterdaten anzeigt. Das Element zeigt die lokal vorherrschende Temperatur an, aber durch Klick auf das angelegte Element werden Luftfeuchtigkeit, Windgeschwindigkeit und Luftdruck gleicherma�en aufgezeigt.<br><br>Einstellungen:<br><ul><li>W�hlen Sie Ihr Land und Ihre Stadt. Sie haben die auch M�glichkeit St�dtenamen mit https://openweathermap.org/ abzugleichen.</li><li>Sie k�nnen sich die Temperatur sowohl in Celsius als auch in Fahrenheit anzeigen lassen.</li></ul>\",\n\t\"l_units\": \"Einheiten\",\n\t\"l_country\": \"Land\",\n\t\"p_country\": \"Deutschland\",\n\t\"l_city\": \"Stadt\",\n\t\"p_city\": \"Berlin\",\n\t\"temp\":\"Temperatur\",\n\t\"err_parse\":\"Fehler beim Einlesen der Wetterinformationen.\",\n\t\"err_fetch\":\"Fehler beim Aktualisieren der Wetterinformationen.\",\n\t\"h_api\":\"Gehen Sie auf die URL: https://openweathermap.org/appid#get und folgen Sie den Anweisungen, um ein OpenWeather-Token zu erstellen.\",\n\t\"rl_show_daylight\":\"Tageslichtsensor anzeigen\",\n\t\"h_show_daylight\":\"Erzeugt einen binären Sensor, der sich je nach Sonnenauf- oder Sonnenuntergangszeit ein- (Tageslicht ein) oder ausschaltet (Tageslicht aus).\",\n\t\"rl_show_temp_hum\": \"Temperatur- und Feuchtigkeitssensor anzeigen\",\n\t\"h_show_temp_hum\": \"Erzeugt Temperatur- und Feuchtigkeitssensor.\",\n\t\"rl_show_wind\": \"Wind Sensoren anzeigen\",\n\t\"h_show_wind\": \"Erzeugt Wind Geschwindigkeits- und Richtungssensor.\",\n\t\"l_refresh_rate\": \"Refresh Rate (Minuten):\",\n\t\"h_refresh_rate\": \"Bitte beachten Sie die max. Anzahl der Abfragen Ihres Accounts!\"\n\n}\n"
  },
  {
    "path": "modules/OpenWeather/lang/en.json",
    "content": "{\n\t\"m_title\":\"Local Weather\",\n\t\"m_descr\": \"The Local Weather app creates an element showing the local weather data as provided by the Internet service https://openweathermap.org/. The element is showing the local temperature but clicking on the created element will reveal humidity, wind speed, air pressure as well.<br><br>Setting:<br><ul><li>Pick your country and your city. You may want to check city names with https://openweathermap.org/</li><li<Select if you want to see your temperature in Celsius or Fahrenheit.</li></ul>\",\n\t\"l_units\": \"Units\",\n\t\"l_country\": \"Country\",\n\t\"p_country\": \"England\",\n\t\"l_city\": \"City\",\n\t\"p_city\": \"London\",\n\t\"temp\":\"Temperature\",\n\t\"err_parse\":\"Can not parse weather information.\",\n\t\"err_fetch\":\"Can not fetch weather information.\",\n\t\"h_api\":\"Go to the URL: https://openweathermap.org/appid#get and follow the instructions to create an OpenWeather token.\",\n\t\"rl_show_daylight\": \"Show daylight sensor\",\n\t\"h_show_daylight\": \"Generates a binary sensor that registers on (daylight on) or off (daylight off) based on the sunrise or sunset time.\",\n\t\"rl_show_temp_hum\": \"Show temperature and humidity sensors\",\n\t\"h_show_temp_hum\": \"Generates temperature and humidity sensor.\",\n\t\"rl_show_wind\": \"Show wind sensors\",\n\t\"h_show_wind\": \"Generates a wind speed and direction sensor.\",\n\t\"l_refresh_rate\": \"Refresh rate (minutes):\",\n\t\"h_refresh_rate\": \"Please remember about maximum allowed requests for your OpenWeatherMap account!\"\n}"
  },
  {
    "path": "modules/OpenWeather/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Погодный информер\",\n\t\"m_descr\": \"Погодный информер предоставляет данные с https://openweathermap.org/.\",\n\t\"l_units\": \"Единица измерения\",\n\t\"l_country\": \"Страна\",\n\t\"p_country\": \"Россия\",\n\t\"l_city\": \"Город\",\n\t\"p_city\": \"Москва\",\n\t\"temp\":\"Температура\",\n\t\"err_parse\":\"Не возможно распарсить информацию о погоде.\",\n\t\"err_fetch\":\"Не возможно извлечь информацию о погоде.\",\n\t\"h_api\":\"Go to the URL: https://openweathermap.org/appid#get and follow the instructions to create an OpenWeather token.\",\n\t\"rl_show_daylight\": \"Show daylight sensor\",\n\t\"h_show_daylight\": \"Generates a binary sensor that registers on (daylight on) or off (daylight off) based on the sunrise or sunset time.\",\n\t\"rl_show_temp_hum\": \"Show temperature and humidity sensors\",\n\t\"h_show_temp_hum\": \"Generates temperature and humidity sensor.\",\n\t\"rl_show_wind\": \"Show wind sensors\",\n\t\"h_show_wind\": \"Generates a wind speed and direction sensor.\",\n\t\"l_refresh_rate\": \"Refresh rate (minutes):\",\n\t\"h_refresh_rate\": \"Please remember about maximum allowed requests for your OpenWeatherMap account!\"\n\n}"
  },
  {
    "path": "modules/OpenWeather/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"support_external_dev\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me/z-way\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"OpenWeather\",\n\t\"version\": \"1.3.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"units\": \"celsius\",\n\t\t\"units_wind\": \"km/h\",\n\t\t\"refresh_rate\": \"20\",\n\t\t\"city\": \"\",\n\t\t\"country\": \"\",\n\t\t\"show_daylight\": false,\n\t\t\"show_temp_hum\": false,\n\t\t\"show_wind\": false\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"city\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"country\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"units\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"celsius\", \"fahrenheit\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"units_wind\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"km/h\",\"m/s\",\"mph\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t \"api\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"refresh_rate\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"05\",\"10\",\"20\",\"30\",\"40\",\"50\",\"60\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"show_daylight\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"show_temp_hum\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"show_wind\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"required\": false\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"city\": {\n\t\t\t\t\"label\": \"__l_city__\",\n\t\t\"placeholder\": \"__p_city__\"\n\t\t\t},\n\t\t\t\"country\": {\n\t\t\t\t\"label\": \"__l_country__\",\n\t\t\"placeholder\": \"__p_country__\"\n\t\t\t},\n\t\t\t\"units\": {\n\t\t\t\t\"label\": \"__l_units__\",\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"units_wind\": {\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"api\": {\n\t\t\t\t\"label\": \"API-Key\",\n\t\t\t\t\"placeholder\": \"API-Key\",\n\t\t\t\t\"helper\":\"__h_api__\"\n\t\t\t},\n\t\t\t\"refresh_rate\": {\n\t\t\t\t\"label\": \"__l_refresh_rate__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"helper\": \"__h_refresh_rate__\"\n\t\t\t},\n\t\t\t\"show_daylight\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\":\"__rl_show_daylight__\",\n\t\t\t\t\"helper\":\"__h_show_daylight__\"\n\t\t\t},\n\t\t\t\"show_temp_hum\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\":\"__rl_show_temp_hum__\",\n\t\t\t\t\"helper\":\"__h_show_temp_hum__\"\n\t\t\t},\n\t\t\t\"show_wind\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\":\"__rl_show_wind__\",\n\t\t\t\t\"helper\":\"__h_show_wind__\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/OpenWeather/patchnotes.txt",
    "content": "v1.2.0\n- add checkbox to add an optional daylight widget based on sunrise/sunset information"
  },
  {
    "path": "modules/PhilioHW/index.js",
    "content": "/*** PhilioHW Z-Way HA module *******************************************\n\nVersion: 1.0.2\n(c) Z-Wave.Me, 2016\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tSupport for Philio hardware\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction PhilioHW (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tPhilioHW.super_.call(this, id, controller);\n}\n\ninherits(PhilioHW, AutomationModule);\n\n_module = PhilioHW;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nPhilioHW.prototype.init = function (config) {\n\tPhilioHW.super_.prototype.init.call(this, config);\n\n\tthis.ZWAY_DATA_CHANGE_TYPE = {   \n\t\t\"Updated\": 0x01,\t   // Value updated or child created\n\t\t\"Invalidated\": 0x02,   // Value invalidated\t\t\t \n\t\t\"Deleted\": 0x03,\t   // Data holder deleted - callback is called last time before being deleted\n\t\t\"ChildCreated\": 0x04,  // New direct child node created\t\t\t\t\t\t\t\t\t\t  \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t \n\t\t// ORed flags\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\"PhantomUpdate\": 0x40, // Data holder updated with same value (only updateTime changed)\t\t  \n\t\t\"ChildEvent\": 0x80\t // Event from child node\t\t\t\t\t\t\t\t\t\t\t\t  \n\t};\n\n\tvar self = this;\n\n\tthis.bindings = [];\n\n\tthis.zwayReg = function (zwayName) {\n\t\tvar zway = global.ZWave && global.ZWave[zwayName].zway;\n\t\t\n\t\tif (!zway) {\n\t\t\treturn;\n\t\t}\n\t   \n\t\tif (!zway.ZMEPHISetLED) {\n\t\t\treturn;\n\t\t}\n\n\t\tself.zwayName = zwayName;\n\t\tself.bindings[zwayName] = [];\n\n\t\tif (zway.controller.data.philiohw) {\n\t\t\tself.registerButtons(zwayName);\n\t\t} else {\n\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"\", function() {\n\t\t\t\tif (zway.controller.data.philiohw) {\n\t\t\t\t\tself.controller.emit(\"ZWave.dataUnbind\", self.bindings[zwayName]);\n\t\t\t\t\tself.registerButtons(zwayName);\n\t\t\t\t}\n\t\t\t}, \"\");\n\t\t\tzway.ZMEPHIGetButton(1);\n\t\t}\n\t};\n\t\n\tthis.zwayUnreg = function(zwayName) {\n\t\tself.controller.devices.remove(\"PhilioHW_\" + self.id + \"_\" + zwayName + \"_Tamper\");\n\t\tif (!self.config.no_battery) {\n\t\t\tself.controller.devices.remove(\"PhilioHW_\" + self.id + \"_\" + zwayName + \"_PowerFailure\");\n\t\t\tself.controller.devices.remove(\"PhilioHW_\" + self.id + \"_\" + zwayName + \"_BatteryLevel\");\n\t\t}\n\n\t\t// detach handlers\n\t\tif (self.bindings[zwayName]) {\n\t\t\tself.controller.emit(\"ZWave.dataUnbind\", self.bindings[zwayName]);\n\t\t}\n\t\tself.bindings[zwayName] = null;\n\t};\n\t\n\tthis.controller.on(\"ZWave.register\", this.zwayReg);\n\tthis.controller.on(\"ZWave.unregister\", this.zwayUnreg);\n\n\t// walk through existing ZWave\n\tif (global.ZWave) {\n\t\tfor (var name in global.ZWave) {\n\t\t\tthis.zwayReg(name);\n\t\t}\n\t}\n\t\n\tthis.WPS_OFF = 0;\n\tthis.WPS_REGISTRAR = 1;\n\tthis.WPS_ENROLLEE = 2;\n\tthis.WPS = this.WPS_OFF; // for LED indicator of WPS\n\n\tthis.amINervous = false;\n\t// export function to show LED status with nervous blinks\n\tif (!PhilioHW.nervous) {\n\t\tPhilioHW.nervous = self.nervous;\n\t}\n}\n\nPhilioHW.prototype.stop = function () {\n\tvar self = this;\n\t// unsign event handlers\n\tthis.controller.off(\"ZWave.register\", this.zwayReg);\n\tthis.controller.off(\"ZWave.unregister\", this.zwayUnreg);\n\n\t// detach handlers\n\tfor (var name in this.bindings) {\n\t\tthis.controller.emit(\"ZWave.dataUnbind\", this.bindings[name]);\n\t}\n\t\n\tthis.bindings = [];\n\t\n\tif (PhilioHW.nervous == self.nervous) {\n\t\tPhilioHW.nervous = undefined;\n\t}\n\n\tPhilioHW.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nPhilioHW.prototype.nervous = function(amINervous) {\n\tthis.amINervous = amINervous;\n\tthis.roundLED();\n};\n\nPhilioHW.prototype.roundLED = function() {\n\tvar zwayName = this.zwayName;\n\t\n\tif (this.WPS === this.WPS_REGISTRAR) {\n\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x04); // LED steady On\n\t} else if (this.WPS === this.WPS_ENROLLEE) {\n\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x08); // Fast blink\n\t} else if (!this.config.no_battery && global.ZWave[zwayName].zway.controller.data.philiohw.powerFail.value) {\n\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x02); // LED off to save battery\n\t} else if (global.ZWave[zwayName].zway.controller.data.philiohw.tamper.state.value === 0) {\n\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x10); // Flashing LED\n\t} else if (this.amINervous) {\n\t\t// vice versa to idle (tamper.state = 2)\n\t\tif (!this.config.breath) {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x20); // Breathing LED\n\t\t} else {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x02); // LED off\n\t\t}\n\t} else if (global.ZWave[zwayName].zway.controller.data.philiohw.tamper.state.value === 2) {\n\t\tif (this.config.breath) {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x20); // Breathing LED\n\t\t} else {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x11, 0x02); // LED off\n\t\t}\n\t}\n}\n\nPhilioHW.prototype.registerButtons = function(zwayName) {\n\tvar self = this,\n\t\tlangFile = this.loadModuleLang();\n\n\t// get current power state and buttons states\n\tif (!self.config.no_battery) {\n\t\tglobal.ZWave[zwayName].zway.ZMEPHIGetPower();\n\t} else {\n\t\tglobal.ZWave[zwayName].zway.controller.data.philiohw.powerFail.value = false;\n\t\tglobal.ZWave[zwayName].zway.controller.data.philiohw.batteryFail.value = false;\n\t\tglobal.ZWave[zwayName].zway.controller.data.philiohw.batteryLevel.value = 0;\n\t}\n\tglobal.ZWave[zwayName].zway.ZMEPHIGetButton(0);\n\tglobal.ZWave[zwayName].zway.ZMEPHIGetButton(1);\n\tglobal.ZWave[zwayName].zway.ZMEPHIGetButton(2);\n\n\t// Create vDev\n\t\n\tvar tamperDev = this.controller.devices.create({\n\t\tdeviceId: \"PhilioHW_\" + this.id + \"_\" + zwayName + \"_Tamper\",\n\t\tdefaults: {\n\t\t\tdeviceType: \"sensorBinary\",\n\t\t\tprobeType: \"alarm_burglar\",\n\t\t\tmetrics: {\n\t\t\t\ticon: \"alarm\",\n\t\t\t\tlevel: global.ZWave[zwayName].zway.controller.data.philiohw.tamper.state.value !== 2 ? \"on\" : \"off\",\n\t\t\t\ttitle: 'Controller Tamper'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function(command, args) {},\n\t\tmoduleId: this.id\n\t});\n\n\tif (!self.config.no_battery) {\n\t\tvar powerFailureDev = this.controller.devices.create({\n\t\t\tdeviceId: \"PhilioHW_\" + this.id + \"_\" + zwayName + \"_PowerFailure\",\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"sensorBinary\",\n\t\t\t\tprobeType: \"alarm_power\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"alarm\",\n\t\t\t\t\tlevel: global.ZWave[zwayName].zway.controller.data.philiohw.powerFail.value ? \"on\" : \"off\",\n\t\t\t\t\ttitle: 'Controller Power Failure'\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {},\n\t\t\thandler: function(command, args) {},\n\t\t\tmoduleId: this.id\n\t\t});\n\n\t\tvar batteryLevelDev = this.controller.devices.create({\n\t\t\tdeviceId: \"PhilioHW_\" + this.id + \"_\" + zwayName + \"_BatteryLevel\",\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: \"battery\",\n\t\t\t\tmetrics: {\n\t\t\t\t\tscaleTitle: '%',\n\t\t\t\t\ticon: \"battery\",\n\t\t\t\t\tlevel: (global.ZWave[zwayName].zway.controller.data.philiohw.batteryLevel.value || 0) * 10,\n\t\t\t\t\ttitle: 'Controller Backup Battery'\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {},\n\t\t\thandler: function(command, args) {},\n\t\t\tmoduleId: this.id\n\t\t});\n\t}\n\t\t\n\t// Trap events\n\t\n\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"philiohw.tamper.state\", function(type) {\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Updated\"]) {\n\t\t\tswitch (this.value) {\n\t\t\t\tcase 0:\n\t\t\t\t\tself.addNotification(\"critical\", langFile.tamper_triggered, \"controller\");\n\t\t\t\t\ttamperDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:\n\t\t\t\t\tself.addNotification(\"notification\", langFile.tamper_idle, \"controller\");\n\t\t\t\t\ttamperDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tself.roundLED();\n\t}, \"\");\n\n\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"philiohw.funcA.state\", function(type) {\n\t\tswitch (this.value) {\n\t\t\tcase 3: // click\n\t\t\t\tself.WPS = self.WPS_REGISTRAR;\n\t\t\t\tself.roundLED();\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.WPS = self.WPS_OFF;\n\t\t\t\t\tself.roundLED();\n\t\t\t\t}, 30*1000);\n\t\t\t\tsystem(\"/lib/wifi-helper.sh WPSRegistrar\");\n\t\t\t\tbreak;\n\t\t\tcase 2: // hold\n\t\t\t\tself.WPS = self.WPS_ENROLLEE;\n\t\t\t\tself.roundLED();\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.WPS = self.WPS_OFF;\n\t\t\t\t\tself.roundLED();\n\t\t\t\t}, 30*1000);\n\t\t\t\tsystem(\"/lib/wifi-helper.sh WPS\");\n\t\t\t\tbreak;\n\t\t}\n\t}, \"\");\n\n\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"philiohw.funcB.state\", function(type) {\n\t\tswitch (this.value) {\n\t\t\tcase 3:\n\t\t\t\tif (global.ZWave[zwayName].zway.controller.data.controllerState.value === 0) {\n\t\t\t\t\tglobal.ZWave[zwayName].zway.AddNodeToNetwork(true, true);\n\t\t\t\t} else if (global.ZWave[zwayName].zway.controller.data.controllerState.value === 1) {\n\t\t\t\t\tglobal.ZWave[zwayName].zway.AddNodeToNetwork(false, false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif (global.ZWave[zwayName].zway.controller.data.controllerState.value === 0) {\n\t\t\t\t\tglobal.ZWave[zwayName].zway.RemoveNodeFromNetwork(true, true);\n\t\t\t\t} else if (global.ZWave[zwayName].zway.controller.data.controllerState.value === 5) {\n\t\t\t\t\tglobal.ZWave[zwayName].zway.RemoveNodeFromNetwork(false, false);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}, \"\");\n\n\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"controllerState\", function(type) {\n\t\tif (this.value == 0) {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x10, 0x02); // idle\n\t\t} else if (this.value >= 1 && this.value <= 4) {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x10, 0x08); // including\n\t\t} else if (this.value >= 5 && this.value <= 7) {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x10, 0x10); // excluding\n\t\t} else {\n\t\t\tglobal.ZWave[zwayName].zway.ZMEPHISetLED(0x10, 0x20); // other\n\t\t}\n\t}, \"\");\n\n\tif (!self.config.no_battery) {\n\t\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"philiohw.batteryLevel\", function(type) {\n\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Updated\"]) {\n\t\t\t\tself.addNotification(\"notification\", langFile.remaining_battery_level + (this.value * 10) + \"%\", \"controller\");\n\t\t\t\tbatteryLevelDev.set(\"metrics:level\", (this.value * 10));\n\t\t\t}\n\t\t}, \"\");\n\n\t\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"philiohw.powerFail\", function(type) {\n\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Updated\"]) {\n\t\t\t\tif (this.value) {\n\t\t\t\t\tself.addNotification(\"critical\", langFile.power_failure, \"controller\");\n\t\t\t\t\tpowerFailureDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\tif (self.batteryTimer) clearInterval(self.batteryTimer);\n\t\t\t\t\tself.batteryTimer = setInterval(function() {\n\t\t\t\t\t\t\tglobal.ZWave[zwayName].zway.ZMEPHIGetPower();\n\t\t\t\t\t}, 60*1000);\n\t\t\t\t} else {\n\t\t\t\t\tself.addNotification(\"notification\", langFile.power_recovery, \"controller\");\n\t\t\t\t\tpowerFailureDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\tif (self.batteryTimer) clearInterval(self.batteryTimer);\n\t\t\t\t\tself.batteryTimer = setInterval(function() {\n\t\t\t\t\t\t\tglobal.ZWave[zwayName].zway.ZMEPHIGetPower();\n\t\t\t\t\t}, 3600*1000);\n\t\t\t\t}\n\t\t\t}\n\t\t\tself.roundLED();\n\t\t}, \"\");\n\n\t\tthis.controller.emit(\"ZWave.dataBind\", self.bindings[zwayName], zwayName, \"philiohw.batteryFail\", function(type) {\n\t\t\tif (this.value) {\n\t\t\t\tself.addNotification(\"critical\", langFile.battery_falure, \"controller\");\n\t\t\t\tbatteryLevelDev.set(\"metrics:level\", 0);\n\t\t\t}\n\t\t}, \"\");\n\t}\n\t\n\t// sync round LED with actual box status on start\n\tself.roundLED();\n};\n"
  },
  {
    "path": "modules/PhilioHW/lang/de.json",
    "content": "{\n\t\"m_title\":\"Philio hardware support\",\n\t\"m_descr\":\"Support for Philio hardware buttons, LEDs, power and battery management\",\n\t\"tamper_triggered\":\"Controller opened or removed from wall\",\n\t\"tamper_idle\":\"Controller returned to normal position\",\n\t\"remaining_battery_level\":\"Remaining controller battery level is \",\n\t\"battery_failure\":\"Backup battery failure!\",\n\t\"power_failure\":\"AC power lost\",\n\t\"power_recovery\":\"AC power recover\",\n\t\"l_no_battery\": \"No battery installed\",\n\t\"h_no_battery\": \"Check if controller have no battery installed to hide battery and power status widgets\",\n\t\"l_breath\": \"Enable contour LED\",\n\t\"h_breath\": \"Enable 'breathing' contour LED\"\n}"
  },
  {
    "path": "modules/PhilioHW/lang/en.json",
    "content": "{\n\t\"m_title\":\"Philio hardware support\",\n\t\"m_descr\":\"Support for Philio hardware buttons, LEDs, power and battery management\",\n\t\"tamper_triggered\":\"Controller opened or removed from wall\",\n\t\"tamper_idle\":\"Controller returned to normal position\",\n\t\"remaining_battery_level\":\"Remaining controller battery level is \",\n\t\"battery_failure\":\"Backup battery failure!\",\n\t\"power_failure\":\"AC power lost\",\n\t\"power_recovery\":\"AC power recover\",\n\t\"l_no_battery\": \"No battery installed\",\n\t\"h_no_battery\": \"Check if controller have no battery installed to hide battery and power status widgets\",\n\t\"l_breath\": \"Enable contour LED\",\n\t\"h_breath\": \"Enable 'breathing' contour LED\"\n}"
  },
  {
    "path": "modules/PhilioHW/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Поддержка контроллера Philio\",\n\t\"m_descr\":\"Поддержка оборудования Philio: кнопок, светодиода, детекции питания и управления аккумулятором\",\n\t\"tamper_triggered\":\"Контроллер вскрыли или сняли со стены\",\n\t\"tamper_idle\":\"Контроллер вернули в нормальное положение\",\n\t\"remaining_battery_level\":\"Оставшийся зарад аккумулятора контроллера \",\n\t\"battery_failure\":\"Сбой в резервном аккумуляторе!\",\n\t\"power_failure\":\"Пропало питание\",\n\t\"power_recovery\":\"Питание восстановлено\",\n\t\"l_no_battery\": \"Аккумулятор не установлен\",\n\t\"h_no_battery\": \"Установите галочку на контроллерах без аккумулятора, чтобы скрыть виджеты батарейки и статуса питания\",\n\t\"l_breath\": \"Включить подсветку\",\n\t\"h_breath\": \"Включить 'дышашую' подсветку\"\n}"
  },
  {
    "path": "modules/PhilioHW/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"support_external_dev\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"PhilioHW\",\n\t\"version\": \"1.0.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"no_battery\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": false\n\t\t\t},\n\t\t\t\"breath\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": false\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"no_battery\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"label\": \"__l_no_battery__\",\n\t\t\t\t\"helper\": \"__h_no_battery__\"\n\t\t\t},\n\t\t\t\"breath\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"label\": \"__l_breath__\",\n\t\t\t\t\"helper\": \"__h_breath__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/PoppCam/index.js",
    "content": "/*** PoppCam Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of PoppCam\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction PoppCam (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tPoppCam.super_.call(this, id, controller);\n}\n\ninherits(PoppCam, AutomationModule);\n\n_module = PoppCam;\n\n// ----------------------------------------------------------------------------\n// --- Module insPoppCam9828tance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(PoppCam.prototype, {\n\tinit: function (config) {\n\t\tPoppCam.super_.prototype.init.call(this, config);\n\t\tvar self=this;\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tthis.proxy_url \t= \"/\" + vDevId + \"/stream\";\n \n\t   \tvar urlup\t\t= config.url + \"/moveptz.xml?dir=up\";\n\t\tvar urldown\t\t= config.url + \"/moveptz.xml?dir=down\";\n\t\tvar urlleft\t\t= config.url + \"/moveptz.xml?dir=left\";\n\t\tvar urlright\t= config.url + \"/moveptz.xml?dir=right\";\n\t\tvar urlstop\t\t= config.url + \"/moveptz.xml?dir=stop\"; \n\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t\t\n\t\t/* setting up the autentications seems not to work anymore\n\t\t\n\t\tthis.setup \t= config.url+ \"/login.xml?user=\" + config.user + \"&password=\" + config.password + \"&usr=\" + config.user + \"&pwd=\" + config.password;  \n\t\tif (this.setup) {\n\t\t\thttp.request({\n\t\t\t\turl: this.setup,\n\t\t\t\tasync: true,\n\t\t\t\tauth: {\n\t\t\t\t\tlogin: config.user,\n\t\t\t\t\tpassword: config.password\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t*/\n\t\t\t\n\t\tthis.url\t= config.url + \"/videostream.cgi?user=\" + config.user + \"&password=\" + config.password;\t\t\n\t\tws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t\thasLeft: !!urlleft,\n\t\t\t\t\thasRight: !!urlright,\n\t\t\t\t\thasUp: !!urlup,\n\t\t\t\t\thasDown: !!urldown,\n\t\t\t\t\thasClose: !!urlstop || (config.doorDevices && config.doorDevices.length)\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\t\t\t\tconsole.log(urlstop);  \n\t\t\t\tif (command == \"left\") {\n\t\t\t\t\turl = urlleft;\n\t\t\t\t} else if (command == \"right\") {\n\t\t\t\t\turl = urlright\n\t\t\t\t} else if (command == \"up\") {\n\t\t\t\t\turl = urlup;\n\t\t\t\t} else if (command == \"down\") {\n\t\t\t\t\turl = urldown;\n\t\t\t\t} else if (command == \"open\") {\n\t\t\t\t\turl = urlopen;\n\t\t\t\t\topener(command);\n\t\t\t\t} else if (command == \"close\") {\n\t\t\t\t\turl = urlstop;\n\n //\t\t\t\t   opener(command);\n\t\t\t\t}\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tPoppCam.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/PoppCam/lang/de.json",
    "content": "{\n\t\"m_title\":\"PoppCam\",\n\t\"m_descr\":\"Ermöglicht PoppCam Ünterstützung\",\n\t\"l_ip\":\"IP-Adresse der Kamera\",\n\t\"h_ip\":\"Beispielformat: 'http://IPADDRESS:PORT' - der Default Port ist 81\",\n\t\"l_user\":\"Benutzername\",\n\t\"h_user\":\"Sie benötigen den Benutzernamen, den Sie in der Kamerakonfiguration angegeben haben. Default ist 'admin'\",\n\t\"l_pw\":\"Passwort\",\n\t\"h_pw\":\"Sie benötigen das Passwort, dass Sie in der Kamerakonfiguration angegeben haben. Default ist 'admin'\",\n\t\"l_door_dev\":\"Türsensor\"\n}"
  },
  {
    "path": "modules/PoppCam/lang/en.json",
    "content": "{\n\t\"m_title\":\"PoppCam\",\n\t\"m_descr\":\"Support the PoppCam\",\n\t\"l_ip\":\"Camera IP URL\",\n\t\"h_ip\":\"in the format 'http://IPADDRESS:PORT'. Default Port is 81\",\n\t\"l_user\":\"Username\",\n\t\"h_user\":\"This is the username that was set up during camera configuration. Default is 'admin'\",\n\t\"l_pw\":\"Password\",\n\t\"h_pw\":\"This is the password that was set up during camera configuration. Default is 'admin'\",\n\t\"l_door_dev\":\"Door device\"\n}"
  },
  {
    "path": "modules/PoppCam/lang/ru.json",
    "content": "{\n\t\"m_title\":\"PoppCam\",\n\t\"m_descr\":\"Поддержка Камер PoppCam.\",\n\t\"l_ip\":\"URL Камеры\",\n\t\"h_ip\":\"В формате 'http://IPADDRESS:PORT'. По умолчанию порт 81\",\n\t\"l_user\":\"Имя пользователя\",\n\t\"h_user\":\"Имя пользователя, которое установлено в настройках камеры. По умолчанию 'admin'\",\n\t\"l_pw\":\"Пароль\",\n\t\"h_pw\":\"Пароль, который установлен в настройках камеры. По умолчанию 'admin'\",\n\t\"l_door_dev\":\"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/PoppCam/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.foscam.com/\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"PoppCam\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"format\": \"password\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__l_ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\t\t\t\t\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"user\": {\n\t\t\t\t\"label\": \"__l_user__\",\n\t\t\t\t\"helper\": \"__h_user__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"password\": {\n\t\t\t\t\"label\": \"__l_pw__\",\n\t\t\t\t\"helper\": \"__h_pw__\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__l_door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/RGB/index.js",
    "content": "/*** RGB Z-Way HA module *******************************************\n\nVersion: 1.0.1\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me> \n-- changed by: Niels Roche <nir@zwave.eu>\n\nDescription:\n\tBinds several dimmers to make RGB device\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction RGB (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tRGB.super_.call(this, id, controller);\n}\n\ninherits(RGB, AutomationModule);\n\n_module = RGB;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nRGB.prototype.init = function (config) {\n\tRGB.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.lastConfig = {\n\t\tr: 99,\n\t\tg: 99,\n\t\tb: 99\n\t};\n\n\tfunction levelToColor(vDev) {\n\t\tvar val = vDev.get(\"metrics:level\");\n\t\t\n\t\tif (val === \"on\" || val === \"255\") {\n\t\t\treturn 255;\n\t\t} else if (val === \"off\" || val === \"0\") {\n\t\t\treturn 0;\n\t\t} else if (!isNaN(parseInt(val))) {\n\t\t\treturn Math.round(parseInt(val) * 255.0/99.0);\n\t\t}\n\t}\n\t\n\tfunction colorToLevel(color) {\n\t\treturn Math.round(color * 99.0 / 255.0);\n\t}\n\t\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"RGB_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"switchRGBW\",\n\t\t\tmetrics: {\n\t\t\t\ticon: '',\n\t\t\t\ttitle: 'RGB ' + this.id,\n\t\t\t\tcolor: {r: 0, g: 0, b: 0},\n\t\t\t\tlevel: 'off'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler:  function (command, args) {\n\t\t\tswitch(command){\n\t\t\t\tcase \"off\":\n\t\t\t\t\tself.controller.devices.get(self.config.red).performCommand(command);\n\t\t\t\t\tself.controller.devices.get(self.config.green).performCommand(command);\n\t\t\t\t\tself.controller.devices.get(self.config.blue).performCommand(command);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"exact\":\n\t\t\t\t\t// change lastConfig values\n\t\t\t\t\tself.lastConfig.r = colorToLevel(args.red);\n\t\t\t\t\tself.lastConfig.g = colorToLevel(args.green);\n\t\t\t\t\tself.lastConfig.b = colorToLevel(args.blue);\n\n\t\t\t\t\t// set color\n\t\t\t\t\tself.controller.devices.get(self.config.red).performCommand(\"exact\", { level: colorToLevel(args.red) } );\n\t\t\t\t\tself.controller.devices.get(self.config.green).performCommand(\"exact\", { level: colorToLevel(args.green) } );\n\t\t\t\t\tself.controller.devices.get(self.config.blue).performCommand(\"exact\", { level: colorToLevel(args.blue) } );\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tself.controller.devices.get(self.config.red).performCommand(\"exact\", { level: self.lastConfig.r } );\n\t\t\t\t\tself.controller.devices.get(self.config.green).performCommand(\"exact\", { level: self.lastConfig.g } );\n\t\t\t\t\tself.controller.devices.get(self.config.blue).performCommand(\"exact\", { level: self.lastConfig.b } );\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\n\tthis.handleLevel = function() {\n\t\tself.vDev.set(\"metrics:level\", (\n\t\t\tlevelToColor(self.controller.devices.get(this.config.red)) ||\n\t\t\tlevelToColor(self.controller.devices.get(this.config.green)) ||\n\t\t\tlevelToColor(self.controller.devices.get(this.config.blue))\n\t\t) ? 'on' : 'off');\n\t};\n\t\n\tthis.handleR = function () {\n\t\tself.vDev.set(\"metrics:color:r\", levelToColor(self.controller.devices.get(self.config.red)));\n\t\tself.handleLevel();\n\t};\n\tthis.handleG = function () {\n\t\tself.vDev.set(\"metrics:color:g\", levelToColor(self.controller.devices.get(self.config.green)));\n\t\tself.handleLevel();\n\t};\n\tthis.handleB = function () {\n\t\tself.vDev.set(\"metrics:color:b\", levelToColor(self.controller.devices.get(self.config.blue)));\n\t\tself.handleLevel();\n\t};\n\tthis.controller.devices.on(self.config.red, \"change:metrics:level\", this.handleR);\n\tthis.controller.devices.on(self.config.green, \"change:metrics:level\", this.handleG);\n\tthis.controller.devices.on(self.config.blue, \"change:metrics:level\", this.handleB);\n};\n\nRGB.prototype.stop = function () {\n\tthis.controller.devices.off(this.config.red, \"change:metrics:level\", this.handleR);\n\tthis.controller.devices.off(this.config.green, \"change:metrics:level\", this.handleG);\n\tthis.controller.devices.off(this.config.blue, \"change:metrics:level\", this.handleB);\n\n\tthis.handleR = null;\n\tthis.handleG = null;\n\tthis.handleB = null;\n\t\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tRGB.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/RGB/lang/de.json",
    "content": "{\n\t\"m_title\":\"RGB Steuerung aus 3 Dimmern\",\n\t\"m_descr\":\"RGB Geräte bieten einen entsprechenden Befehl zur Farbeinstellung. Einige veraltete Geräte unterstützen zwar diese spezielle Z-Wave Farbwahlmethode nicht, aber emulieren ihren Farbwechsel mit drei Dimmern für die Farben Rot, Grün und Blau. Diese App kombiniert diese drei Dimmer und bietet ein praktisches Element zur Farbwahl durch entsprechende Einstellung der drei Dimmerwerte.Beachten Sie bitte: Moderne Z-Wave Geräte sollten durch diese UI unterstützt werden ohne Installation zusätzlicher Apps wie dieser. Infolgedessen wird diese App nur für Altgeräte benötigt.  <br><br>Einstellungen:<br><ul><li>Auswahl freier Dimmer von veralteten RGB Steuergeräten</li></ul><br>Anwendung:Ein neues Element wird zur Einstellung von Farbwerten erstellt. Bitte beachten Sie, dass in der Regel ein weiteres Dimmerelement angelegt wird, dass schließlich die gewählte Farbe dimmt. \",\n\t\"l_red\":\"Rot\",\n\t\"l_green\":\"Grün\",\n\t\"l_blue\":\"Blau\"\n}"
  },
  {
    "path": "modules/RGB/lang/en.json",
    "content": "{\n\t\"m_title\":\"RGB Light from 3 Dimmers\",\n\t\"m_descr\":\"RGB devices offer a dedicated command to set their color. Some legacy devices dont support this defined Z-Wave Color Choosing Method but emulate their color change with three dimmers for the three colors Red, Green, Blue. This app combines these three dimmers and offers a convenient element to pick the color by setting the three dimmer values accordingly.Note: Modern Z-Wave devices shall be supported by this UI without installing any additional app like this. Hence, this app is only needed for legacy devices<br><br>Settings:<br><ul><li>Pick the free dimmers of the legacy RGB control device</li></ul><br>Usage:A new element is created allowing setting the color value. Please note that usually another dimmer element is created that will finally dim the device with the selected color.\",\n\t\"l_red\":\"Red\",\n\t\"l_green\":\"Green\",\n\t\"l_blue\":\"Blue\"\n}\n"
  },
  {
    "path": "modules/RGB/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Устройство управления RGB (Цветной) лентой\",\n\t\"m_descr\":\"Создание устройства для управления RGB (Цветной) лентой основанное на трёх разных диммерах.\",\n\t\"l_red\":\"Красный\",\n\t\"l_green\":\"Зеленый\",\n\t\"l_blue\":\"Синий\"\n}"
  },
  {
    "path": "modules/RGB/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"legacy_products_workaround\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"RGB\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"red\": null,\n\t\t\"green\": null,\n\t\t\"blue\": null\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"red\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"green\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"blue\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"red\": {\n\t\t\t\t\"label\": \"__l_red__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t},\n\t\t\t\"green\": {\n\t\t\t\t\"label\": \"__l_green__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t},\n\t\t\t\"blue\": {\n\t\t\t\t\"label\": \"__l_blue__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/RemoteAccess/index.js",
    "content": "/*** RemoteAccess Z-Way HA module *******************************************\n\nVersion: 1.0.6\n(c) Z-Wave.Me, 2015\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>\nDescription:\n\tThis module allows to set or get remote access values in admin profile via 'My settings'\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction RemoteAccess (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tRemoteAccess.super_.call(this, id, controller);\n}\n\ninherits(RemoteAccess, AutomationModule);\n\n_module = RemoteAccess;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nRemoteAccess.prototype.init = function (config) {\n\tRemoteAccess.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tlangFile = self.loadModuleLang();\n\n\tthis.path = self.config.path;\n\tthis.zbw = null;\n\tthis.checkIfTypeError = true;\n\tthis.zbwTimerCount = 0;\n\tthis.serviceTimerCount = 0;\n\n\tthis.setZBWService = function() {\n\t\t// look if ZBW Service is available \n\t\tif (typeof ZBWConnect === 'function') {\n\t\t\ttry {\n\t\t\t\tself.zbw = self.path? new ZBWConnect(self.path) : new ZBWConnect(); // find zbw by path or use (raspberry) location /etc/zbw as default\n\n\t\t\t\tif(!!self.zbw) {\n\t\t\t\t\tself.checkIfTypeError = self.zbw.getUserId() instanceof TypeError? true : false;\n\t\t\t\t\tself.checkIfTypeError = self.zbw.getActStatus() instanceof TypeError? true : false;\n\t\t\t\t\tself.checkIfTypeError = self.zbw.getSshStatus() instanceof TypeError? true : false;\n\t\t\t\t\tself.checkIfTypeError = self.zbw.getStatus() instanceof TypeError? true : false;\n\t\t\t\t}\n\t\t\t} catch (e) {\t\t\t  \n\n\t\t\t\tif (self.serviceTimer) {\n\t\t\t\t\tconsole.log('Clear self.serviceTimer ... ');\n\t\t\t\t\tclearInterval(self.serviceTimer);\n\t\t\t\t}\n\n\t\t\t\tif (!self.zbwTimer) {\n\t\t\t\t\t// set interval (5 sec) to check for service again - max. 5 min\n\t\t\t\t\tself.zbwTimer = setInterval(function() {\n\t\t\t\t\t\tself.zbwTimerCount ++;\n\t\t\t\t\t\tconsole.log('zbwTimerCount:'+ self.zbwTimerCount);\n\t\t\t\t\t\tself.setZBWService();\n\t\t\t\t\t}, 5000);\n\n\t\t\t\t} else if (self.zbwTimer && self.zbwTimerCount > 60) {\n\t\t\t\t\tconsole.log('Clear self.zbwTimer after 5 min');\n\t\t\t\t\t// clear interval after 5 min\n\t\t\t\t\tclearInterval(self.zbwTimer);\n\t\t\t\t\tself.zbwTimer = undefined;\n\t\t\t\t\t\n\t\t\t\t\tself.addNotification(\"warning\", langFile.zbw_service_timeout, \"module\");\n\t\t\t\t\tself.addNotification(\"error\", langFile.load_zbw_error, \"module\");\n\t\t\t\t\t\n\t\t\t\t\tconsole.log(langFile.load_zbw_error,'Error:', e.message);\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tif (!!self.zbw && !self.checkIfTypeError) {\n\t\t\t\t// start RemoteAccess functions\n\t\t\t\tconsole.log('success! start zbw ... ');\n\t\t\t\tself.startRemoteAccess(config, self.zbw, langFile);\n\n\t\t\t\t// clear interval\n\t\t\t\tif (self.zbwTimer) {\n\t\t\t\t\tconsole.log('Clear self.zbwTimer ... ');\n\t\t\t\t\tclearInterval(self.zbwTimer);\n\t\t\t\t\tself.zbwTimer = undefined;\n\t\t\t\t}\n\n\t\t\t\tif (self.serviceTimer) {\n\t\t\t\t\tconsole.log('Clear self.serviceTimer ... ');\n\t\t\t\t\tclearInterval(self.serviceTimer);\n\t\t\t\t\tself.serviceTimer = undefined;\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else if (!self.serviceTimer) {\n\t\t\t// set interval (5 sec) to check for service again - max. 5 min\n\t\t\tself.serviceTimer = setInterval(function() {\n\t\t\t\tself.serviceTimerCount ++;\n\t\t\t\t\n\t\t\t\tconsole.log('serviceTimerCount:', self.serviceTimerCount);\n\t\t\t\tself.setZBWService();\n\t\t\t}, 5000);\n\n\t\t} else if (self.serviceTimer && self.serviceTimerCount > 60) {\n\t\t\t// clear interval after 5 min\n\t\t\tconsole.log('Clear self.serviceTimer after 5 min');\n\t\t\t\n\t\t\tclearInterval(self.serviceTimer);\n\t\t\tself.serviceTimer = undefined;\n\n\t\t\tself.addNotification(\"warning\", langFile.zbw_service_timeout, \"module\");\n\t\t}\n\t};\n\n\t// initialize service\n\tself.setZBWService();\n};\n\nRemoteAccess.prototype.stop = function () {\n\n\tif (this.serviceTimer) {\n\t\tclearInterval(this.serviceTimer);\n\t\tthis.serviceTimer = undefined;\n\t}\n\n\tif (this.zbwTimer) {\n\t\tclearInterval(this.zbwTimer);\n\t\tthis.zbwTimer = undefined;\n\t}\n\n\tRemoteAccess.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nRemoteAccess.prototype.startRemoteAccess = function (config, zbw, langFile) {\n\t\n\tvar self = this;\n\n\tthis.updateRemoteData = function () {\n\t\ttry {\n\t\t\tself.config.userId = zbw.getUserId();\n\t\t\tself.config.actStatus = zbw.getActStatus();\n\t\t\tself.config.sshStatus = zbw.getSshStatus();\n\t\t\tself.config.zbwStatus = zbw.getStatus();\n\t\t} catch(e) {\n\t\t\tself.addNotification(\"warning\", langFile.setup_config_zbw_error + e.message, \"module\");\n\t\t}\n\t};\n\n\tthis.setRemoteConfigurations = function () {\n\t\ttry{\n\t\t\tvar raSshStatus = zbw.getSshStatus(),\n\t\t\t\traStatus = zbw.getStatus(),\n\t\t\t\tpassword = self.config.pass? self.config.pass : '',\n\t\t\t\tcurrDate = new Date();\n\n\t\t\t// update userId (after restoring backup userId in the config might not be equal userId in ZBW service)\n\t\t\tself.config.userId = zbw.getUserId();\n\n\t\t\t// stop and start zbw connect if necessary\t   \n\t\t\tif(raStatus !== false && raStatus === self.config.zbwStatus && (raSshStatus !== self.config.sshStatus || password)){\n\t\t\t\tzbw.setStatus(false); // stop zbw\n\t\t\t\tconsole.log('--- Stopping ZBW Connect Service');\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tzbw.setStatus(true);\n\t\t\t\t\tconsole.log('--- Starting ZBW Connect Service');\n\t\t\t\t}, 7000); // wait 7 sec to start zbw\n\t\t\t}\n\n\t\t\t// set remote ssh status\n\t\t\tif(raSshStatus !== self.config.sshStatus){\n\t\t\t\tzbw.setSshStatus(self.config.sshStatus);\n\t\t\t\tself.config.lastChange.sshStatus = currDate;\n\t\t\t}\n\n\t\t\t// start/stop zbw connect - start/stop RemoteAccess\n\t\t\tif(raStatus !== self.config.zbwStatus){\n\t\t\t\tzbw.setStatus(self.config.zbwStatus);\n\t\t\t\tself.config.zbwStatus === false ? console.log('--- Stopping ZBW Connect Service') : console.log('--- Starting ZBW Connect Service');\n\t\t\t\tself.config.lastChange.zbwStatus = currDate;\n\t\t\t\tself.config.actStatus = zbw.getActStatus();\n\t\t\t}\n\n\t\t\t// set remote password\n\t\t\tif(password){\n\t\t\t\tzbw.setPass(password);\n\t\t\t\tself.config.pass = '';\n\t\t\t\tself.config.lastChange.pass = currDate;\n\t\t\t}\n\n\t\t\tif(raSshStatus !== self.config.sshStatus || raStatus !== self.config.zbwStatus || password) {\n\t\t\t\tself.addNotification(\"notification\", langFile.config_changed_successful, \"module\");\n\t\t\t}\n\t\t} catch(e) {\n\t\t\tself.addNotification(\"error\", langFile.config_changed_error + e.message, \"module\");\n\t\t} \n\t};  \n\t\n\t// run first time to get the values from zbw module\n\tif(self.config.userId === '' || self.config.actStatus === '' || self.config.sshStatus === '' || self.config.zbwStatus === '') {\n\t\tself.updateRemoteData();\n\t} else {\n\t\tself.setRemoteConfigurations();\n\t}\n};"
  },
  {
    "path": "modules/RemoteAccess/lang/de.json",
    "content": "{\n\t\"m_title\":\"Remote-Zugriff\",\n\t\"m_descr\":\"Diese App wird benötig, um über die SmartHome UI den Remote-Zugriff zu konfigurieren. </br></br><strong>Hinweis:</strong></br></br>Ein Entfernen oder Stoppen der App wird den Fernzugriff nicht beenden, wenn dieser nicht vorher explizit unter <strong>Einstellungen > Management > Verwaltung des Fernzugriffes</strong> deaktiviert wurde.\",\n\t\"l_ra_path\":\"Absoluter Pfad auf dem Server zu ZBWConnect:\",\n\t\"h_ra_path\":\"z.B. /etc/zbw oder ./zbw - wird auf dem Raspberry nicht benötigt\",\n\t\"load_zbw_error\":\"ZBWConnect Modul konnte nicht initialisiert werden. Fehler: \",\n\t\"setup_config_zbw_error\":\"Der Remote-Zugriff konnte nicht initialisiert werden. Bitte checken Sie Ihre Internetverbindung und starten Sie den Service unter 'Apps > Active > Remote Access' erneut.\",\n\t\"config_changed_successful\":\"Konfiguration des Remote-Zugriffs erfolgreich geändert.\",\n\t\"config_changed_error\":\"Konfigurationsproblem: \",\n\t\"zbw_service_timeout\":\"The connection to the ZBW Service has timed out. Please restart the App 'Remote Access' and try it again.\"\n}"
  },
  {
    "path": "modules/RemoteAccess/lang/en.json",
    "content": "{\n\t\"m_title\":\"Remote Access\",\n\t\"m_descr\":\"This app is required to configure the remote access via the Smart Home UI.</br></br><strong>Note:</strong></br></br>Removing or stopping the app will not stop the remote access, if it has not been disabled explicitly under <strong>Settings > Management > Remote Access</strong> in advance.\",\n\t\"l_ra_path\":\"Absolute path to ZBWConnect on server:\",\n\t\"h_ra_path\":\"e.g. /etc/zbw or ./zbw - not necessary on raspberry\",\n\t\"load_zbw_error\":\"Cannot initialize ZBWConnect module. Error: \",\n\t\"setup_config_zbw_error\":\"Remote Access is not initialized yet, you probably need to connect to the internet and restart the service in 'Apps > Active > Remote Access'\",\n\t\"config_changed_successful\":\"Configuration of remote access has changed successfully.\",\n\t\"config_changed_error\":\"Configuration error: \",\n\t\"zbw_service_timeout\":\"The connection to the ZBW Service has timed out. Please restart the App 'Remote Access' and try it again.\"\n}"
  },
  {
    "path": "modules/RemoteAccess/module.json",
    "content": "{\n\t\"singleton\" : true,\n\t\"dependencies\" : [],\n\t\"category\" : \"security\",\n\t\"author\" : \"Z-Wave.Me\",\n\t\"homepage\" : \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"RemoteAccess\",\n\t\"version\" : \"1.0.6\",\n\t\"maturity\" : \"stable\",\n\t\"repository\" : {\n\t\t\"type\" : \"git\",\n\t\t\"source\" : \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\" : {\n\t\t\"title\" : \"__m_title__\",\n\t\t\"description\" : \"__m_descr__\",\n\t\t\"path\":\"\",\n\t\t\"userId\":\"\",\n\t\t\"actStatus\":\"\",\n\t\t\"sshStatus\":\"\",\n\t\t\"zbwStatus\":\"\",\n\t\t\"pass\":\"\",\n\t\t\"lastChange\":{}\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"path\": {\n\t\t\t\t\"required\": false\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"path\": {\n\t\t\t\t\"label\": \"__l_ra_path__\",\n\t\t\t\t\"helper\": \"__h_ra_path__\"\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/RemoteAccess/patchnotes.txt",
    "content": "v1.0.6\n- remove initial restart\n\nv1.0.5\n- add initial restart to fix zbw service problems\n- interval added to check if ZBW service is available - check max. 5 minutes\n"
  },
  {
    "path": "modules/RoundRobinScenes/index.js",
    "content": "/*** RoundRobinScenes Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tSwitches scenes in round robin policy\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction RoundRobinScenes (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tRoundRobinScenes.super_.call(this, id, controller);\n}\n\ninherits(RoundRobinScenes, AutomationModule);\n\n_module = RoundRobinScenes;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nRoundRobinScenes.prototype.init = function (config) {\n\tRoundRobinScenes.super_.prototype.init.call(this, config);\n\n\tthis.currentSceneIndex = -1;\n\n\tvar self = this;\n\t\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"RoundRobinScene_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"toggleButton\",\n\t\t\tmetrics: {\n\t\t\t\tlevel: \"on\", // it is always on, but usefull to allow bind\n\t\t\t\ticon: \"gesture\",\n\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function () {\n\t\t\tself.currentSceneIndex++;\n\t\t\tself.currentSceneIndex %= self.config.scenes.length;\n\n\t\t\tvar vDev = self.controller.devices.get(self.config.scenes[self.currentSceneIndex]);\n\t\t\tif (vDev) {\n\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t}\n\t\t\t\n\t\t\tself.vDev.set(\"metrics:level\", \"on\"); // update on ourself to allow catch this event\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\tif (this.config.trackCurrent) {\n\t\tthis.tracker = function(vDev) {\n\t\t\tfor (var i in self.config.scenes) {\n\t\t\t\tif (self.config.scenes[i] === vDev.id) {\n\t\t\t\t\tself.currentSceneIndex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\t\n\t\tfor (var i in this.config.scenes) {\n\t\t\tthis.controller.devices.on(self.config.scenes[i], \"change:metrics:level\", this.tracker);\n\t\t}\n\t}\n};\n\nRoundRobinScenes.prototype.stop = function () {\n\tif (this.config.trackCurrent) {\n\t\tfor (var i in this.config.scenes) {\n\t\t\tthis.controller.devices.off(self.config.scenes[i], \"change:metrics:level\", this.tracker);\n\t\t}\n\n\t\tthis.tracker = null;\n\t}\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tRoundRobinScenes.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/RoundRobinScenes/lang/de.json",
    "content": "{\n\t\"m_title\":\"Sequenzieller Szenenumschalter\",\n\t\"m_descr\":\"Diese Anwendung erstellt ein simples UI Element zur Schaltung von einer Reihe auserwhlter Szenen, welche immer eine nach der anderen (Round Robin) ausgefhrt werden. Im Falle von lediglich zwei Szenen schaltet dieses Element immer zwischen beiden hin und her. Diese Einstellung ist insbesondere dann sinnvoll, wenn mehrere Szenen innerhalb eines Raumes oder Bereiches immer in einer bestimmten Reihenfolge ausgefhrt werden sollen. Beispiel fr Szenen im Schlafzimmer: <br> 1 - Beim Betreten des Raumes,  Erleuchten des Raumes<br> 2 - Gang zum Bett,  Leichtes Abdimmen des Lichtes<br> 3 - Schlafen,  Alles ist ausgeschalten.<br>4 - Aufwachen am Morgen,  Licht leicht gedimmt einschalten.<br><br>Einstellungen:<br><ul><li>Auffhren der Szenen, die nacheinander aktiviert werden sollen.</ul></li>\",\n\t\"l_options\":\"Zu aktivierende Szenen/Aktionen:\",\n\t\"rl_track_current\":\"Change index of the next scene to be executed according to explicit manually activated scene\"\n}\n"
  },
  {
    "path": "modules/RoundRobinScenes/lang/en.json",
    "content": "{\n\t\"m_title\":\"Round Robin Scene Switcher\",\n\t\"m_descr\":\"This application creates a simple UI element allowing the switching a series of selected scenes in round robin (one after each other). In case there are only two scenes defined this element will toggle between these two scenes. This setup is particularly useful if there are multiple scenes for one room or zone that are typically executed in a defined order (Example: Three scenes in sleeping room: 1 enter the room –> light up the room, 2 move to bed -> dim the light but still keep it up, 3 sleep -> everything is off, 4 - > wakeup in the morning -> only dim the light)<br><br>Settings:<br><ul><li>List of scenes to be activates in round robin</li></ul>\",\n\t\"l_options\":\"List of scenes to activate\",\n\t\"rl_track_current\":\"Change index of the next scene to be executed according to explicit manually activated scene\"\n}"
  },
  {
    "path": "modules/RoundRobinScenes/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Запуск сцен одна за одной по кругу\",\n\t\"m_descr\":\"Round-robin алгоритм для циклического запуска сцен. При каждом запуске этой сцены будет запускаться следующая сцена из списка.\",\n\t\"l_options\":\"Список сцен\",\n\t\"rl_track_current\":\"Обновлять индекс следующей запускаемой сцены, учитывая явный ручной запуск сцен\"\n}"
  },
  {
    "path": "modules/RoundRobinScenes/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"RoundRobinScenes\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"scenes\": [],\n\t\t\"trackCurrent\": false\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"scenes\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"trackCurrent\": {\n\t\t\t\t\"type\": \"boolean\"\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"scenes\": {\n\t\t\t\t\"label\": \"__l_options__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"trackCurrent\": {\n\t\t\t\t\"label\": \"\",\n\t\t\t\t\"rightLabel\": \"__rl_track_current__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/Rules/index.js",
    "content": "/*** Rules Z-Way HA module *******************************************\n\nVersion: 1.0.1\n(c) Z-Wave.Me, 2018\n-----------------------------------------------------------------------------\nAuthor: Hans-Christian Göckeritz <hcg@zwave.eu>\nAuthor: Niels Roche <nir@zwave.eu>\nAuthor: Karsten Reichel <kar@zwave.eu>\nDescription:\n\tBind actions on one device to other devices or scenes\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Rules(id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tRules.super_.call(this, id, controller);\n\n\tvar self = this;\n\tthis.attachedList = [];\n\tthis.reversActivated = false;\n\n\tthis._testRule = function() { // wrapper to correct this and parameters in testRule\n\t\tself.testRule.call(self, null);\n\t}\n}\n\ninherits(Rules, AutomationModule);\n\n_module = Rules;\n\n/*\"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"simple\": {\n            \"triggerEvent\": {},\n            \"triggerDelay\": 0,\n            \"targetElements\": [],\n            \"sendNotifications\": [],\n            \"reverseDelay\": 0\n        },\n        \"advanced\": {\n            \"active\": false,\n            \"triggerScenes\" : [],\n            \"triggerDelay\": 0,\n            \"logicalOperator\" : \"and\",\n            \"tests\" : [],\n            \"targetElements\": [],\n            \"sendNotifications\": [],\n            \"reverseDelay\": 0,\n            \"triggerOnDevicesChange\" : true\n        },\n        \"reverse\": false\n    }*/\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nRules.prototype.init = function(config) {\n\tRules.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tifElement = self.config.simple.triggerEvent,\n\t\t/*\n\t\tcolor als trigger??\n\t\t{\n\t\t    deviceId: '',\n\t\t    deviceType: '',\n\t\t    level: '', //on, off, open, close, color, level\n\t\t    operator: <, = , > ,''\n\t\t}\n\t\t*/\n\t\tdoReverse = self.config.reverse,\n\t\tadvancedActive = self.config.advanced.active;\n\ttriggered = 0;\n\n\tthis.handlerLevel = function(sDev) {\n\t\tvar operator = ifElement.operator || null,\n\t\t\tifLevel = ifElement.level,\n\t\t\tifType = ifElement.deviceType,\n\t\t\tcheck = false,\n\t\t\tvalue = sDev.get(\"metrics:level\"),\n\t\t\tsimple = self.config.simple;\n\n\t\t// - IF-THEN-PART\n\t\tif (!!operator && ifLevel) {\n\t\t\tcheck = self.op(value, operator, ifLevel);\n\t\t} else if (ifType === 'switchRGBW') {\n\t\t\tcheck = _.isEqual(sDev.get(\"metrics:color\"), ifLevel);\n\t\t}\n\n\t\tvar triggerTimeout = self.getConfigTimeout(simple.triggerDelay);\n\t\tvar reverseTimeout = self.getConfigTimeout(simple.reverseDelay);\n\n\t\tif (check || value === ifLevel || sDev.get('deviceType') === 'toggleButton') {\n\n\t\t\tthis.simpleTriggerTimer = setTimeout(function() {\n\n\t\t\t\t/*\n\t\t\t\t{\n\t\t\t\t    deviceId: '',\n\t\t\t\t    deviceType: '',\n\t\t\t\t    level: '', / color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t\t    reverseLevel: '',\n\t\t\t\t    sendAction: true / false >> don't do this if level is already\n\t\t\t\t}\n\t\t\t\t*/\n\n\t\t\t\t// do action for all target devices\n\t\t\t\tsimple.targetElements.forEach(function(el) {\n\t\t\t\t\tself.shiftDevice(el);\n\t\t\t\t});\n\n\t\t\t\tsimple.sendNotifications.forEach(function(notification) {\n\t\t\t\t\tself.sendNotification(notification, simple.triggerEvent, simple.targetElements);\n\t\t\t\t});\n\n\t\t\t\tself.reversActivated = true;\n\t\t\t}, triggerTimeout);\n\t\t} else if (doReverse && !check && self.reversActivated) {\n\t\t\tthis.simpleReverseTimer = setTimeout(function() {\n\t\t\t\tself.performReverse(self.config.simple.targetElements);\n\t\t\t}, reverseTimeout);\n\t\t}\n\t};\n\n\tif (advancedActive) { // - LOGICAL-RULES-PART\n\t\tthis.expertTriggerEventRule();\n\t}\n\n\t// Setup metric update event listener\n\tif (!advancedActive && ifElement && ifElement.deviceId) {\n\t\tself.controller.devices.on(ifElement.deviceId, 'change:metrics:level', this.handlerLevel);\n\t}\n};\n\nRules.prototype.stop = function() {\n\tvar self = this;\n\n\tif (this.config.advanced.active) {\n\t\tif (this.config.advanced.triggerScenes) {\n\t\t\tthis.config.advanced.triggerScenes.forEach(function(scene) {\n\t\t\t\tself.attachDetach(scene, false);\n\t\t\t});\n\t\t}\n\n\t\t// testType ... switchBinary, switchMultilevel, switchRGBW, doorlock, switchControl, time, sensorDiscrete, nested\n\t\t// nested testType ... switchBinary, switchMultilevel, switchRGBW, doorlock, switchControl, time, sensorDiscrete\n\n\t\tthis.config.advanced.tests.forEach(function(test) {\n\t\t\tswitch (test.type) {\n\t\t\t\tcase 'switchBinary':\n\t\t\t\tcase 'switchMultilevel':\n\t\t\t\tcase 'sensorBinary':\n\t\t\t\tcase 'sensorMultilevel':\n\t\t\t\tcase 'switchRGBW':\n\t\t\t\tcase 'doorlock':\n\t\t\t\tcase 'switchControl':\n\t\t\t\tcase 'toggleButton':\n\t\t\t\tcase 'sensorDiscrete':\n\t\t\t\tcase 'thermostat':\n\t\t\t\t\tself.attachDetach(test, false);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'nested':\n\t\t\t\t\ttest.tests.forEach(function(xtest) {\n\t\t\t\t\t\tself.attachDetach(xtest, false);\n\t\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\t\tcase 'compare':\n\t\t\t\t\tif (test.devices.length == 2) {\n\t\t\t\t\t\ttest.devices.forEach(function(xtest) {\n\t\t\t\t\t\t\tself.attachDetach(xtest, false);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'time':\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\n\t\tthis.attachedList = [];\n\n\t} else {\n\t\t// remove event IfElement listener\n\t\tself.controller.devices.off(self.config.simple.triggerEvent.deviceId, 'change:metrics:level', self.handlerLevel);\n\t}\n\n\tif (this.simpleReverseTimer) {\n\t\tclearTimeout(this.simpleReverseTimer);\n\t\tthis.simpleReverseTimer = undefined;\n\t}\n\n\tif (this.advancedReverseTimer) {\n\t\tclearTimeout(this.advancedReverseTimer);\n\t\tthis.advancedReverseTimer = undefined;\n\t}\n\n\tif (this.simpleTriggerTimer) {\n\t\tclearTimeout(this.simpleTriggerTimer);\n\t\tthis.simpleTriggerTimer = undefined;\n\t}\n\n\tif (this.advancedTriggerTimer) {\n\t\tclearTimeout(this.advancedTriggerTimer);\n\t\tthis.advancedTriggerTimer = undefined;\n\t}\n\n\tthis.reversActivated = false;\n\n\tRules.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nRules.prototype.expertTriggerEventRule = function() {\n\tvar self = this;\n\n\t// testType ... switchBinary, switchMultilevel, switchRGBW, doorlock, switchControl, time, sensorDiscrete, nested\n\t// nested testType ... switchBinary, switchMultilevel, switchRGBW, doorlock, switchControl, time, sensorDiscrete\n\n\tthis.config.advanced.tests.forEach(function(test) {\n\t\tswitch (test.type) {\n\t\t\tcase 'switchBinary':\n\t\t\tcase 'switchMultilevel':\n\t\t\tcase 'sensorBinary':\n\t\t\tcase 'sensorMultilevel':\n\t\t\tcase 'switchRGBW':\n\t\t\tcase 'doorlock':\n\t\t\tcase 'switchControl':\n\t\t\tcase 'toggleButton':\n\t\t\tcase 'sensorDiscrete':\n\t\t\tcase 'thermostat':\n\t\t\t\t/*\n\t\t\t\t    test = {\n\t\t\t\t        type: 'xxx',\n\t\t\t\t        deviceId: 'xxx',\n\t\t\t\t        level: 'xxx',\n\t\t\t\t        operator: '=', '!=', '<', '>', '<=', '>='\n\t\t\t\t    },\n\t\t\t\t    time = {\n\t\t\t\t        type: 'time',\n\t\t\t\t        level: 'xxx',\n\t\t\t\t        testOperator: '<=', '>='\n\t\t\t\t    }\n\t\t\t\t*/\n\t\t\t\tself.attachDetach(test, true);\n\t\t\t\tbreak;\n\t\t\tcase 'nested':\n\t\t\t\t/*\n\t\t\t\tnested = {\n\t\t\t\t    type: 'nested',\n\t\t\t\t    logicalOperator: 'and' // 'or'\n\t\t\t\t    tests: [{\n\t\t\t\t            type: 'xxx'\n\t\t\t\t            deviceId: 'xxx'\n\t\t\t\t            level: 'xxx'\n\t\t\t\t            testOperator: '=', '!=', '<', '>', '<=', '>='\n\t\t\t\t        },{\n\t\t\t\t            type: 'aaa'\n\t\t\t\t            deviceId: 'aaa'\n\t\t\t\t            level: 'aaa'\n\t\t\t\t            testOperator: '=', '!=', '<', '>', '<=', '>='\n\t\t\t\t        }\n\t\t\t\t    ]\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\ttest.tests.forEach(function(xtest) {\n\t\t\t\t\tself.attachDetach(xtest, true);\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase 'compare':\n\t\t\t\t/*\n\t\t\t\tcompare = {\n\t\t\t\t    type: 'compare',\n\t\t\t\t    operator: '>=',\n\t\t\t\t    devices: [{\n\t\t\t\t        \tdeviceId: 'aaa',\n\t\t\t\t            type: 'aaa'\n\t\t\t\t        },\n\t\t\t\t        {\n\t\t\t\t        \tdeviceId: 'bbb,\n\t\t\t\t            type: 'bbb'\n\t\t\t\t    \t}\n\t\t\t\t    ]\n\t\t\t\t}\n\t\t\t\t*/\n\t\t\t\tif (test.devices.length == 2) {\n\t\t\t\t\ttest.devices.forEach(function(xtest) {\n\t\t\t\t\t\tself.attachDetach(xtest, true);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 'time':\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t});\n\n\t// TODO add sensorDiscrete as trigger\n\tthis.config.advanced.triggerScenes.forEach(function(scene) {\n\t\tself.attachDetach(scene, true);\n\t});\n};\n\n// LogicalRuleMethods\nRules.prototype.attachDetach = function(test, attachOrDetach) {\n\tif (this.config.advanced.triggerOnDevicesChange === false) { // this condition is used to allow empty triggerOnDevicesChange if old LogicalRules is used\n\t\treturn;\n\t}\n\n\tif (attachOrDetach) {\n\t\tif (this.attachedList.indexOf(test.deviceId) === -1) {\n\t\t\tthis.attachedList.push(test.deviceId);\n\t\t\tthis.controller.devices.on(test.deviceId, \"change:metrics:level\", this._testRule);\n\t\t\tthis.controller.devices.on(test.deviceId, \"change:metrics:change\", this._testRule); //switchControl\n\t\t}\n\t} else {\n\t\tthis.controller.devices.off(test.deviceId, \"change:metrics:level\", this._testRule);\n\t\tthis.controller.devices.off(test.deviceId, \"change:metrics:change\", this._testRule); //switchControl\n\t}\n};\n\nRules.prototype.testRule = function(tree) {\n\tvar self = this,\n\t\tres = null,\n\t\ttopLevel = !tree,\n\t\tself = this,\n\t\tlangFile = this.loadModuleLang(),\n\t\tdoReverse = this.config.reverse || false,\n\t\ttriggerTimeout = this.getConfigTimeout(self.config.advanced.triggerDelay),\n\t\treverseTimeout = this.getConfigTimeout(self.config.advanced.reverseDelay);\n\n\t// if tests are false check if advanced is active\n\tif (!!!tree) {\n\t\ttree = this.config.advanced;\n\t}\n\n\t// loop through all tests and proof conditions\n\tif (_.contains([\"and\", \"or\"], tree.logicalOperator)) {\n\t\tres = self.runTests[tree.logicalOperator].call(self, tree);\n\t}\n\n\tif (topLevel && res) {\n\t\tthis.advancedTriggerTimer = setTimeout(function() {\n\t\t\ttree.targetElements.forEach(function(el) {\n\t\t\t\tself.shiftDevice(el);\n\t\t\t});\n\n\t\t\ttree.sendNotifications.forEach(function(notification) {\n\t\t\t\tself.sendNotification(notification, tree.tests, tree.targetElements);\n\t\t\t});\n\n\t\t\tself.reversActivated = true;\n\n\t\t}, triggerTimeout);\n\t} else if (doReverse && !res && self.reversActivated) {\n\t\tthis.advancedReverseTimer = setTimeout(function() {\n\t\t\tself.performReverse(tree.targetElements);\n\t\t}, reverseTimeout);\n\t}\n\n\treturn res;\n};\n\nRules.prototype.runTests = {\n\t\"and\": function(tree) {\n\t\tvar res = true,\n\t\t\tself = this;\n\n\t\ttree.tests.forEach(function(test) {\n\t\t\tvar vDev = null, vDev2 = null, level = undefined, level2 = undefined;\n\t\t\tif (test.type !== 'nested' && test.type !== 'time' && test.type !== 'compare') {\n\t\t\t\tvDev = self.controller.devices.get(test.deviceId);\n\t\t\t\tlevel = !!vDev ? vDev.get(\"metrics:level\") : undefined;\n\t\t\t} else if (test.type == 'compare' && test.devices.length == 2) {\n\t\t\t\tvDev = self.controller.devices.get(test.devices[0].deviceId);\n\t\t\t\tvDev2 = self.controller.devices.get(test.devices[1].deviceId);\n\t\t\t\tlevel = !!vDev ? vDev.get(\"metrics:level\") : undefined;\n\t\t\t\tlevel2 = !!vDev2 ? vDev2.get(\"metrics:level\") : undefined\n\t\t\t}\n\n\t\t\tswitch (test.type) {\n\t\t\t\tcase 'doorlock':\n\t\t\t\tcase 'switchBinary':\n\t\t\t\tcase 'sensorBinary':\n\t\t\t\tcase 'sensorDiscrete':\n\t\t\t\t\tres = res && (level === test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'thermostat':\n\t\t\t\tcase 'switchMultilevel':\n\t\t\t\tcase 'sensorMultilevel':\n\t\t\t\t\tres = res && self.op(level, test.operator, test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'switchRGBW':\n\t\t\t\t\tres = res && _.isEqual(vDev.get('metrics:color'), test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'toggleButton':\n\t\t\t\tcase 'switchControl':\n\t\t\t\t\tres = res && self.compareSwitchControl(vDev, test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'time':\n\t\t\t\t\tres = res && self.compareTime(test.level, test.operator);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'nested':\n\t\t\t\t\tres = res && self.testRule(test);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'compare':\n\t\t\t\t\tres = res && self.op(level, test.operator, level2);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\n\t\treturn res;\n\t},\n\t\"or\": function(tree) {\n\t\tvar res = false,\n\t\t\tself = this;\n\n\t\ttree.tests.forEach(function(test) {\n\t\t\tvar vDev = null, vDev2 = null, level = undefined, level2 = undefined;\n\t\t\tif (test.type !== 'nested' && test.type !== 'time' && test.type !== 'compare') {\n\t\t\t\tvDev = self.controller.devices.get(test.deviceId);\n\t\t\t\tlevel = !!vDev ? vDev.get(\"metrics:level\") : undefined;\n\t\t\t} else if (test.type == 'compare' && test.devices.length == 2) {\n\t\t\t\tvDev = self.controller.devices.get(test.devices[0].deviceId);\n\t\t\t\tvDev2 = self.controller.devices.get(test.devices[1].deviceId);\n\t\t\t\tlevel = !!vDev ? vDev.get(\"metrics:level\") : undefined;\n\t\t\t\tlevel2 = !!vDev2 ? vDev2.get(\"metrics:level\") : undefined\n\t\t\t}\n\n\t\t\tswitch (test.type) {\n\t\t\t\tcase 'doorlock':\n\t\t\t\tcase 'switchBinary':\n\t\t\t\tcase 'sensorBinary':\n\t\t\t\tcase 'sensorDiscrete':\n\t\t\t\t\tres = res || (level === test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'thermostat':\n\t\t\t\tcase 'switchMultilevel':\n\t\t\t\tcase 'sensorMultilevel':\n\t\t\t\t\tres = res || self.op(level, test.operator, test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'switchRGBW':\n\t\t\t\t\tres = res || _.isEqual(vDev.get('metrics:color'), test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'toggleButton':\n\t\t\t\tcase 'switchControl':\n\t\t\t\t\tres = res || self.compareSwitchControl(vDev, test.level);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'time':\n\t\t\t\t\tres = res || self.compareTime(test.level, test.operator);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'nested':\n\t\t\t\t\tres = res || self.testRule(test);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'compare':\n\t\t\t\t\tres = res || self.op(level, test.operator, level2);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t});\n\n\t\treturn res;\n\t}\n}\n\nRules.prototype.performReverse = function(targetElements) {\n\tvar self = this;\n\n\tif (targetElements && targetElements.length > 0) {\n\t\ttargetElements.forEach(function(el) {\n\n\t\t\tif (el.reverseLevel !== null) {\n\t\t\t\tself.shiftDevice(el, true);\n\n\t\t\t\tself.reversActivated = false;\n\t\t\t}\n\t\t});\n\t\tself.reversActivated = false;\n\t}\n};\n\nRules.prototype.sendNotification = function(notification, conditions, actions) {\n\tvar notificationType = '',\n\t\tnotificationMessage = '';\n\n\tif (notification.target && notification.target !== '') {\n\t\tthis.controller.notificationChannelSend(notification.target, notification.message ? notification.message : this.getInstanceTitle());\n\t}\n};\n\nRules.prototype.getConfigTimeout = function(configTimeout) {\n\treturn !!!configTimeout ? 0 : Math.floor(configTimeout * 1000); // !!! > proof for undefined and null\n};"
  },
  {
    "path": "modules/Rules/lang/de.json",
    "content": "{\n\t\"m_title\":\"Regeln\",\n\t\"m_descr\":\"!!! SOLLTE EVTL AN NEUE FUNKTIONALITÄT ANGEPASST WERDEN... ODER MINDESTENS DEN NAMEN ÜBERALL ANPASSEN !!! Ein oder mehrere Geräte werden immer DANN geschaltet, WENN ein gewähltes Ereignis eingetreten ist. Dieses Ereignis kann das Auslösen eines Bewegungsmelders oder Türkontaktes sein aber auch das Umschalten eines anderen Schaltaktors.\",\n\t\"l_event_sources\":\"Wenn\",\n\t\"l_actors\":\"Dann\",\n\t\"l_notification\":\"Benachrichtigung\",\n\t\"l_delay\":\"Delay\",\n\t\"l_reverse\":\"Umkehr\",\n\t\"l_advanced\":\"Erweiterte Einstellungen\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_level\":\"Level\",\n\t\"level\": \"Setze Level\",\n\t\"open\":\"Öffnen\",\n\t\"close\":\"Schließen\",\n\t\"l_scene\":\"Szene\",\n\t\"switchBinary\":\"Binärschalter\",\n\t\"switchMultilevel\":\"Multilevelschalter\",\n\t\"sensorMultilevel\":\"Multilevelsensor\",\n\t\"doorlock\":\"Türschloss\",\n\t\"thermostat\":\"Thermostat\",\n\t\"l_filter\":\"Filtern nach Typ\",\n\t\"l_target_device\":\"Gerät\",\n\t\"l_action\":\"Aktion\",\n\t\"toggleButton\": \"Schaltsteuerung / Szene (nur An)\",\n\t\"switchControl\": \"Schaltsteuerung (An/Aus/Level)\",\n\t\"sensorBinary\": \"Binärsensor\",\n\t\"l_choose\":\"--- Gerätetyp wählen ---\",\n\t\"l_choose_dev\":\"--- Gerät wählen ---\",\n\t\"l_choose_controller_action\":\"--- Interaktion wählen ---\",\n\t\"l_controller_action\":\"Interaktionen\",\n\t\"h_controller_action\":\"Die Aktion wird als zweistelliger Wert angegeben: Die erste Zahl ist die Nummer des Tasters/der Szene, die zweite Zahl stellt die Aktion des Tasters/der Szene dar (0 = kurz gedrückt, 1 = losgelassen, 2 = gehalten, 3 = 2x kurz gedrückt, 4 = 3x kurz gedrückt, usw. Besispiele: Doppelklick Taste/Szene 2 => 23, Einfachklick Taste/Szene 1 = 10)\",\n\t\"sensorDiscrete\":\"Szenensteuerung\",\n\t\"switchRGBW\":\"Farbsteuerung\",\n\t\"l_red\":\"Rot\",\n\t\"l_green\":\"Grün\",\n\t\"l_blue\":\"Blau\",\n\t\"colors\":\"Farben\",\n\t\"h_color\":\"Wählen Sie einen Wert von 0 - 255\",\n\t\"l_notification_message\":\"Nachricht\",\n\t\"h_notification_message\":\"Inhalt der Benachrichtigung.\",\n\t\"l_notification_target\":\"Ziel\",\n\t\"l_notification_device\":\"Gerät\",\n\t\"l_notification_mail\":\"Email\",\n\t\"l_choose_target\":\"--- Ziel wählen ---\",\n\t\"h_nomail\":\"Aktuell ist keine Benachrichtigung über Email möglich, da die EMailMe-App nicht installiert/aktiviert ist.\",\n\t\"b_createmail\": \"Aktiviere EMailMe\",\n\t\"m_createmail\": \"ACHTUNG!<br />Beim Verlassen des Konfigurationsfensters gehen alle bisherigen Einstellungen verloren.<br /><br />HINWEIS:<br />Sie können mit 'Abbrechen' ohne die Konfiguration der EMailMe-App fortfahren, diese im Nachgang anlegen und anschließend in der Rules-Konfiguration hinzufügen.\",\n\t\"l_sendAction\":\"Sende kein 'An' Kommando, wenn das Gerät bereits aktiviert ist. Das Gleiche gilt für 'Aus'.\",\n\t\"h_sendAction\":\"Verhindert überflüssige Befehle im Netzwerk.\",\n\t\"h_delay\":\"Zeit in Sekunden bis das Then-Ereignis gestartet wird.\",\n\t\"c_reverse\":\"Umkehrevent aktivieren\",\n\t\"c_advanced\":\"Erweiterte Einstellungen Nutzen\",\n\n\t\"rl_options\":\"Prüfe die Regel bei jeder Zustandsänderung eines unter 'Bedingungen' gelisteten Gerätes\",\n\t\"l_eventSource\":\"Führe eine Regelprüfung bei der Aktivierung folgender Szenen durch:\",\n\t\"l_logicalOperator\":\"Logische Verknüpfung\",\n\t\"h_logicalOperator\":\"Diese Option verknüpft alle in der Liste befindlichen Bedingungen mit einem logischen ODER (OR) oder UND (AND). Bei OR wird die Aktion ausgeführt, wenn mindestens eine Bedingung zutrifft. Bei AND wird die Aktion nur ausgeführt, wenn alle Bedingungen zutreffen.\",\n\t\"l_tests\":\"Bedingungen\",\n\t\"l_testBinary\":\"Binäre Schalter/Sensoren\",\n\t\"l_testMultilevel\":\"Dimmer/Motorsteuerung/Analoge Sensoren/Batterien\",\n\t\"l_testRemote\":\"Schaltsteuerung/Szenen\",\n\t\"l_testTime\":\"Zeit\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_testNested\":\"Verschachtelt\",\n\t\"l_logical_action\":\"Aktionen:\",\n\t\"l_switches\":\"Binäre Schalter:\",\n\t\"l_thermostats\":\"Thermostats\",\n\t\"upstart\":\"Aufwärts: start\",\n\t\"upstop\":\"Aufwärts: stop\",\n\t\"downstart\":\"Abwärts: start\",\n\t\"downstop\":\"Abwärts: stop\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerung:\",\n\t\"l_status\":\"Level\",\n\t\"l_locks\":\"Türschlösser\",\n\t\"logical_close\":\"Verriegelt\",\n\t\"logical_open\":\"Entriegelt\",\n\t\"l_scenes\":\"Zu aktivierende Szenen/Aktionen:\",\n\t\"or\": \"Mindestens eine Bedingung wird erfüllt (OR)\",\n\t\"and\": \"Alle Bedingungen müssen erfüllt werden (AND)\",\n\t\"l_testType\": \"Typ der Bedingung:\",\n\t\"h_testNested\": \"Erzeugt weitere verschachtelte Bedingungen - logische Schreibweise: A AND B AND (C OR D). Die zusätzliche verschachtelte Bedingung ist (C OR D). Eine Aktion wird also nur dann ausgelöst, wenn die Bedingungen A und B sowie entweder die Bedingung C oder D gemeinsam erfüllt sind. Beispiel: Wenn außen der Lichtsensor A > 80% und der Temperatursensor B > 26°C und (Zeit < 12:00 Uhr oder Zeit > 14:00 Uhr) dann wird die Jalousie im Wohnzimmer auf 50% gesetzt.\",\n\t\"l_logical_sendAction\":\"Sende kein 'An' Kommando, wenn das Gerät bereits aktiviert ist. Das Gleiche gilt für 'Aus'.\",\n\t\"h_logical_sendAction\":\"Verhindert überflüssige Befehle im Netzwerk.\",\n\t\"h_testTime\":\"Diese Bedingung überprüft, ob die aktuelle Zeit Kleiner-Gleich oder Größer-Gleich der eingegebenen ist. Z.B aktuelle Zeit: 09:00 und Bedingung: >= 10:00 würde ein 'false' zurückliefern und die Regel nicht auslösen. 24-h-Format - hh:mm\",\n\t\"l_triggers\": \"Wie wird die Regel ausgelöst\",\n\t\"l_conditions\": \"Bedingungen zum Auslösen\",\n\t\"p_select\": \" Bitte auswählen\",\n\t\"WrongOperator\": \"Wählen Sie einen gültigen Operator aus\",\n\t\"h_triggerOnDevicesChange\": \"Standardmäßig achtet die logische Regel auf alle Änderungen von Geräten, die unter Bedingungen aufgelistet sind. Wird eine Änderung durch die logische Regel erkannt, wird geprüft, ob eine Aktion ausgelöst werden soll oder nicht. Deaktivieren Sie diese Option, wenn die logische Regel Bedingung nur bei ausgelösten Szenen geprüft werden soll. Es wird empfohlen, dieses Feld in Kombination mit der Option' Regelprüfung bei Aktivierung der folgenden Szenen auslösen' zu verwenden.\",\n\t\"rl_expertSettings\": \"Erweiterte Einstellungen\",\n\t\"h_expertSettings\": \"Hier finden Sie weitere Einstellungen zur Regelprüfung.\"\n}"
  },
  {
    "path": "modules/Rules/lang/en.json",
    "content": "{\n\t\"m_title\":\"Rules\",\n\t\"m_descr\":\"!!! SOLLTE EVTL AN NEUE FUNKTIONALITÄT ANGEPASST WERDEN... ODER MINDESTENS DEN NAMEN ÜBERALL ANPASSEN !!! The If->Then is the foundation of automation. A selected action (WHEN) is executed automatically at the moment when a certain event (IF) has happen. This app allows defining these relationships.  The (IF) event must be a event that happens at one time. Examples for this are a door that is opened (the door sensor trips) or a button that is pressed. A simple switch is also a reasonable source for an event because this switch can be switched. A temperature sensor is NO event in this regard because this sensor will continuously send temperature and not create an event. The event need to have two defines status of ‘0’ and ‘1’ Every binary sensor or switch button has these states. Status=1 will send a Command Set(1) to the list of selected actuators, Status=0 will sen Set(0) to these devices.<br> <br>Settings:<br> <ul><li>Pick the events that shall trigger. You can select multiple events and all of them will trigger the selected action (connected with Logical OR). If you pick a dimmer or a motor control the change to full 100 % will be considered as the event to trigger.</li> <li>Pick the devices that shall be switches depending on the action. Please not that these devices must be able to receive and execute Set(1) and set(0) commands.</li></ul>\",\n\t\"l_event_sources\":\"If\",\n\t\"l_actors\":\"Then\",\n\t\"l_notification\":\"Notification\",\n\t\"l_delay\":\"Delay\",\n\t\"l_reverse\":\"Reverse\",\n\t\"l_advanced\":\"Advanced settings\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_level\":\"Level\",\n\t\"level\": \"Set Level\",\n\t\"open\":\"Open\",\n\t\"close\":\"Close\",\n\t\"logical_open\":\"Open\",\n\t\"logical_close\":\"Close\",\n\t\"l_scene\":\"Scene\",\n\t\"l_filter\":\"Filter by Type\",\n\t\"switchBinary\":\"Binary Switch\",\n\t\"switchMultilevel\":\"Multilevel Switch\",\n\t\"sensorMultilevel\":\"Multilevel Sensor\",\n\t\"doorlock\":\"Doorlock\",\n\t\"thermostat\":\"Thermostat\",\n\t\"l_target_device\":\"Device\",\n\t\"l_action\":\"Action\",\n\t\"toggleButton\": \"Switch Control / Scene (On only)\",\n\t\"switchControl\": \"Switch Control (On/Off/Level)\",\n\t\"sensorBinary\": \"Binary Sensor\",\n\t\"l_choose\":\"--- Choose a device type ---\",\n\t\"l_choose_dev\":\"--- Choose a device ---\",\n\t\"l_choose_controller_action\":\"--- Choose a controller action ---\",\n\t\"l_controller_action\":\"Controller Actions\",\n\t\"h_controller_action\":\"The action is described with a two-digit value: The first digit is the button number, the second digit points to the action of this button (0=short press, 1=release, 2=hold, 3=short press two times, 4 = short press three times, and so on. Examples: Double Click button 2 => 23, Single Click button 1 = 10)\",\n\t\"sensorDiscrete\":\"Scene Controller\",\n\t\"switchRGBW\":\"Color Switch\",\n\t\"l_red\":\"Red\",\n\t\"l_green\":\"Green\",\n\t\"l_blue\":\"Blue\",\n\t\"colors\":\"Colors\",\n\t\"h_color\":\"Choose a value from 0 - 255\",\n\t\"l_notification_message\":\"Message\",\n\t\"h_notification_message\":\"Content of the notification.\",\n\t\"l_notification_target\":\"Target\",\n\t\"l_notification_device\":\"Device\",\n\t\"l_notification_mail\":\"Email\",\n\t\"l_choose_target\":\"--- Choose a target ---\",\n\t\"h_nomail\":\"Currently, no email notification is possible because the EMailMe app is not installed/activated.\",\n\t\"b_createmail\": \"Activate EMailMe\",\n\t\"m_createmail\": \"ATTENTION! <br /> When leaving the current configuration, all previous settings are lost. <br /><br /> NOTE: <br /> You can continue with 'Cancel' without configuring the EMailMe app, create it afterwards, and add it then in the Rules configuration.\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\",\n\t\"h_delay\":\"Time in seconds when event starts after triggering event...\",\n\t\"c_reverse\":\"activate reverse event\",\n\t\"c_advanced\":\"use advanced settings\",\n\n\t\"rl_options\":\"Check the rule for every change of state of a device listed under 'Conditions'.\",\n\t\"l_eventSource\":\"Trigger the rule check on activation of the following scenes:\",\n\t\"l_logicalOperator\":\"Boolean operator\",\n\t\"h_logicalOperator\":\"This option links all conditions in the list to a logical OR or AND. With OR, the action is executed if at least one condition applies. With AND, the action is only executed if all conditions apply.\",\n\t\"l_tests\":\"Conditions\",\n\t\"l_testBinary\":\"Binary condition\",\n\t\"l_testMultilevel\":\"Multilevel condition\",\n\t\"l_testRemote\":\"Remote condition\",\n\t\"l_testTime\":\"Time condition\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_testNested\":\"Nested conditions\",\n\t\"l_logical_action\":\"Actions:\",\n\t\"l_switches\":\"List of switches:\",\n\t\"l_thermostats\":\"Thermostats\",\n\t\"upstart\":\"Up start\",\n\t\"upstop\":\"Up stop\",\n\t\"downstart\":\"Down start\",\n\t\"downstop\":\"Down stop\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_status\":\"Level\",\n\t\"l_locks\":\"List of locks:\",\n\t\"l_scenes\":\"List of scenes to activate:\",\n\t\"or\": \"At least one condition is fulfilled (OR)\",\n\t\"and\": \"All conditions must be met (AND)\",\n\t\"l_testType\": \"Type of condition:\",\n\t\"h_testNested\": \"Add a new nested condition - like in logical notation: A AND B AND (C OR D). The additional nested condition is (C OR D). An action is only triggered if the conditions A and B and either the condition C or D are met together. Example: If outside the light sensor A > 80% and the temperature sensor B > 26°C and (time < 12:00 am or time > 02:00 pm) then the jalousie in the living room is set to 50%.\",\n\t\"l_logical_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off. Need to avoid flooding the network.\",\n\t\"h_logical_sendAction\":\"Prevents unnecessary network commands.\",\n\t\"h_testTime\":\"This condition checks if the current time is 'less than or equal to' or 'greater than or equal to' the entered time. E.g. current time: 09:00 and condition: >= 10:00 will return 'false' and not pass the rule. 24-h-format - hh:mm\",\n\t\"l_triggers\": \"How the Logical Rule is triggered\",\n\t\"l_conditions\": \"What triggers the Logical Rule\",\n\t\"p_select\": \" Please choose\",\n\t\"WrongOperator\": \"Choose a valid operator\",\n\t\"h_triggerOnDevicesChange\": \"By default the logical rule listens to all changes of devices listed in conditions. If a change is recognized by the logical rule it will check the condition wether to trigger an action or not. Deactivate this option if the logical rule condition should only be checked by triggered scenes. It is recommented to use this field in combination with 'Trigger the rule check on activation of the following scenes' option.\",\n\t\"rl_expertSettings\": \"Advanced Settings\",\n\t\"h_expertSettings\": \"Here you can find further settings for the rule check.\",\n\t\"l_sensorDiscrete\":\"Scene Controller\"\n}"
  },
  {
    "path": "modules/Rules/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Если -> Тогда\",\n\t\"m_descr\":\"Ассоциирование устройств с возможностью задать состояния устройств.\",\n\t\"l_event_sources\":\"Если\",\n\t\"l_actors\":\"Тогда\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_level\":\"Уровень\",\n\t\"level\": \"Set Level\",\n\t\"open\":\"Открыть\",\n\t\"close\":\"Закрыть\",\n\t\"l_scene\":\"Сцена\",\n\t\"l_filter\":\"Фильтр по типу\",\n\t\"switchBinary\":\"Выключатель\",\n\t\"switchMultilevel\":\"Диммер\",\n\t\"sensorMultilevel\":\"Multilevel Sensor\",\n\t\"doorlock\":\"Замок\",\n\t\"thermostat\":\"Thermostat\",\n\t\"l_target_device\":\"Устройство\",\n\t\"l_action\":\"Действие\",\n\t\"toggleButton\": \"Кнопка (только Включить)\",\n\t\"switchControl\": \"Кнопка (Включить/Выключить/Level)\",\n\t\"sensorBinary\": \"Бинарный датчик\",\n\t\"l_choose\":\"--- Выберите тип устройства ---\",\n\t\"l_choose_dev\":\"--- Выберите устройство ---\",\n\t\"l_choose_controller_action\":\"--- Choose a controller action ---\",\n\t\"l_controller_action\":\"Controller Actions\",\n\t\"h_controller_action\":\"The action is described with a two-digit value: The first digit is the button number, the second digit points to the action of this button (0=short press, 1=release, 2=hold, 3=short press two times, 4 = short press three times, and so on. Examples: Double Click button 2 => 23, Single Click button 1 = 10)\",\n\t\"sensorDiscrete\":\"Scene Controller\",\n\t\"switchRGBW\":\"Color Switch\",\n\t\"l_red\":\"Красный\",\n\t\"l_green\":\"Зеленый\",\n\t\"l_blue\":\"Синий\",\n\t\"colors\":\"Цвет\",\n\t\"h_color\":\"Выберите значение 0 - 255\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Нужно чтобы не забивать сеть.\",\n\t\"l_notification_message\":\"Message\",\n\t\"h_notification_message\":\"Content of the notification.\",\n\t\"l_notification_target\":\"Target\",\n\t\"l_notification_device\":\"Device\",\n\t\"l_notification_mail\":\"Email\",\n\t\"l_choose_target\":\"--- Choose a target ---\",\n\t\"h_nomail\":\"Currently, no email notification is possible because the EMailMe app is not installed/activated.\",\n\t\"b_createmail\": \"Activate EMailMe\",\n\t\"m_createmail\": \"ATTENTION! <br /> When leaving the current configuration, all previous settings are lost. <br /><br /> NOTE: <br /> You can continue with 'Cancel' without configuring the EMailMe app, create it afterwards, and add it then in the If -> Then configuration.\"\n}"
  },
  {
    "path": "modules/Rules/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"system\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"Rules\",\n\t\"version\": \"1.0.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"simple\": {\n\t\t\t\"triggerEvent\": {},\n\t\t\t\"triggerDelay\": 0,\n\t\t\t\"targetElements\": [],\n\t\t\t\"sendNotifications\": [],\n\t\t\t\"reverseDelay\": 0\n\t\t},\n\t\t\"advanced\": {\n\t\t\t\"active\": false,\n\t\t\t\"triggerScenes\" : [],\n\t\t\t\"triggerDelay\": 0,\n\t\t\t\"logicalOperator\" : \"and\",\n\t\t\t\"tests\" : [],\n\t\t\t\"targetElements\": [],\n\t\t\t\"sendNotifications\": [],\n\t\t\t\"reverseDelay\": 0,\n\t\t\t\"triggerOnDevicesChange\" : true\n\t\t},\n\t\t\"reverse\": false\n\t},\n\t\"schema\": {},\n\t\"options\": {}\n}\n"
  },
  {
    "path": "modules/Rules/patchnotes.txt",
    "content": "v1.0.1\n- support to compare 2 devices\nv1.0.0\n- delay for trigger\n- logical rule features as \"advanced\" feature\n- reverse trigger\n- Basis: If-Then (v2.5.1), LogicalRules (v1.4.1)"
  },
  {
    "path": "modules/Scenes/htdocs/js/postRender.js",
    "content": "function modulePostRender() {\n\tvar icons;\n\t$(document).ready(function() {\n\n\t\t$('.alpaca-fileupload-well').hide();\n\n\t\t$.ajax('/ZAutomation/api/v1/icons')\n\t\t\t.done(function(iconsResponse) {\n\t\t\t\tvar moduleId = parseInt(window.location.href.substring(window.location.href.lastIndexOf(\"/\") + 1));\n\t\t\t\tif (!isNaN(moduleId)) {\n\t\t\t\t\t$.ajax('/ZAutomation/api/v1/instances/' + moduleId)\n\t\t\t\t\t\t.done(function(response) {\n\t\t\t\t\t\t\tif (typeof iconsResponse.data != 'undefined')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ticons = iconsResponse.data;\n\t\t\t\t\t\t\t\t$(\"select[name='icon-select']\").each(function(i,select) {\n\t\t\t\t\t\t\t\t\t$(iconsResponse.data).each(function(n, row){\n\t\t\t\t\t\t\t\t\t\tvar id = $(select).attr('name').split('_')[2];\n\t\t\t\t\t\t\t\t\t\tif ($(select).attr('name').indexOf('customicon') != -1)\n\t\t\t\t\t\t\t\t\t\t\tselected = row.file == response.data.params.customicon.table[id].icon;\n\n\t\t\t\t\t\t\t\t\t\tvar option = $('<option>', {\n\t    \t\t\t\t\t\t\t\t\tvalue: row.file,\n\t    \t\t\t\t\t\t\t\t\ttext: row.orgfile,\n\t    \t\t\t\t\t\t\t\t\tselected: selected\n\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t$(select).append(option);\n\n\t\t\t\t\t\t\t\t\t\tif (selected) {\n\t\t\t\t\t\t\t\t\t\t\t$(select).parent().parent().next('td').find('img').attr('src','user/icons/' + row.file);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tif (typeof iconsResponse.data != 'undefined')\n\t\t\t\t\t{\n\t\t\t\t\t\t$(\"select[name='icon-select']\").each(function(i,select) {\n\t\t\t\t\t\t\tif ($(select).attr('name').indexOf('scene') != -1)\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\ticons = iconsResponse.data;\n\t\t\t\t\t\t\t$(iconsResponse.data).each(function(n, row){\n\t\t\t\t\t\t\t\tvar option = $('<option>', {\n\t\t\t\t\t    \t\t\tvalue: row.file,\n\t\t\t\t\t    \t\t\ttext: row.orgfile,\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t$(select).append(option);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t}\n\t\t\t})\n\t\t\t.fail(function() {\n\t\t\t\tconsole.log('unable to load custom icons');\n\t\t\t});\n\n\t\t$(document).on('click', 'select[name=\"icon-select\"]', function() {\n\t\t\t$(this).parent().parent().next('td').find('img').attr('src','user/icons/' + $(this).val());\n\t\t});\n\n\t\t$(document).ajaxComplete(function( event, xhr, settings ) {\n\t\t\tif (settings.url === '/ZAutomation/api/v1/icons/upload'){\n\t\t\t\t$.ajax('/ZAutomation/api/v1/icons')\n\t\t\t\t\t.done(function(iconsResponse) {\n\t\t\t\t\t\tvar moduleId = parseInt(window.location.href.substring(window.location.href.lastIndexOf(\"/\") + 1));\n\t\t\t\t\t\tif (!isNaN(moduleId)) {\n\t\t\t\t\t\t\t$.ajax('/ZAutomation/api/v1/instances/' + moduleId)\n\t\t\t\t\t\t\t\t.done(function(response) {\n\t\t\t\t\t\t\t\t\tif (typeof iconsResponse.data != 'undefined')\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\ticons = iconsResponse.data;\n\t\t\t\t\t\t\t\t\t\t$(\"select[name='icon-select']\").each(function(i,select) {\n\t\t\t\t\t\t\t\t\t\t\t$(select).empty();\n\t\t\t\t\t\t\t\t\t\t\t$(select).append($('<option>', {\n\t\t\t\t\t\t\t\t\t    \t\tvalue: '',\n\t\t\t\t\t\t\t\t\t    \t\ttext: 'None',\n\t\t\t\t\t\t\t\t\t\t\t}));\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t$(iconsResponse.data).each(function(n, row){\n\t\t\t\t\t\t\t\t\t\t\t\tvar id = $(select).attr('name').split('_')[2];\n\t\t\t\t\t\t\t\t\t\t\t\tif ($(select).attr('name').indexOf('customicon') != -1)\n\t\t\t\t\t\t\t\t\t\t\t\t\tselected = row.file == response.data.params.customicon.table[id].icon;\n\n\t\t\t\t\t\t\t\t\t\t\t\tvar option = $('<option>', {\n\t\t\t    \t\t\t\t\t\t\t\t\tvalue: row.file,\n\t\t\t    \t\t\t\t\t\t\t\t\ttext: row.orgfile,\n\t\t\t    \t\t\t\t\t\t\t\t\tselected: selected\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\t\t\t\t$(select).append(option);\n\n\t\t\t\t\t\t\t\t\t\t\t\tif (selected) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$(select).parent().parent().next('td').find('img').attr('src','user/icons/' + row.file);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (typeof iconsResponse.data != 'undefined')\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t$(\"select[name='icon-select']\").each(function(i,select) {\n\t\t\t\t\t\t\t\t\t$(select).empty();\n\t\t\t\t\t\t\t\t\ticons = iconsResponse.data;\n\t\t\t\t\t\t\t\t\t$(select).append($('<option>', {\n\t\t\t\t\t\t\t    \t\tvalue: '',\n\t\t\t\t\t\t\t    \t\ttext: 'None',\n\t\t\t\t\t\t\t\t\t}));\n\t\t\t\t\t\t\t\t\t$(iconsResponse.data).each(function(n, row){\n\t\t\t\t\t\t\t\t\t\tvar option = $('<option>', {\n\t\t\t\t\t\t\t    \t\t\tvalue: row.file,\n\t\t\t\t\t\t\t    \t\t\ttext: row.orgfile,\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t$(select).append(option);\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.fail(function() {\n\t\t\t\t\t\tconsole.log('unable to load custom icons');\n\t\t\t\t\t});\t\t\t\t\n\t\t\t}\n\t\t});\t\t\n\t});\n};"
  },
  {
    "path": "modules/Scenes/index.js",
    "content": "/*** Scenes Z-Way HA module *******************************************\n\nVersion: 1.2.1\n(c) Z-Wave.Me, 2018\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nChanged: Michael Hensche <mh@zwave.eu>\nChanged: Hans-Christian Göckeritz <hcg@zwave.eu>\nChanged: Niels Roche <nir@z-wave.eu>\nChanged: Karsten Reichel <kar@z-wave.eu>\nDescription:\n\tImplements light scene based on virtual devices of type dimmer, switch or anothe scene\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Scenes(id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tScenes.super_.call(this, id, controller);\n}\n\ninherits(Scenes, AutomationModule);\n\n_module = Scenes;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nScenes.prototype.init = function(config) {\n\tScenes.super_.prototype.init.call(this, config);\n\n\tvar self = this,\n\t\tdevices = _.isArray(this.config.devices) ? this.config.devices : [];\n\t\tnotifications = _.isArray(this.config.notifications) ? this.config.notifications : [];\n\n\t// transform old structure to new\n\tif (typeof self.config.devices === 'object' && !_.isArray(self.config.devices)) {\n\n\t\t// concat all lists to one\n\t\tObject.keys(self.config.devices).forEach(function(key) {\n\t\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes\n\t\t\t\t{\n\t\t\t\t    deviceId: '',\n\t\t\t\t    deviceType: '',\n\t\t\t\t    level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t\t    sendAction: true || false >> don't do this if level is already triggered\n\t\t\t\t}\n\t\t\t*/\n\t\t\tself.config.devices[key].forEach(function(entry) {\n\t\t\t\tvar vDev = null;\n\t\t\t\tif (entry.device || (key === 'scenes' && entry)) {\n\t\t\t\t\tif (key === 'scenes') {\n\t\t\t\t\t\tdevices.push({\n\t\t\t\t\t\t\tdeviceId: entry,\n\t\t\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\t\t\tlevel: 'on'\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvDev = self.controller.devices.get(entry.device);\n\n\t\t\t\t\t\tdevices.push({\n\t\t\t\t\t\t\tdeviceId: entry.device,\n\t\t\t\t\t\t\tdeviceType: vDev ? vDev.get('deviceType') : '',\n\t\t\t\t\t\t\tlevel: entry.status && entry.status != 'level' ? entry.status : (entry.status === 'level' && entry.level ? entry.level : 0),\n\t\t\t\t\t\t\tsendAction: entry.sendAction || false\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\t// overwrite config devices list\n\t\tself.config.devices = _.uniq(devices);\n\n\t\t//save into config\n\t\tself.saveConfig();\n\t}\n\n\tself.vDev = self.controller.devices.create({\n\t\tdeviceId: \"Scenes_\" + self.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"toggleButton\",\n\t\t\tcustomIcons: {\n\t\t\t\t\"default\": self.config.customIcon.table[0].icon\n\t\t\t},\n\t\t\tmetrics: {\n\t\t\t\tlevel: \"on\", // it is always on, but usefull to allow bind\n\t\t\t\ticon: \"scene\",\n\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function(command) {\n\t\t\tif (command !== 'on') return;\n\n\t\t\tdevices.forEach(function(el) {\n\t\t\t\tself.shiftDevice(el);\n\t\t\t});\n\n\t\t\tnotifications.forEach(function(n) {\n\t\t\t\tif (n.target && n.target !== '') {\n\t\t\t\t\tself.controller.notificationChannelSend(n.target, n.message ? n.message : self.getInstanceTitle());\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// update on ourself to allow catch this event\n\t\t\tself.vDev.set(\"metrics:level\", \"on\");\n\t\t},\n\t\tmoduleId: self.id\n\t});\n};\n\nScenes.prototype.stop = function() {\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tScenes.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------"
  },
  {
    "path": "modules/Scenes/lang/de.json",
    "content": "{\n\t\"m_title\":\"Szene\",\n\t\"m_descr\":\"Die Lichtszene ist eine Basisfunktion des Smart Home. Mit nur einem Klick werden mehrere Geräte in einen individuellen Status geschalten. In Verwendung weiterer Apps wie “Delayed Scene” oder “Scheduled Scene” kann diese Szene automatisch in Abhängigkeit von generierten Ereignissen im Smart Home aktiviert werden. Die App erstellt ein neues Element zur Szenenauslösung. Der Einstelldialog ermöglicht die Auswahl von mehreren Schaltern und Dimmern sowie die Definition des gewünschten Schaltzustands eines jeden ausgewählten Gerätes.Desweiteren ist es möglich, andere Szenen als Teil dieser Szene auszulösen.Bitte beachten Sie, dass Dimmer einen Wert zwischen ‘0‘ und ‘100‘ bedürfen, während dessen bei Schaltungen zwischen ‘an‘ und ‘aus‘ gewählt wird. <br><br>Einstellungen:<br><ul><li>Wählen Sie alle Schalter, die zur Szene gehören sollen und definierten Sie den Schaltstatus als ‘an’ oder ‘aus’.</li><li>Wählen Sie alle Dimmer, die zur Szene gehören sollen und definieren Sie den Dimmpegel als einen Wert zwischen 0 und 100.</li><li>Auf Wunsch wählen Sie weitere Szenen, die mit dieser Szene ausgelöst werden sollen.</li></ul><br>Anwendung: Der Button auf dem Szenenelement aktiviert die definierte Szene. \",\n\t\"l_switches\":\"Schalter:\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerungen:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"Aktionen/Szenen die aktiviert werden sollen:\",\n\t\"l_thermostats\":\"Thermostate\",\n\t\"l_temperature\":\"Temperatur\",\n\t\"l_locks\":\"Türschlösser\",\n\t\"close\":\"Verriegelt\",\n\t\"open\":\"Entriegelt\",\n\t\"l_icon\":\"Benutzerdefinierter Icon\",\n\t\"t_icon\":\"Icon\",\n\t\"t_preview\":\"Icon Vorschau\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\",\n\t\"l_files\":\"Icon hochladen\",\n\t\"h_files\":\"Laden Sie weitere Icons hoch. Diese werden nach erfolgreichem Upload automatisch in den Auswahlfeldern gelistet.\"\n}"
  },
  {
    "path": "modules/Scenes/lang/en.json",
    "content": "{\n\t\"m_title\":\"Scene\",\n\t\"m_descr\":\"The scene is a basic function of a smart home. Multiple devices are switched into individual status by just one click. Using other apps like “Delayed Scene” or “Scheduled Scene” this scene can also be activated automatically depending on events generated in the Smart Home.  The app will create a new element to triggering the scene. The setup dialog allows selecting a series of switches and dimmers and defining the desired switching state of each individual device selected. Additionally it is possible to trigger other scenes as part of the scene. Please note that dimmers require a value between 0 and 100, while the switches can be selected between on and off.<br><br>Setup:<br><ul><li>Select all switches that shall belong to the scene and define the switching state as ‘on’ or ‘off’</li><li>Select all dimmers that shall belong to the scene and define the dimming level as a value between 0 und 100</li><li>Optionally select other scenes that shall be trigger with this scene.</li></ul><br>Usage: The toggle button on the scene element will activate the defined scene\",\n\t\"l_switches\":\"List of switches:\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"List of scenes to activate:\",\n\t\"l_thermostats\":\"List of thermostats\",\n\t\"l_temperature\":\"Temperature\",\n\t\"l_locks\":\"List of locks:\",\n\t\"close\":\"Close\",\n\t\"open\":\"Open\",\n\t\"l_icon\":\"Custom icon\",\n\t\"t_icon\":\"Icon\",\n\t\"t_preview\":\"Icon Preview\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\",\n\t\"l_files\":\"Upload Icon\",\n\t\"h_files\":\"Upload additional icons. They will show up directly in the dropdown fields.\"\n}"
  },
  {
    "path": "modules/Scenes/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Сцена\",\n\t\"m_descr\":\"В сцене можно задать уровень освещения, включить или выключить лампы, открыть или закрыть жалюзи, задать температуру для термостатов.\",\n\t\"l_switches\":\"Список выключателей\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_dimmers\":\"Список диммеров\",\n\t\"l_level\":\"Уровень\",\n\t\"l_scenes\":\"Список сцен\",\n\t\"l_thermostats\":\"Список термостатов\",\n\t\"l_temperature\":\"Температура\",\n\t\"l_locks\":\"Список замков\",\n\t\"close\":\"Закрыть\",\n\t\"open\":\"Открыть\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Нужно чтобы не забивать сеть.\"\n}"
  },
  {
    "path": "modules/Scenes/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"system\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"Scenes\",\n\t\"version\": \"1.2.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"devices\": [],\n\t\t\"customIcon\": {\n\t\t\t\"table\": [{\n\t\t\t\t\"icon\": \"\"\n\t\t\t}]\n\t\t}\n\t},\n\t\"schema\": {},\n\t\"options\": {}\n}"
  },
  {
    "path": "modules/Scenes/patchnotes.txt",
    "content": "v1.2.1\n- added notifications\n\nv1.1.2\n- customer icon for widget available\n\nv1.1.1\n- change icon type form gesture to new icon type scene\n"
  },
  {
    "path": "modules/ScheduledScene/htdocs/js/postRender.js",
    "content": "function modulePostRender(control) {\n    if(window.location.href.indexOf(\"post\") > -1) {\n\t    $('#title').val(getWeekArray() + ': ' + $('input[name=times_0]').val());\n\n        $(document).on(\"click\", \"input[type=checkbox]\", function() {\n            $('#title').val(getWeekArray() + ': ' + $('input[name=times_0]').val());\n        });\n\n        $(document).on(\"blur\", \"input[name=times_0]\", function() {\n            $('#title').val(getWeekArray() + ': ' + $('input[name=times_0]').val());\n        })        \n    }\n}\n\nfunction getWeekArray() {\n    var weekdays = ['Su', 'Mo', 'Tue', 'Wed', 'Thu', 'Fr', 'Sa'];\n    var elem = ($('div[data-alpaca-field-name=weekdays]'))[0].children,\n        lday = -1,\n        a_week = [],\n        a_week_counter = 0;\n\n    for(var i = 0, len = elem.length; i<len; i++) {\n        var check = $(elem[i]).find(\"input\"),\n            day = parseInt($(check).attr('data-checkbox-value'));\n\n        if($(check).is(':checked')) {\n            if(lday === -1) {\n                a_week[a_week_counter++] = weekdays[day];\n                lday = day;\n                continue;\n            }\n            if((lday + 1) === day || (lday - 6) === day) {\n                a_week[a_week_counter] = '-' + weekdays[day];\n            } else {\n                a_week_counter++;\n                a_week[a_week_counter++] = ',' + weekdays[day];\n            }\n            lday = day;\n        }\n    };\n    return a_week.join(\"\");\n}"
  },
  {
    "path": "modules/ScheduledScene/index.js",
    "content": "/*** ScheduledScene Z-Way HA module *******************************************\n\nVersion: 2.2.2\n(c) Z-Wave.Me, 2018\n-----------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>, Niels Roche <nir@zwave.eu>, Yurkin Vitaliy <aivs@z-wave.me>\nAuthor: Hans-Christian Göckeritz <hcg@zwave.eu>\nDescription:\n\tThis executes scene by cron\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction ScheduledScene (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tScheduledScene.super_.call(this, id, controller);\n}\n\ninherits(ScheduledScene, AutomationModule);\n\n_module = ScheduledScene;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nScheduledScene.prototype.init = function (config) {\n\tScheduledScene.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t/**** TRANSFORM OLD CONFIG FROM 2.1.2 TO 2.2.1 VERSION ****/\n\tvar needToSaveConfig = false;\n\n\tif (self.config.switches) {\n\t\tself.config.devices.switches = self.config.switches;\n\t\tdelete self.config.switches;\n\t\tneedToSaveConfig = true;\n\t}\n\tif (self.config.dimmers) {\n\t\tself.config.devices.dimmers = self.config.dimmers;\n\t\tdelete self.config.dimmers;\n\t\tneedToSaveConfig = true;\n\t}\n\tif (self.config.thermostats) {\n\t\tself.config.devices.thermostats = self.config.thermostats;\n\t\tdelete self.config.thermostats;\n\t\tneedToSaveConfig = true;\n\t}\n\tif (self.config.scenes) {\n\t\tself.config.devices.scenes = self.config.scenes;\n\t\tdelete self.config.scenes;\n\t\tneedToSaveConfig = true;\n\t}\n\tif (self.config.locks) {\n\t\tself.config.devices.locks = self.config.locks;\n\t\tdelete self.config.locks;\n\t\tneedToSaveConfig = true;\n\t}\n\tif (self.config.time) {\n\t\tself.config.times = [];\n\t\tself.config.times.push(self.config.time);\n\t\tdelete self.config.time;\n\t\tneedToSaveConfig = true;\n\t}\n\tif (needToSaveConfig) {\n\t\tself.saveConfig();\n\t}\n\t/***********************************************************/\n\n\tthis.runScene = function() {\n\t\tvar switchesArray;\n\t\tif (_.isArray(self.config.devices.switches)) {\n\t\t\tswitchesArray = self.config.devices.switches;\n\t\t}\n\n\t\tif (switchesArray) {\n\t\t\tswitchesArray.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar thermostatsArray;\n\t\tif (_.isArray(self.config.devices.thermostats)) {\n\t\t\tthermostatsArray = self.config.devices.thermostats;\n\t\t}\n\n\t\tif (thermostatsArray) {\n\t\t\tthermostatsArray.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar dimmersArray;\n\t\tif (_.isArray(self.config.devices.dimmers)) {\n\t\t\tdimmersArray = self.config.devices.dimmers;\n\t\t}\n\n\t\tif (dimmersArray) {\n\t\t\tdimmersArray.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar locksArray;\n\t\tif (_.isArray(self.config.devices.locks)) {\n\t\t\tlocksArray = self.config.devices.locks;\n\t\t}\n\n\t\tif (locksArray) {\n\t\t\tlocksArray.forEach(function(devState) {\n\t\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tif (!devState.sendAction || (devState.sendAction && vDev.get(\"metrics:level\") != devState.status)) {\n\t\t\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tvar scenesArray;\n\t\tif (_.isArray(self.config.devices.scenes)) {\n\t\t\tscenesArray = self.config.devices.scenes;\n\t\t}\n\n\t\tif (scenesArray) {\n\t\t\tscenesArray.forEach(function(scene) {\n\t\t\t\tvar vDev = self.controller.devices.get(scene);\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\n\t// set up cron handler\n\tthis.controller.on(\"scheduledScene.run.\"+self.id, this.runScene);\n\n\t// add cron schedule\n\tvar wds = this.config.weekdays.map(function(x) { return parseInt(x, 10); });\n\t\n\tif (wds.length == 7) {\n\t\twds = [null]; // same as all - hack to add single cron record. NB! changes type of wd elements from integer to null\n\t}\n\n\twds.forEach(function(wd) {\n\t\tif (_.isArray(self.config.times)) {\n\t\t\tself.config.times.forEach(function(time) {\n\t\t\t\tself.controller.emit(\"cron.addTask\", \"scheduledScene.run.\"+self.id, {\n\t\t\t\t\tminute: parseInt(time.split(\":\")[1], 10),\n\t\t\t\t\thour: parseInt(time.split(\":\")[0], 10),\n\t\t\t\t\tweekDay: wd,\n\t\t\t\t\tday: null,\n\t\t\t\t\tmonth: null\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t});\n};\n\nScheduledScene.prototype.stop = function () {\n\tScheduledScene.super_.prototype.stop.call(this);\n\n\tthis.controller.emit(\"cron.removeTask\", \"scheduledScene.run.\"+this.id);\n\tthis.controller.off(\"scheduledScene.run.\"+this.id, this.runScene);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/ScheduledScene/lang/de.json",
    "content": "{\n\t\"m_title\":\"Zeitplan\",\n\t\"m_descr\":\"Diese App löst zu einer festgelegten Zeit einmal an ausgewählten Wochentagen eine bestimmte Szene aus.  <br><br>Einstellungen:<br><ul><li>Wählen Sie Tageszeit.</li><li>Wählen Sie die Wochentage, an denen die Szene ausgeführt werden soll.</li><li>Wählen Sie eine vordefinierte Szene. Eine solche Szene muss in Verwendung mit der App „Szene“ definiert werden.</li></ul>\",\n\t\"monday\":\"Montag\",\n\t\"tuesday\":\"Dienstag\",\n\t\"wednesday\":\"Mittwoch\",\n\t\"thursday\":\"Donnerstag\",\n\t\"friday\":\"Freitag\",\n\t\"saturday\":\"Samstag\",\n\t\"sunday\":\"Sonntag\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_switches\":\"Schalter:\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_times\":\"Zeiten\",\n\t\"l_devices\":\"Geräte und Szenen\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerungen:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"Aktionen/Szenen die aktiviert werden sollen:\",\n\t\"l_thermostats\":\"Thermostate\",\n\t\"l_temperature\":\"Temperatur\",\n\t\"l_locks\":\"Türschlösser\",\n\t\"close\":\"Verriegelt\",\n\t\"open\":\"Entriegelt\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/ScheduledScene/lang/en.json",
    "content": "{\n\t\"m_title\":\"Schedule\",\n\t\"m_descr\":\"This app allow to control relays, dimmers, thermostats and scenes on a schedule.<br><br>Settings:<br><ul><li>Pick the time of day</li><li>Pick the week days the scene shall be executed</li><li>Pick a predefined scene. Such a scene need to be defined using the app “Scene”</li></ul>\",\n\t\"monday\":\"Monday\",\n\t\"tuesday\":\"Tuesday\",\n\t\"wednesday\":\"Wednesday\",\n\t\"thursday\":\"Thursday\",\n\t\"friday\":\"Friday\",\n\t\"saturday\":\"Saturday\",\n\t\"sunday\":\"Sunday\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_switches\":\"List of switches:\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_times\":\"Times\",\n\t\"l_devices\":\"Devices and scenes\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"List of scenes to activate:\",\n\t\"l_thermostats\":\"List of thermostats\",\n\t\"l_temperature\":\"Temperature\",\n\t\"l_locks\":\"List of locks:\",\n\t\"close\":\"Close\",\n\t\"open\":\"Open\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/ScheduledScene/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Расписание\",\n\t\"m_descr\":\"Включение/выключение по расписанию диммеров, реле, термостатов, сцен.\",\n\t\"monday\":\"Понедельник\",\n\t\"tuesday\":\"Вторник\",\n\t\"wednesday\":\"Среда\",\n\t\"thursday\":\"Четверг\",\n\t\"friday\":\"Пятница\",\n\t\"saturday\":\"Суббота\",\n\t\"sunday\":\"Воскресенье\",\n\t\"timeFormat\":\"чч:мм\",\n\t\"l_switches\":\"Список выключателей\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_times\":\"Время\",\n\t\"l_devices\":\"Устройства и сцены\",\n\t\"l_dimmers\":\"Список диммеров\",\n\t\"l_level\":\"Уровень\",\n\t\"l_scenes\":\"Список сцен\",\n\t\"l_thermostats\":\"Список термостатов\",\n\t\"l_temperature\":\"Температура\",\n\t\"l_locks\":\"Список замков\",\n\t\"close\":\"Закрыть\",\n\t\"open\":\"Открыть\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Нужно чтобы не забивать сеть.\"\n}"
  },
  {
    "path": "modules/ScheduledScene/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"ScheduledScene\",\n\t\"version\": \"2.2.2\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"weekdays\": [1, 2, 3, 4, 5, 6, 0],\n\t\t\"times\": [\"00:00\",\"12:00\"],\n\t\t\"devices\": {\n\t\t\t\"switches\": [],\n\t\t\t\"dimmers\": [],\n\t\t\t\"thermostats\": [],\n\t\t\t\"scenes\": []\n\t\t}\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"weekdays\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"enum\": [1, 2, 3, 4, 5, 6, 0],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"times\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"time\": {\n\t\t\t\t\t\t\t   \"format\":\"time\",\n\t\t\t\t\t\t\t   \"required\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"devices\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"switches\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dimmers\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"thermostats\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_thermostat:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"locks\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"enum\": [\"close\", \"open\"],\n\t\t\t\t\t\t\t\t\t\"default\" : \"open\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scenes\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"weekdays\": {\n\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\"optionLabels\": [\"__monday__\", \"__tuesday__\", \"__wednesday__\", \"__thursday__\", \"__friday__\", \"__saturday__\", \"__sunday__\"]\n\t\t\t},\n\t\t\t\"times\": {\n\t\t\t\t\"label\": \"__l_times__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"time\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"time\",\n\t\t\t\t\t\t\t\t\t\"maskString\": \"99:99\",\n\t\t\t\t\t\t\t\t\t\"dateFormat\": \"HH:mm\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"devices\": {\n\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"switches\": {\n\t\t\t\t\t\t\"label\": \"__l_switches__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\"]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dimmers\": {\n\t\t\t\t\t\t\"label\": \"__l_dimmers__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_level__\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"thermostats\": {\n\t\t\t\t\t\t\"label\": \"__l_thermostats__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_thermostat:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_temperature__\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"locks\": {\n\t\t\t\t\t\t\"label\": \"__l_locks__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__close__\", \"__open__\"]\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"sendAction\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\t\t\t\t\"rightLabel\": \"__l_sendAction__\",\n\t\t\t\t\t\t\t\t\t\t\"helper\": \"__h_sendAction__\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scenes\": {\n\t\t\t\t\t\t\"label\": \"__l_scenes__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"postRender\": \"loadFunction:postRender.js\"\n}\n"
  },
  {
    "path": "modules/ScheduledScene/patchnotes.txt",
    "content": "v2.1.1\n- format of time input field changed (HH:mm 24h)\n\nv2.2\n- can start scene many times in day\n- defined default times: 00:00 and 12:00\n- devices on new path, as example switch: this.config.devices.swithes\n- compatibility with old config\n\nv2.2.1\n- scenes only show scenes and no mobile devices and email addresses\n- dynamic defaultname"
  },
  {
    "path": "modules/Schedules/htdocs/js/postRender.js",
    "content": "function modulePostRender(control) {\n    if(window.location.href.indexOf(\"put\") > -1) {\n        var row = \"<p><button class='btn btn-success' type='button' id='testbutton'>TEST</button></p>\";\n        $(row).insertAfter('#active');\n    }\n\n    $(document).on(\"click\", \"#testbutton\", function() {\n        l = document.createElement(\"a\");\n        l.href = window.location.href;\n        id = l.hash.split(\"/\");\n\n        $.ajax({\n            url: 'http://' + l.host + '/JS/Run/controller.emit(\"scheduledScene.run.' + id[3] + '\")'\n        }).success( function() {\n            alert('Current schedule test completed!');\n        });\n    });\n\n/* part of normal ScheduledScene */\n/*\n    if( $('input[name=title]').val() === 'Schedule')\n\t{\n\t    week = getWeekArray();\n\t    $('#title').val(week + ': ' + $('input[name=times_0]').val());\n    }\n\n    $(document).on(\"click\", \"input[type=checkbox]\", function() {\n        if(window.location.href.indexOf(\"post\") > -1) {\n            week = getWeekArray();\n            $('#title').val(week + ': ' + $('input[name=times_0]').val());\n\t    }\n    });\n\n    $(document).on(\"blur\", \"input[name=times_0]\", function() {\n        if(window.location.href.indexOf(\"post\") > -1) {\n            week = getWeekArray();\n            $('#title').val(week + ': ' + $('input[name=times_0]').val());\n\t    }\n    });\n*/\n}\n\n/*\nfunction getWeekArray() {\n    var weekdays = ['Su', 'Mo', 'Tue', 'Wed', 'Thu', 'Fr', 'Sa'];\n    var elem = ($('div[data-alpaca-field-name=weekdays]'))[0].children,\n        lday = -1,\n        a_week = [],\n        a_week_counter = 0;\n\n    for(var i = 0, len = elem.length; i<len; i++) {\n        var check = $(elem[i]).find(\"input\"),\n            day = parseInt($(check).attr('data-checkbox-value'));\n\n        if($(check).is(':checked')) {\n            if(lday === -1) {\n                a_week[a_week_counter++] = weekdays[day];\n                lday = day;\n                continue;\n            }\n            if((lday + 1) === day || (lday - 6) === day) {\n                a_week[a_week_counter] = '-' + weekdays[day];\n            } else {\n                a_week_counter++;\n                a_week[a_week_counter++] = ',' + weekdays[day];\n            }\n            lday = day;\n        }\n    };\n    return a_week.join(\"\");\n}\n*/\n"
  },
  {
    "path": "modules/Schedules/index.js",
    "content": "/*** Schedules Z-Way HA module *******************************************\n\nVersion: 1.1.1\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>, Niels Roche <nir@zwave.eu>, Yurkin Vitaliy <aivs@z-wave.me>\nAuthor: Hans-Christian Göckeritz <hcg@zwave.eu>\nChanged: Karsten Reichel <kar@z-wave.eu>\nDescription:\n\tThis executes scene by cron\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Schedules(id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSchedules.super_.call(this, id, controller);\n}\n\ninherits(Schedules, AutomationModule);\n\n_module = Schedules;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSchedules.prototype.init = function(config) {\n\tSchedules.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.devices = _.isArray(this.config.devices) ? this.config.devices : [];\n\tthis.notifications = _.isArray(this.config.notifications) ? this.config.notifications : [];\n\n\t/*old = {\n\t\t\"switches\": [],\n\t\t\"dimmers\": [],\n\t\t\"thermostats\": [],\n\t\t\"scenes\": []\n\t}*/\n\n\t// transform old structure to new\n\tif (typeof self.config.devices === 'object' && !_.isArray(self.config.devices)) {\n\n\t\t// concat all lists to one\n\t\tObject.keys(self.config.devices).forEach(function(key) {\n\t\t\t/* transform each single entry to the new format: switches, thermostats, dimmers, locks, scenes\n\t\t\t\t{\n\t\t\t\t    deviceId: '',\n\t\t\t\t    deviceType: '',\n\t\t\t\t    level: '', // color: { r: 0, g: 0, b: 0}, on, off, open, close, color\n\t\t\t\t    sendAction: true || false >> don't do this if level is already triggered\n\t\t\t\t}\n\t\t\t*/\n\t\t\tself.config.devices[key].forEach(function(entry) {\n\t\t\t\tvar vDev = null;\n\t\t\t\tif (entry.device || (key === 'scenes' && entry)) {\n\t\t\t\t\tif (key === 'scenes') {\n\t\t\t\t\t\tself.devices.push({\n\t\t\t\t\t\t\tdeviceId: entry,\n\t\t\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\t\t\tlevel: 'on'\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvDev = self.controller.devices.get(entry.device);\n\n\t\t\t\t\t\tself.devices.push({\n\t\t\t\t\t\t\tdeviceId: entry.device,\n\t\t\t\t\t\t\tdeviceType: vDev ? vDev.get('deviceType') : '',\n\t\t\t\t\t\t\tlevel: entry.status && entry.status != 'level' ? entry.status : (entry.status === 'level' && entry.level ? entry.level : 0),\n\t\t\t\t\t\t\tsendAction: entry.sendAction || false\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\n\t\t// overwrite config devices list\n\t\tself.devices = _.uniq(self.devices);\n\t\tself.config.devices = self.devices;\n\n\t\t//save into config\n\t\tself.saveConfig();\n\t}\n\n\tself.runScene = function() {\n\n\t\tself.devices.forEach(function(el) {\n\t\t\tself.shiftDevice(el);\n\t\t});\n\n\t\tself.notifications.forEach(function(n) {\n\t\t\tif (n.target && n.target !== '') {\n\t\t\t\tself.controller.notificationChannelSend(n.target, n.message ? n.message : self.getInstanceTitle());\n\t\t\t}\n\t\t});\n\t};\n\n\t// set up cron handler\n\tself.controller.on(\"scheduledScene.run.\" + self.id, self.runScene);\n\n\t// add cron schedule\n\tvar wds = self.config.weekdays.map(function(x) {\n\t\treturn parseInt(x, 10);\n\t});\n\n\tif (wds.length == 7) {\n\t\twds = [null]; // same as all - hack to add single cron record. NB! changes type of wd elements from integer to null\n\t}\n\n\twds.forEach(function(wd) {\n\t\tvar times = _.isArray(self.config.times) ? self.config.times : [self.config.times];\n\t\ttimes.forEach(function(time) {\n\t\t\tself.controller.emit(\"cron.addTask\", \"scheduledScene.run.\" + self.id, {\n\t\t\t\tminute: parseInt(time.split(\":\")[1], 10),\n\t\t\t\thour: parseInt(time.split(\":\")[0], 10),\n\t\t\t\tweekDay: wd,\n\t\t\t\tday: null,\n\t\t\t\tmonth: null\n\t\t\t});\n\t\t});\n\t});\n};\n\nSchedules.prototype.stop = function() {\n\tSchedules.super_.prototype.stop.call(this);\n\n\tthis.controller.emit(\"cron.removeTask\", \"scheduledScene.run.\" + this.id);\n\tthis.controller.off(\"scheduledScene.run.\" + this.id, this.runScene);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/Schedules/lang/de.json",
    "content": "{\n\t\"m_title\":\"Zeitplan\",\n\t\"m_descr\":\"Diese App löst zu einer festgelegten Zeit einmal an ausgewählten Wochentagen eine bestimmte Szene aus.  <br><br>Einstellungen:<br><ul><li>Wählen Sie Tageszeit.</li><li>Wählen Sie die Wochentage, an denen die Szene ausgeführt werden soll.</li><li>Wählen Sie eine vordefinierte Szene. Eine solche Szene muss in Verwendung mit der App „Szene“ definiert werden.</li></ul>\",\n\t\"monday\":\"Montag\",\n\t\"tuesday\":\"Dienstag\",\n\t\"wednesday\":\"Mittwoch\",\n\t\"thursday\":\"Donnerstag\",\n\t\"friday\":\"Freitag\",\n\t\"saturday\":\"Samstag\",\n\t\"sunday\":\"Sonntag\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_switches\":\"Schalter:\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_times\":\"Zeiten\",\n\t\"l_devices\":\"Geräte und Szenen\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerungen:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"Aktionen/Szenen die aktiviert werden sollen:\",\n\t\"l_thermostats\":\"Thermostate\",\n\t\"l_temperature\":\"Temperatur\",\n\t\"l_locks\":\"Türschlösser\",\n\t\"close\":\"Verriegelt\",\n\t\"open\":\"Entriegelt\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/Schedules/lang/en.json",
    "content": "{\n\t\"m_title\":\"Schedule\",\n\t\"m_descr\":\"This app allow to control relays, dimmers, thermostats and scenes on a schedule.<br><br>Settings:<br><ul><li>Pick the time of day</li><li>Pick the week days the scene shall be executed</li><li>Pick a predefined scene. Such a scene need to be defined using the app “Scene”</li></ul>\",\n\t\"monday\":\"Monday\",\n\t\"tuesday\":\"Tuesday\",\n\t\"wednesday\":\"Wednesday\",\n\t\"thursday\":\"Thursday\",\n\t\"friday\":\"Friday\",\n\t\"saturday\":\"Saturday\",\n\t\"sunday\":\"Sunday\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_switches\":\"List of switches:\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_times\":\"Times\",\n\t\"l_devices\":\"Devices and scenes\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_level\":\"Level\",\n\t\"l_scenes\":\"List of scenes to activate:\",\n\t\"l_thermostats\":\"List of thermostats\",\n\t\"l_temperature\":\"Temperature\",\n\t\"l_locks\":\"List of locks:\",\n\t\"close\":\"Close\",\n\t\"open\":\"Open\",\n\t\"l_sendAction\":\"Don't send On command, if device is already turned On, similarly for Off\",\n\t\"h_sendAction\":\"Need to avoid flooding the network.\"\n}"
  },
  {
    "path": "modules/Schedules/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Расписание\",\n\t\"m_descr\":\"Включение/выключение по расписанию диммеров, реле, термостатов, сцен.\",\n\t\"monday\":\"Понедельник\",\n\t\"tuesday\":\"Вторник\",\n\t\"wednesday\":\"Среда\",\n\t\"thursday\":\"Четверг\",\n\t\"friday\":\"Пятница\",\n\t\"saturday\":\"Суббота\",\n\t\"sunday\":\"Воскресенье\",\n\t\"timeFormat\":\"чч:мм\",\n\t\"l_switches\":\"Список выключателей\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_times\":\"Время\",\n\t\"l_devices\":\"Устройства и сцены\",\n\t\"l_dimmers\":\"Список диммеров\",\n\t\"l_level\":\"Уровень\",\n\t\"l_scenes\":\"Список сцен\",\n\t\"l_thermostats\":\"Список термостатов\",\n\t\"l_temperature\":\"Температура\",\n\t\"l_locks\":\"Список замков\",\n\t\"close\":\"Закрыть\",\n\t\"open\":\"Открыть\",\n\t\"l_sendAction\":\"Не отправлять команду ВКЛ, если устройство уже включено, аналогично для ВЫКЛ\",\n\t\"h_sendAction\":\"Нужно чтобы не забивать сеть.\"\n}"
  },
  {
    "path": "modules/Schedules/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"category\": \"system\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\": \"Schedules\",\n\t\"version\": \"1.1.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"weekdays\": [1, 2, 3, 4, 5, 6, 0],\n\t\t\"times\": [\"00:00\", \"12:00\"],\n\t\t\"devices\": []\n\t},\n\t\"schema\": {},\n\t\"options\": {}\n}"
  },
  {
    "path": "modules/Schedules/patchnotes.txt",
    "content": "v1.1.1\n- added notification\n\nv1.0.1\n- Button to test schedule\n- BugFix show mobile devices and email addresses in scene select\n\nv1.0.0\n- clone and rework from \"ScheduledScene\""
  },
  {
    "path": "modules/Security/htdocs/js/postRender.js",
    "content": "function modulePostRender(control) {\n\tvar id = 0;\n\tvar notificationSilentAlarm, notificationAlarm, notificationArm, notificationDisarm, notificationClean;\n\n\tnotificationSilentAlarm = control.childrenByPropertyId[\"silentAlarms\"].children[1];\n\tnotificationAlarm = control.childrenByPropertyId[\"alarms\"].children[1];\n\tnotificationArm = control.childrenByPropertyId[\"armConfirm\"].children[1];\n\tnotificationDisarm = control.childrenByPropertyId[\"disarmConfirm\"].children[1];\n\tnotificationClean = control.childrenByPropertyId[\"clean\"].children[1];\n\n\tif (typeof notificationSilentAlarm !== 'undefined' && typeof notificationAlarm !== 'undefined' && typeof notificationArm !== 'undefined'  && typeof notificationDisarm !== 'undefined' && typeof notificationClean !== 'undefined' ) {\n\t\t$.ajax(\"/ZAutomation/api/v1/instances/MailNotifier\")\n\t\t\t.done(function (response) {\n\t\t\t\tif (typeof response.data[0].active !== 'undefinded' && response.data[0].active === true) {\n\t\t\t\t\t$.ajax(\"/ZAutomation/api/v1/profiles\")\n\t\t\t\t\t\t.done(function (profilesResponse) {\n\t\t\t\t\t\t\tvar moduleId = parseInt(window.location.href.substring(window.location.href.lastIndexOf(\"/\") + 1));\n\n\t\t\t\t\t\t\tif (!isNaN(moduleId)) {\n\t\t\t\t\t\t\t\t$.ajax(\"/ZAutomation/api/v1/instances/\" + moduleId)\n\t\t\t\t\t\t\t\t\t.done(function (response) {\n\t\t\t\t\t\t\t\t\t\tif (typeof response.data.params.silentAlarms.notification !== 'undefinded') {\n\t\t\t\t\t\t\t\t\t\t\tvar mail = response.data.params.silentAlarms.notification.target;\n\t\t\t\t\t\t\t\t\t\t\tif (typeof mail !== 'undefined' && mail.search('@') > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, mail, 0);\n\t\t\t\t\t\t\t\t\t\t\t} else if (typeof response.data.params.silentAlarms.notification.mail_to_input === 'undefined') {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 0);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (typeof response.data.params.alarms.notification !== 'undefinded') {\n\t\t\t\t\t\t\t\t\t\t\tvar mail = response.data.params.alarms.notification.target;\n\t\t\t\t\t\t\t\t\t\t\tif (typeof mail !== 'undefined' && mail.search('@') > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, mail, 1);\n\t\t\t\t\t\t\t\t\t\t\t} else if (typeof response.data.params.alarms.notification.mail_to_input === 'undefined') {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 1);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (typeof response.data.params.armConfirm.notification !== 'undefinded') {\n\t\t\t\t\t\t\t\t\t\t\tvar mail = response.data.params.armConfirm.notification.target;\n\t\t\t\t\t\t\t\t\t\t\tif (typeof mail !== 'undefined' && mail.search('@') > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, mail, 2);\n\t\t\t\t\t\t\t\t\t\t\t} else if (typeof response.data.params.armConfirm.notification.mail_to_input === 'undefined') {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 2);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (typeof response.data.params.disarmConfirm.notification !== 'undefinded') {\n\t\t\t\t\t\t\t\t\t\t\tvar mail = response.data.params.disarmConfirm.notification.target;\n\t\t\t\t\t\t\t\t\t\t\tif (typeof mail !== 'undefined' && mail.search('@') > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, mail, 3);\n\t\t\t\t\t\t\t\t\t\t\t} else if (typeof response.data.params.disarmConfirm.notification.mail_to_input === 'undefined') {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 3);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (typeof response.data.params.clean.notification !== 'undefinded') {\n\t\t\t\t\t\t\t\t\t\t\tvar mail = response.data.params.clean.notification.target;\n\t\t\t\t\t\t\t\t\t\t\tif (typeof mail !== 'undefined' && mail.search('@') > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, mail, 4);\n\t\t\t\t\t\t\t\t\t\t\t} else if (typeof response.data.params.clean.notification.mail_to_input === 'undefined') {\n\t\t\t\t\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 4);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 0);\n\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 1);\n\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 2);\n\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 3);\n\t\t\t\t\t\t\t\tfillDropDown(profilesResponse.data, false, 4);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.fail(function () {\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\t$(\".mail_input\").parent().append('<div class=\"alert alert-warning\">'+control.data.mail_helper+'</div>');\n\t\t\t\t\t$(\".mail_input\").hide();\t\t\t\t\t\n\t\t\t\t}\n\t\t\t})\n\t\t\t.fail(function () {\n\t\t\t\t$(\".mail_input\").parent().append('<div class=\"alert alert-warning\">'+control.data.mail_helper+'</div>');\n\t\t\t\t$(\".mail_input\").hide();\n\t\t\t});\n\t}\n}\n\nfunction fillDropDown(profiles, selectedMail, notificationID) {\n\tvar select = $(\".target_select\").find('select');\n\tvar added = false;\n\n\tprofiles.forEach(function (singleProfile) {\n\t\tif ((typeof singleProfile.email !== 'undefined') && (singleProfile.email !== \"\")) {\n\t\t\tif (singleProfile.email === selectedMail) {\n\t\t\t\t$(select[notificationID]).append($('<option></option>').val(singleProfile.email).html(singleProfile.email));\n\t\t\t} else {\n\t\t\t\t$(select[notificationID]).append($('<option></option>').val(singleProfile.email).html(singleProfile.email));\n\t\t\t}\n\t\t\tadded = true;\n\t\t}\n\t});\n\n\tif (!added){\n\t\t$(\".mail_input\").show();\n\t} else {\n\t\tif (selectedMail) {\n\t\t\t$(select[notificationID]).val(selectedMail);\n\t\t}\n\n\t\t$(\".mail_input\").hide();\n\t}\n}\n"
  },
  {
    "path": "modules/Security/index.js",
    "content": "/*** Security Z-Way HA module *******************************************\n\n Version: 2.1\n (c) Z-Wave.Me, 2022\n -----------------------------------------------------------------------------\n Author: Karsten Reichel <kar@zwave.eu>, Yurkin Vitaliy <aivs@z-wave.me>\n Description: Basic Security Module\n ******************************************************************************/\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\nfunction Security(id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSecurity.super_.call(this, id, controller);\n\n\tvar self = this;\n\n\tthis.minuteStandart = 60; //60\n\tthis.secondStandart = 1; //1\n\n\t/**\n\t * Static State Datas\n\t * @type {{COFF: {value: number, name: string, code: string, vDevname: string}, CON: {value: number, name: string, code: string, vDevname: string}, CRESET: {value: number, name: string, code: string, vDevname: string}, TRIGGER: {value: number, name: string, code: string, vDevname: string}, TIMER: {value: number, name: string, code: string, vDevname: string}, FTIMER: {value: number, name: string, code: string, vDevname: string}, AUTOTOGGLE: {value: number, name: string, code: string, vDevname: string}}}\n\t */\n\tthis.performEnum = {\n\t\tCOFF: {\n\t\t\tvalue: 0,\n\t\t\tname: \"cOff\",\n\t\t\tcode: \"OF\",\n\t\t\tvDevname: \"Security_Unarmed\"\n\t\t},\n\t\tCON: {\n\t\t\tvalue: 1,\n\t\t\tname: \"cOn\",\n\t\t\tcode: \"ON\",\n\t\t\tvDevname: \"Security_Armed\"\n\t\t},\n\t\tCRESET: {\n\t\t\tvalue: 2,\n\t\t\tname: \"cReset\",\n\t\t\tcode: \"RE\",\n\t\t\tvDevname: \"Security_Reset\"\n\t\t},\n\t\tTRIGGER: {\n\t\t\tvalue: 3,\n\t\t\tname: \"trigger\",\n\t\t\tcode: \"TR\",\n\t\t\tvDevname: \"Alarm_Trigger\"\n\t\t},\n\t\tTIMER: {\n\t\t\tvalue: 4,\n\t\t\tname: \"timer\",\n\t\t\tcode: \"TI\",\n\t\t\tvDevname: \"Alarm_Command_TimerStart\"\n\t\t},\n\t\tFTIMER: {\n\t\t\tvalue: 5,\n\t\t\tname: \"ftimer\",\n\t\t\tcode: \"FT\",\n\t\t\tvDevname: \"Alarm_Command_TimerEnd\"\n\t\t},\n\t\tAUTOTOGGLE: {\n\t\t\tvalue: 6,\n\t\t\tname: \"automationToggle\",\n\t\t\tcode: \"AT\",\n\t\t\tvDevname: \"Automation_switch\"\n\t\t}\n\t};\n\n\t/**\n\t * Stati an State can have\n\t * @type {{INIT: string, STOPPED: string, RUNNING: string}}\n\t */\n\tthis.StateStatus = {\n\t\tINIT: \"init\",\n\t\tSTOPPED: \"stop\",\n\t\tRUNNING: \"run\"\n\t};\n\n\t/**\n\t * Static Transition Datas\n\t * @type {{OFF: {value: number, name: string, code: string, vDevname: string, StateStatus: string}, LIVEON: {value: number, name: string, code: string, vDevname: string, StateStatus: string}, ALARMED: {value: number, name: string, code: string, vDevname: string, StateStatus: string}, INITIAL: {value: number, name: string, code: string, vDevname: string, StateStatus: string}}}\n\t */\n\tthis.StateEnum = {\n\t\tOFF: {\n\t\t\tvalue: 0,\n\t\t\tname: \"off\",\n\t\t\tcode: \"O\",\n\t\t\tvDevname: \"Alarm_Off\",\n\t\t\tStateStatus: this.StateStatus.STOPPED\n\t\t},\n\t\tLIVEON: {\n\t\t\tvalue: 2,\n\t\t\tname: \"liveOn\",\n\t\t\tcode: \"L\",\n\t\t\tvDevname: \"Alarm_Ready\",\n\t\t\tStateStatus: this.StateStatus.STOPPED\n\t\t},\n\t\tALARMED: {\n\t\t\tvalue: 3,\n\t\t\tname: \"alarmed\",\n\t\t\tcode: \"A\",\n\t\t\tvDevname: \"Alarm_Alarmed\",\n\t\t\tStateStatus: this.StateStatus.STOPPED\n\t\t},\n\t\tINITIAL: {\n\t\t\tvalue: 4,\n\t\t\tname: \"initial\",\n\t\t\tcode: \"I\",\n\t\t\tvDevname: \"Alarm_Initial\",\n\t\t\tStateStatus: this.StateStatus.STOPPED\n\t\t}\n\t};\n}\ninherits(Security, AutomationModule);\n_module = Security;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n//\n\n/**\n * Datas an Extern Device needs for Controling the Module oder get Controled from the Module\n * @param self a Reference of this Module\n * @param device a Reference of the device\n * @param condition the Condition when something happends in the Module when device Level is condition\n * @param performE what Happend if Conditionb is true\n * @constructor\n */\nSecurity.prototype.BusDatas = function(self, device, condition, performE) {\n\tthis.self = self;\n\tthis.device = device;\n\tthis.condition = condition;\n\tthis.performE = performE;\n}\n\n//State Definition\n/**\n * Definition of an State\n * @param stateEnum the Unique State Datas\n * @param entry The first called Method of an State before it is Set\n * @param make the doing Method of an State can have an arg Parameter\n * @param exit the Method who called by exitin an state\n * @constructor\n */\nSecurity.prototype.State = function(stateStatus, stateEnum, entry, make, exit) {\n\tvar entry = entry;\n\tvar make = make;\n\tvar exit = exit;\n\n\tthis.stateStatus = stateStatus;\n\tthis.stateEnum = stateEnum;\n\n\tthis.doEntry = function() {\n\t\tstateEnum.StateStatus = stateStatus.INIT;\n\t\tentry();\n\t};\n\tthis.doMake = function(args) {\n\t\tif (stateEnum.StateStatus === stateStatus.INIT) {\n\t\t\tstateEnum.StateStatus = stateStatus.RUNNING;\n\t\t\tmake(args);\n\t\t}\n\t};\n\tthis.doExit = function() {\n\t\tif (stateEnum.StateStatus === stateStatus.RUNNING) {\n\t\t\texit();\n\t\t\tstateEnum.StateStatus = stateStatus.STOPPED;\n\t\t}\n\t};\n}\n\n/**\n * sets the parameter to the Automation Controlling value\n * @param toSet parameter\n */\nSecurity.prototype.setAutomation = function(toSet) {\n\tvar self = this;\n\tself.vDev.set(\"metrics:Alevel\", toSet);\n};\n/**\n * Initiate the Module\n * @param config Alpaca Datas\n */\nSecurity.prototype.init = function(config) {\n\tSecurity.super_.prototype.init.call(this, config);\n\tvar self = this;\n\tthis.a = null;\n\tthis.alarmDevice = null;\n\t//this.scheduletimer = null;\n\tthis.alarmtimer = null;\n\tthis.alarmSilenttimerS2 = null;\n\tthis.alarmtimerS2 = null;\n\tthis.alarmCtimer = null;\n\tthis.sensorsDatas = config.input.table;\n\tthis.armingDevicesData = config.inputArming.table;\n\tthis.entranceGroup = self.filterForOn(config.input.table, \"sensorAtTheEntrance\");\n\tthis.lastTriggerList = [];\n\tthis.ignorenamesList = [];\n\tthis.onDatas = self.filterFor(config.controls.table, \"armCondition\");\n\tthis.offDatas = self.filterFor(config.controls.table, \"disarmCondition\");\n\tthis.resetDatas = self.filterFor(config.controls.table, \"clearCondition\");\n\tthis.silentalarmDatas = config.silentAlarms.table;\n\tthis.alarmDatas = config.alarms.table;\n\tthis.confirmDatas = config.armConfirm.table;\n\tthis.disconfirmDatas = config.disarmConfirm.table;\n\tthis.armFailureDatas = config.armFailureAction.table;\n\tthis.entranceDetectedDatas = config.entranceDetected.table;\n\tthis.cleanDatas = config.clean.table;\n\tthis.silentalarmNots = config.silentAlarms.notification;\n\tthis.alarmNots = config.alarms.notification;\n\tthis.confirmNots = config.armConfirm.notification;\n\tthis.disconfirmNots = config.disarmConfirm.notification;\n\tthis.armFailureNots = config.armFailureAction.notification;\n\tthis.entranceDetectedNots = config.entranceDetected.notification;\n\tthis.cleanNots = config.clean.notification;\n\tthis.timeSchedule = config.schedules;\n\tthis.cronListeningCollector = [];\n\tthis.busDatas = new this.BusDatas(null, null, null, null);\n\tthis.busDataMap = {};\n\tthis.interval = config.times.interval;\n\tthis.silent = config.times.silent;\n\tthis.delayForEntranceGroup = config.times.delaySensorAtTheEntrance;\n\tthis.autoDeviceTrigger = \"on\";\n\tthis.timerEntranceGroupAlarm = null;\n\tthis.timerEntranceGroupAtStart = null;\n\tthis.timerWaitDevicesAtStart = null;\n\tthis.onInputList = [];\n\tthis.langFile = this.loadModuleLang();\n\n\t/**\n\t * function who will Connected to devices who trigger the Alarm\n\t * @param idev device\n\t */\n\tthis.sensorFunction = function sensorFunction(idev) {\n\t\tvar busDatas;\n\t\tvar vDevD;\n\n\t\tthis.sensorFunctionIF = function() {\n\t\t\tif (busDatas) {\n\t\t\t\tvDevD = busDatas.self.controller.devices.get(busDatas.device);\n\t\t\t\tif (busDatas.condition === vDevD.get(\"metrics:level\")) {\n\t\t\t\t\tif (busDatas.self.vDev.get(\"metrics:state\") === self.StateEnum.LIVEON) {\n\t\t\t\t\t\tbusDatas.self.lastTrigger(busDatas.self.lastTriggerList, vDevD);\n\t\t\t\t\t}\n\t\t\t\t\tif (busDatas.self.vDev.get(\"metrics:level\") === \"on\") {\n\t\t\t\t\t\t/* \n\t\t\t\t\t\t * Check if sensor in the entranceGroup list.\n\t\t\t\t\t\t * Check if timer at start for entrance group stopped.\n\t\t\t\t\t\t * If in the list, so start timer for trigger alarm,\n\t\t\t\t\t\t * else run alarm immediately.\n\t\t\t\t\t\t * The timer resets only when disarmed.\n\t\t\t\t\t\t */\n\t\t\t\t\t\tif (self.entranceGroup.indexOf(busDatas.device) !== -1) {\n\t\t\t\t\t\t\tif (self.timerEntranceGroupAtStart == null) {\n\t\t\t\t\t\t\t\tconsole.log(\"--- Security: At the entrance detected sensor activation. Wait \" + self.delayForEntranceGroup + \" seconds.\");\n\t\t\t\t\t\t\t\t// Run entrance detected actions\n\t\t\t\t\t\t\t\tself.shiftTriggerDevices(self.entranceDetectedDatas, self.entranceDetectedNots, 'disarm');\n\t\t\t\t\t\t\t\tvar bDatas = busDatas;\n\t\t\t\t\t\t\t\tif (self.timerEntranceGroupAlarm == null) {\n\t\t\t\t\t\t\t\t\tself.timerEntranceGroupAlarm = setTimeout(function () {\n\t\t\t\t\t\t\t\t\t\tbDatas.self.vDev.performCommand(self.performEnum.TRIGGER.name, {\n\t\t\t\t\t\t\t\t\t\t\tdevice: bDatas.device.toString()\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\tself.timerEntranceGroupAlarm = null;\n\n\t\t\t\t\t\t\t\t\t}, self.delayForEntranceGroup*1000);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tbusDatas.self.vDev.performCommand(self.performEnum.TRIGGER.name, {\n\t\t\t\t\t\t\t\tdevice: busDatas.device.toString()\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!busDatas.self.alarmDevice) {\n\t\t\t\t\t\tbusDatas.self.alarmDevice = busDatas.device.toString();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tbusDatas = self.busDataMap[idev.id + '#' + \"on\"];\n\t\tthis.sensorFunctionIF();\n\t\tbusDatas = self.busDataMap[idev.id + '#' + \"off\"];\n\t\tthis.sensorFunctionIF();\n\t};\n\t/**\n\t * function who will Connected to devices who Control the Module\n\t * @param idev\n\t */\n\tthis.inputFunction = function inputFunction(idev) {\n\t\tvar busDatas;\n\t\tvar vDevD;\n\n\t\tthis.inputFunctionIF = function() {\n\t\t\tif (busDatas) {\n\t\t\t\tvDevD = self.controller.devices.get(busDatas.device);\n\t\t\t\tif (busDatas.condition === vDevD.get(\"metrics:level\") || busDatas.condition === true) {\n\t\t\t\t\tbusDatas.self.vDev.performCommand(busDatas.performE.name, {\n\t\t\t\t\t\tdevice: busDatas.device.toString()\n\t\t\t\t\t});\n\t\t\t\t\tif (!busDatas.self.alarmDevice) {\n\t\t\t\t\t\tbusDatas.self.alarmDevice = busDatas.device.toString();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\tbusDatas = self.busDataMap[idev.id + '#' + idev.get('metrics:level')];\n\t\tthis.inputFunctionIF();\n\t\tbusDatas = self.busDataMap[idev.id + '#' + true];\n\t\tthis.inputFunctionIF();\n\t};\n\n\tthis.startSecurity = function () {\n\t\tconsole.log(\"------------------Security start\"); \n\t\tself.makeVDevs(config);\n\t\tself.wipeOwnVDevs();\n\t\tself.initStates();\n\t\tself.state = self.initState;\n\t\tself.initDevices();\n\t\tself.state.doEntry();\n\t\tself.state.doMake();\n\n\t\tvar activeStatusAtStart = config.times.active;\n\t\tself.vDev.performCommand(self.performEnum.COFF.name);\n\n\t\tif (activeStatusAtStart) {\n\t\t\tself.vDev.performCommand(self.performEnum.CON.name);\n\t\t}\n\t};\n\n\tvar notAddedDevices = [];\n\tthis.onDeviceAdded = function (vDev) {\n\t\tconst index = notAddedDevices.indexOf(vDev.id);\n\t\tif (notAddedDevices.length > 0 && index > -1) {\n\t\t\tnotAddedDevices.splice(index, 1);\n\t\t}\n\n\t\tif (notAddedDevices.length == 0) {\n\t\t\tself.controller.devices.off(\"created\", self.onDeviceAdded);\n\t\t\tself.startSecurity();\n\t\t}\n\t};\n\t\n\tthis.pollArm = function() {\n\t\tself.vDev.performCommand(self.performEnum.CON.name);\n\t};\n\n\tthis.pollDisarm = function() {\n\t\tself.vDev.performCommand(self.performEnum.COFF.name);\n\t}\n\t// Get all devices used in this app\n\tObject.keys(this.config).forEach(function (e) {\n\t\tif (self.config[e].table) {\n\t\t\tself.config[e].table.forEach(function (ee) {\n\t\t\t\tif (!self.controller.devices.get(ee.devices)) {\n\t\t\t\t\tnotAddedDevices.push(ee.devices);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t});\n\n\tif (notAddedDevices.length > 0) {\n\t\tself.controller.devices.on(\"created\", self.onDeviceAdded);\n\t\tconsole.log(\"--- Security running, but not all devices are available: \" + notAddedDevices.toString() + \". We are waiting 2 minutes before restarting.\");\n\n\t\t// Start 2 minutes off timer\n\t\tself.timerWaitDevicesAtStart = setTimeout(function () {\n\t\t\tself.log(\"warning\", notAddedDevices.toString() + self.langFile.device_used_in_settings, false);\n\t\t\tself.controller.devices.off(\"created\", self.onDeviceAdded);\n\t\t\tself.startSecurity();\n\t\t}, 120*1000);\n\t}\n\telse {\n\t\tself.startSecurity();\n\t}\n};\n\n/**\n * stops module and remove all injections and destroys all vdevs\n */\nSecurity.prototype.stop = function() {\n\tthis.alarmCancel();\n\tthis.stopDevices();\n\tthis.endschedule();\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t}\n\n\tthis.vDev = null;\n\tthis.destroyVDevs();\n\tSecurity.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n/**\n * Method calls the wipeOwnVdevs for all Device Arrays\n */\nSecurity.prototype.wipeOwnVDevs = function() {\n\tvar self = this;\n\tself.wipeOwnVDevsFromArray(self.alarmDatas);\n\tself.wipeOwnVDevsFromArray(self.confirmDatas);\n\tself.wipeOwnVDevsFromArray(self.disconfirmDatas);\n\tself.wipeOwnVDevsFromArray(self.resetDatas);\n\n};\n/**\n * Methode who deletes all VDevs from the Security Module out of his\n * own inputs\n * @param array\n */\nSecurity.prototype.wipeOwnVDevsFromArray = function(array) {\n\tvar self = this;\n\tself.ignorenamesList.forEach(function(input) {\n\t\tarray.forEach(function(aInput, index) {\n\t\t\tif (input.devices === aInput.devices) {\n\t\t\t\tarray.splice(index, 1);\n\t\t\t}\n\t\t});\n\n\t});\n};\n/**\n * Methode who fills an Array with The Triggers of an Alarm\n * @param array\n * @param trigger\n */\nSecurity.prototype.lastTrigger = function(array, trigger) {\n\tvar self = this;\n\tif (array.length < 11) {\n\t\ttrigger.get(\"metrics:title\");\n\t\tarray[array.length] = {\n\t\t\tid: trigger.get(\"id\"),\n\t\t\tname: trigger.get(\"metrics:title\"),\n\t\t\ttime: new Date(),\n\t\t\tstate: trigger.get(\"metrics:level\")\n\t\t};\n\t} else {\n\t\tarray.unshift(trigger);\n\t}\n\tself.vDev.set(\"metrics:lastTriggerList\", array);\n};\n/**\n * Method who filters an Array on an condition value of its objects and Return it than\n * @param array\n * @param condition\n * @returns {Array}\n */\nSecurity.prototype.filterFor = function(array, condition) {\n\tvar output = [];\n\tarray.forEach(function(input) {\n\t\tif (input[condition] !== \"not_used\") {\n\t\t\toutput.push({\n\t\t\t\tdevices: input.devices,\n\t\t\t\tconditions: input[condition]\n\t\t\t});\n\t\t}\n\t});\n\treturn output;\n};\n\n/**\n * Method who filters an Array on an condition ON of its objects and Return it than\n * @param array\n * @param condition\n * @returns {Array}\n */\nSecurity.prototype.filterForOn = function(array, condition) {\n\tvar output = [];\n\tarray.forEach(function(input) {\n\t\tif (input[condition] === \"on\")\n\t\t\toutput.push(input.devices);\n\t});\n\treturn output;\n};\n\n/**\n * Method who injects the Methods for Alarmtriggering on an Device with some Condition for Triggering\n * @param device\n * @param condition\n */\nSecurity.prototype.onSensor = function(device, condition) {\n\tvar self = this;\n\tif (!self.busDataMap[device + '#' + condition]) {\n\t\tself.busDataMap[device + '#' + condition] = new this.BusDatas(self, device, condition, null);\n\t}\n\tself.controller.devices.on(device, \"change:metrics:level\", self.sensorFunction);\n};\n/**\n * looks after commands if they come from extern or from the module\n * @param args argument of the command\n * @param vdevId Id of the Command sender\n * @param method method to perform\n */\nSecurity.prototype.commandHandlingWithBidirektionalScene = function(args, vdevId, method) {\n\tvar self = this;\n\tif (args && args.device && args.device === vdevId) {\n\t\tmethod();\n\t} else {\n\t\tself.controller.devices.get(vdevId).set(\"metrics:level\", \"on\");\n\t}\n};\n/**\n * Initiate all Vdevs for the Module\n */\nSecurity.prototype.makeVDevs = function() {\n\tvar self = this;\n\t//Transition VDEVS\n\tself.vDevON = self.makeVDev(this.performEnum.CON.vDevname, 'toggleButton');\n\tself.vDevOFF = self.makeVDev(this.performEnum.COFF.vDevname, 'toggleButton');\n\tself.vDevRESET = self.makeVDev(this.performEnum.CRESET.vDevname, 'toggleButton');\n\tself.vDevTRIGGER = self.makeVDev(this.performEnum.TRIGGER.vDevname, 'toggleButton');\n\t//Alarm State VDEV\n\tself.vDevALARM = self.makeVDev(this.StateEnum.ALARMED.vDevname, 'toggleButton');\n\t//Automation VDEV\n\tself.vDevTimeSchedule = self.makeVDev(this.performEnum.AUTOTOGGLE.vDevname, 'toggleButton');\n\t//Module VDEV\n\tself.vDev = self.controller.devices.create({\n\t\tdeviceId: \"Security_\" + self.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"sensorMultiline\",\n\t\t\tmetrics: {\n\t\t\t\tmultilineType: \"securityControl\",\n\t\t\t\ttitle: self.getInstanceTitle(),\n\t\t\t\ticon: \"security\",\n\t\t\t\tstate: self.StateEnum.OFF,\n\t\t\t\tlevel: 'off',\n\t\t\t\tscaleTitle: '',\n\t\t\t\tAlevel: 'off',\n\t\t\t\tRlevel: 'off',\n\t\t\t\tClevel: this.performEnum.COFF.name,\n\t\t\t\tinterval: self.interval,\n\t\t\t\tlastTriggerList: []\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function(command, args) {\n\t\t\tvar returnState = {\n\t\t\t\t'code': 2,\n\t\t\t\t'runningState': \"undefined\"\n\t\t\t};\n\t\t\tswitch (command) {\n\t\t\t\tcase \"test\":\n\t\t\t\t\tself.test();\n\t\t\t\t\treturnState = self.makeReturnState(1, \"test Security_\" + self.id);\n\t\t\t\t\treturn returnState;\n\t\t\t\tcase self.performEnum.COFF.name:\n\t\t\t\t\tself.config.times.active = false;\n\t\t\t\t\tself.saveConfig();\n\t\t\t\t\tif (self.timerEntranceGroupAlarm) {\n\t\t\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\t\t\tclearTimeout(self.timerEntranceGroupAlarm);\n\t\t\t\t\t\tself.timerEntranceGroupAlarm = null;\n\t\t\t\t\t}\n\t\t\t\t\tself.commandHandlingWithBidirektionalScene(args, self.vDevOFF.id, function() {\n\t\t\t\t\t\tself.transition(true /*self.canOff()*/, self.off, args);\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase self.performEnum.CRESET.name:\n\t\t\t\t\tself.commandHandlingWithBidirektionalScene(args, self.vDevRESET.id, function() {\n\t\t\t\t\t\tself.transition(self.canReset(), self.liveOn, args);\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase self.performEnum.CON.name:\n\t\t\t\t\tself.config.times.active = true;\n\t\t\t\t\tself.saveConfig();\n\t\t\t\t\tself.commandHandlingWithBidirektionalScene(args, self.vDevON.id, function() {\n\t\t\t\t\t\tself.transition(self.canOn(), self.liveOn, args);\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase self.performEnum.TRIGGER.name:\n\t\t\t\t\tself.alarmDevice = args.device;\n\t\t\t\t\tif (args.device && args.device !== self.vDevTRIGGER.id) {\n\t\t\t\t\t\tself.a = args;\n\t\t\t\t\t}\n\t\t\t\t\tself.commandHandlingWithBidirektionalScene(args, self.vDevTRIGGER.id, function() {\n\t\t\t\t\t\tself.transition(self.canTrigger(), self.alarmed, self.a);\n\t\t\t\t\t});\n\t\t\t\t\tbreak;\n\t\t\t\tcase self.performEnum.TIMER.name:\n\t\t\t\t\tself.transition(self.canTimer(), self.liveOn, args);\n\t\t\t\t\tbreak;\n\t\t\t\tcase self.performEnum.FTIMER.name:\n\t\t\t\t\tself.transition(self.canTimer(), self.alarmed, args);\n\t\t\t\t\tbreak;\n\t\t\t\tcase self.performEnum.AUTOTOGGLE.name:\n\t\t\t\t\tif (args.device === self.vDevTimeSchedule.id) {\n\t\t\t\t\t\tif (self.vDev.get(\"metrics:Alevel\") === 'on') {\n\t\t\t\t\t\t\tself.setAutomation('off');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.setAutomation('on');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.log(\"warning\", \"automation switched to \" + \"#\" + self.vDev.get(\"metrics:Alevel\"), false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.controller.devices.get(self.vDevTimeSchedule.id).set(\"metrics:level\", \"on\");\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tself.log(\"warning\", \"unknown command \" + command, false);\n\t\t\t\t\treturnState = self.makeReturnState(2, command + 'is not available command');\n\t\t\t\t\treturn returnState;\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n};\n/**\n * Deletes all Vdevs\n */\nSecurity.prototype.destroyVDevs = function() {\n\tvar self = this;\n\tself.destroyVDev(this.performEnum.CON.vDevname);\n\tself.destroyVDev(this.performEnum.COFF.vDevname);\n\tself.destroyVDev(this.performEnum.CRESET.vDevname);\n\tself.destroyVDev(this.performEnum.TRIGGER.vDevname);\n\tself.destroyVDev(this.StateEnum.ALARMED.vDevname);\n\tself.destroyVDev(this.performEnum.AUTOTOGGLE.vDevname);\n};\n/**\n * Makes an VDEV with name and Devicetype\n * @param name\n * @param devicetype\n * @returns {*} VDEV\n */\nSecurity.prototype.makeVDev = function(name, devicetype) {\n\tvar self = this;\n\tvar title = name + \" (\" + self.id + \")\";\n\tvar id = \"Security_\" + self.id + name;\n\tself.ignorenamesList.push({\n\t\t\"devices\": id\n\t});\n\treturn self.controller.devices.create({\n\t\tdeviceId: id,\n\t\tdefaults: {\n\t\t\tdeviceType: devicetype,\n\t\t\tmetrics: {\n\t\t\t\tlevel: 'on',\n\t\t\t\ttitle: title\n\t\t\t}\n\t\t},\n\t\toverlay: {\n\t\t\tdeviceType: devicetype,\n\t\t\tprobeType: self.id + name\n\t\t},\n\t\thandler: function(command) {\n\n\t\t\tthis.set(\"metrics:level\", command);\n\t\t},\n\t\tmoduleId: this.id\n\n\t});\n};\n/**\n * Deletes an VDEV withj specifik name\n * @param vdevName\n */\nSecurity.prototype.destroyVDev = function(vdevName) {\n\tvar self = this;\n\tself.controller.devices.remove(\"Security_\" + self.id + vdevName);\n\n};\n/**\n * Injects the Extern Module Control Devices\n * @param pE Transition to Trigger\n * @param device Device\n * @param condition Condition of the Devicelevel when trigger\n */\n\nSecurity.prototype.onInput = function(pE, device, condition) {\n\tvar self = this;\n\tif (self.controller.devices.get(device) && self.onInputList.indexOf(device) === -1) {\n\t\tself.controller.devices.on(device, \"change:metrics:level\",\n\t\t\tself.inputFunction\n\t\t);\n\t}\n\n\tif (!self.busDataMap[device + '#' + condition] && condition !== \"\") {\n\t\tself.busDataMap[device + '#' + condition] = new this.BusDatas(self, device, condition, pE);\n\t\tself.onInputList.push(device);\n\t}\n};\n\n\n/**\n * Inits all vdevs and Used Devices and visibility\n */\nSecurity.prototype.initDevices = function() {\n\tvar self = this;\n\tif (self.sensorsDatas) {\n\t\tself.onSensorsAndConditionArray(self.sensorsDatas);\n\t}\n\tif (self.offDatas) {\n\t\tself.onInputArray(this.performEnum.COFF, self.offDatas);\n\t}\n\tif (self.onDatas) {\n\t\tself.onInputArray(this.performEnum.CON, self.onDatas);\n\t}\n\tif (self.resetDatas) {\n\t\tself.onInputArray(this.performEnum.CRESET, self.resetDatas);\n\t}\n\tself.onInput(this.performEnum.CON, self.vDevON.id, true);\n\tself.onInput(this.performEnum.COFF, self.vDevOFF.id, true);\n\tself.onInput(this.performEnum.CRESET, self.vDevRESET.id, true);\n\tself.onInput(this.performEnum.TRIGGER, self.vDevTRIGGER.id, true);\n\tself.onInput(this.performEnum.AUTOTOGGLE, self.vDevTimeSchedule.id, true);\n\tthis.vDevON.set('visibility', false, {\n\t\tsilent: true\n\t});\n\tthis.vDevOFF.set('visibility', false, {\n\t\tsilent: true\n\t});\n\tthis.vDevRESET.set('visibility', false, {\n\t\tsilent: true\n\t});\n\tthis.vDevTRIGGER.set('visibility', false, {\n\t\tsilent: true\n\t});\n\tthis.vDevALARM.set('visibility', false, {\n\t\tsilent: true\n\t});\n\tthis.vDevTimeSchedule.set('visibility', false, {\n\t\tsilent: true\n\t});\n};\n/**\n * removes all device Injections and removes all vdevs\n */\nSecurity.prototype.stopDevices = function() {\n\tvar self = this;\n\tif (self.sensorsDatas) {\n\t\tself.offSensorsAndConditionArray(self.sensorsDatas);\n\t}\n\tif (self.onDatas) {\n\t\tself.offInputArray(this.performEnum.CON, self.onDatas);\n\t}\n\tif (self.offDatas) {\n\t\tself.offInputArray(this.performEnum.COFF, self.offDatas);\n\t}\n\tif (self.resetDatas) {\n\t\tself.offInputArray(this.performEnum.CRESET, self.resetDatas);\n\t}\n\n\tif (self.vDevON) {\n\t\tself.offInput(this.performEnum.CON, self.vDevON.id, true);\n\t\tself.controller.devices.remove(self.vDevON.id);\n\t\tself.vDevON = null;\n\t}\n\tif (self.vDevOFF) {\n\t\tself.offInput(this.performEnum.COFF, self.vDevOFF.id, true);\n\t\tself.controller.devices.remove(self.vDevOFF.id);\n\t\tself.vDevOFF = null;\n\t}\n\tif (self.vDevRESET) {\n\t\tself.offInput(this.performEnum.CRESET, self.vDevRESET.id, true);\n\t\tself.controller.devices.remove(self.vDevRESET.id);\n\t\tself.vDevRESET = null;\n\t}\n\tif (self.vDevTRIGGER) {\n\t\tself.offInput(this.performEnum.TRIGGER, self.vDevTRIGGER.id, true);\n\t\tself.controller.devices.remove(self.vDevTRIGGER.id);\n\t\tself.vDevTRIGGER = null;\n\t}\n\tif (self.vDevTimeSchedule) {\n\t\tself.offInput(this.performEnum.AUTOTOGGLE, self.vDevTimeSchedule.id, true);\n\t\tself.controller.devices.remove(self.vDevTimeSchedule.id);\n\t\tself.vDevTimeSchedule = null;\n\t}\n\tif (self.vDevALARM) {\n\t\tself.controller.devices.remove(self.vDevALARM.id);\n\t\tself.vDevALARM = null;\n\t}\n\tself.log(\"warning\", self.langFile.disabled, false);\n\n};\n/**\n * iterates an array of devices for Injection to Control the Module\n * @param pE command for the devices\n * @param inputList\n */\nSecurity.prototype.onInputArray = function(pE, inputList) {\n\tvar self = this;\n\tinputList.forEach(function(input) {\n\t\tself.onInput(pE, input.devices, input.conditions);\n\t});\n};\n/**\n * iterates an array of devices for Injection to Trigger Alarm\n * @param sensors\n */\nSecurity.prototype.onSensorsAndConditionArray = function(sensors) {\n\tvar self = this;\n\tsensors.forEach(\n\t\tfunction(args) {\n\t\t\tself.onSensor(args.devices, args.conditions);\n\t\t}\n\t);\n};\n/**\n * iterates an array of devices for remove Injection to Control the Module\n * @param pE\n * @param inputList\n */\nSecurity.prototype.offInputArray = function(pE, inputList) {\n\tvar self = this;\n\n\tinputList.forEach(function(input) {\n\t\tself.offInput(pE, input.devices, input.conditions);\n\t});\n};\n/**\n * removes Injections off an Control device\n * @param pE\n * @param device\n */\nSecurity.prototype.offInput = function(pE, device) {\n\tvar self = this;\n\tif (self.controller.devices.get(device)) {\n\t\tself.controller.devices.off(device, \"change:metrics:level\",\n\t\t\tself.inputFunction\n\t\t);\n\t}\n\n\n};\n/**\n * iterates an array of devices for remove Injection to Trigger Alarm\n * @param sensors\n */\nSecurity.prototype.offSensorsAndConditionArray = function(sensors) {\n\tvar self = this;\n\tsensors.forEach(\n\t\tfunction(args) {\n\t\t\tself.offSensor(args.devices, args.conditions);\n\t\t}\n\t);\n};\n/**\n * removes trigger function of an Alarm Sensor\n * @param device\n */\nSecurity.prototype.offSensor = function(device) {\n\tvar self = this;\n\tself.controller.devices.off(device, \"change:metrics:level\",\n\t\tself.sensorFunction\n\t);\n};\n/**\n * looks if scheduler is running\n * @returns {boolean}\n */\nSecurity.prototype.scheduleActive = function() {\n\tvar self = this;\n\tif (self.controller.devices.get(self.vDevTimeSchedule.id) && self.controller.devices.get(self.vDevTimeSchedule.id).get(\"metrics:level\")) {\n\t\treturn self.controller.devices.get(self.vDevTimeSchedule.id).get(\"metrics:level\");\n\t} else {\n\t\treturn false;\n\t}\n};\n/**\n * analyse the Scheduler if sth changed\n * @param timeSchedule\n */\nSecurity.prototype.schedule = function() {\n\tvar self = this;\n\t/*self.scheduletimer = setInterval(function() {\n\t\tif (self.scheduleActive()) {\n\t\t\tif (self.analyseSchedule(timeSchedule, \"arm\")) {\n\t\t\t\tself.vDev.performCommand(self.performEnum.CON.name);\n\t\t\t}\n\t\t\tif (self.analyseSchedule(timeSchedule, \"disarm\")) {\n\t\t\t\tself.vDev.performCommand(self.performEnum.COFF.name);\n\t\t\t}\n\t\t}\n\n\t}, this.minuteStandart * 500);*/\n\tconsole.log('### timeSchedule:', JSON.stringify(this.timeSchedule));\n\tconsole.log('### this.scheduleActive():', this.scheduleActive());\n\n\tif (this.scheduleActive() && this.timeSchedule) {\n\t\tObject.keys(this.timeSchedule).forEach(function(weekday) {\n\t\t\tvar times = ['arm', 'disarm'];\n\t\t\tif (self.timeSchedule[weekday].length > 0) {\n\t\t\t\tself.timeSchedule[weekday].forEach(function(entry) {\n\t\t\t\t\ttimes.forEach(function(time) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar min = parseInt(entry[time].split(\":\")[1], 10),\n\t\t\t\t\t\t\t\thour = parseInt(entry[time].split(\":\")[0], 10),\n\t\t\t\t\t\t\t\tlistenerName = time + '.' + entry[time] + '.' + weekday + '.poll';\n\n\t\t\t\t\t\t\t// add cron schedule every week\n\t\t\t\t\t\t\tself.controller.emit(\"cron.addTask\", listenerName, {\n\t\t\t\t\t\t\t\tminute: min,\n\t\t\t\t\t\t\t\thour: hour,\n\t\t\t\t\t\t\t\tweekDay: parseInt(weekday, 10),\n\t\t\t\t\t\t\t\tday: null,\n\t\t\t\t\t\t\t\tmonth: null\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (time === 'arm') {\n\t\t\t\t\t\t\t\tself.controller.on(listenerName, self.pollArm);\n\t\t\t\t\t\t\t} else if (time === 'disarm') {\n\t\t\t\t\t\t\t\tself.controller.on(listenerName, self.pollDisarm);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (self.cronListeningCollector.indexOf(listenerName) < 0) {\n\t\t\t\t\t\t\t\tself.cronListeningCollector.push(listenerName);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tconsole.log('Security schedule error:', e.toString());\n\t\t\t\t\t\t}\n\n\t\t\t\t\t})\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t} else {\n\t\tthis.cronListeningCollector.forEach(function(listenerName) {\n\t\t\tvar condition = listenerName.split('.')[0];\n\n\t\t\tself.controller.emit(\"cron.removeTask\", \"listenerName\");\n\n\t\t\tif (condition === 'arm') {\n\t\t\t\tself.controller.off(listenerName, self.pollArm);\n\t\t\t} else if (condition === 'disarm') {\n\t\t\t\tself.controller.off(listenerName, self.pollDisarm);\n\t\t\t}\n\t\t});\n\t}\n\n\tconsole.log('### this.cronListeningCollector:', JSON.stringify(this.cronListeningCollector));\n};\n\n/**\n * checks if scheduler has to do sth\n * @param timeSchedule\n * @param condition\n * @returns {boolean}\n */\nSecurity.prototype.analyseSchedule = function(timeSchedule, condition) {\n\tvar self = this;\n\tvar back = false;\n\tvar check = new Date();\n\ttimeSchedule.forEach(function(timeSet) {\n\t\tif (check.getHours() === timeSet.time.hour && check.getMinutes() === timeSet.time.minute &&\n\t\t\ttimeSet.weekday === check.getDay() && timeSet.condition === condition) {\n\t\t\tback = true;\n\t\t\treturn back;\n\t\t}\n\t});\n\treturn back;\n\n\n};\n/**\n * reads the Alpaca Data for the schedules and make the Usefull for the Scheduler\n * @param timeSchedule\n * @returns {Array}\n */\nSecurity.prototype.scheduleAnalyse = function(timeSchedule) {\n\tvar self = this,\n\t\tanalysed = [];\n\n\t/*Date.prototype.setDay = function (dayOfWeek) {\n\t    var distance = ( (dayOfWeek - this.getDay()) % 7);\n\t    this.setDate(this.getDate() + distance);\n\t};*/\n\t/*for (var i = 0; i <= 6; i++) {\n\t    if (inPut[i].length > 0) {\n\t        weekdays.push(i);\n\t    }\n\t}*/\n\n\tObject.keys(timeSchedule).forEach(function(key) {\n\t\tvar time = {\n\t\t\tminute: parseInt(timeSchedule[key].time.split(\":\")[1], 10),\n\t\t\thour: parseInt(timeSchedule[key].time.split(\":\")[0], 10)\n\t\t};\n\n\t\tif (timeSchedule[key].length > 0) {\n\n\t\t\tanalysed.push({\n\t\t\t\tweekday: key,\n\t\t\t\ttime: time,\n\t\t\t\tcondition: timeSchedule[key].condition\n\t\t\t});\n\t\t}\n\t});\n\n\treturn analysed;\n};\n/**\n * Main Method defines what happend at the State Methods and Changes\n */\nSecurity.prototype.initStates = function() {\n\tvar self = this;\n\n\t//--Initial-State--\n\tself.initState = new this.State(this.StateStatus, this.StateEnum.INITIAL,\n\t\tfunction() {},\n\t\tfunction() {\n\t\t\tself.vDevALARM.performCommand(\"on\");\n\n\t\t},\n\t\tfunction() {});\n\t//--OFF-State--\n\tself.off = new this.State(this.StateStatus, this.StateEnum.OFF, function() {\n\t\tif (self.vDev.get(\"metrics:level\") !== \"off\") {\n\t\t\tself.shiftTriggerDevices(self.disconfirmDatas, self.disconfirmNots, 'disarm');\n\t\t}\n\t\tself.vDev.set(\"metrics:state\", self.StateEnum.OFF);\n\t\tself.vDev.set(\"metrics:level\", 'off');\n\t\tself.vDev.set(\"metrics:Rlevel\", 'off');\n\t\tself.vDev.set(\"metrics:Clevel\", self.performEnum.COFF.name);\n\t\tself.endschedule();\n\t}, function(args) {\n\t\tself.schedule();\n\t}, function() {});\n\t//--Online-State--\n\tself.liveOn = new this.State(this.StateStatus, this.StateEnum.LIVEON, function() {\n\t\tself.vDev.set(\"metrics:state\", self.StateEnum.LIVEON);\n\t\tself.vDev.set(\"metrics:level\", 'pending');\n\t}, function(args) {\n\t\t// Check if possible to start arming\n\t\tif (self.requiredDevicesInit()) {\n\t\t\tself.shiftTriggerDevices(self.confirmDatas, self.confirmNots, 'arm');\n\n\t\t\t// If Entrance Group not empty, so run the timer to ignore Entrance Group at start\n\t\t\tif (self.entranceGroup.length > 0) {\n\t\t\t\tconsole.log(\"--- Security. Arming without Entrance Group. Wait \",self.delayForEntranceGroup, \" seconds for full arming\");\n\t\t\t\tself.timerEntranceGroupAtStart = setTimeout(function () {\n\t\t\t\t\tconsole.log(\"--- Security. Full Arming with Entrance Group\");\n\t\t\t\t\tself.vDev.set(\"metrics:level\", 'on');\n\t\t\t\t\tself.vDev.set(\"metrics:Clevel\", self.performEnum.CON.name);\n\t\t\t\t\tvar triggeredDevice = self.triggeredAtStart();\n\t\t\t\t\tif (triggeredDevice) {\n\t\t\t\t\t\tself.vDev.performCommand(self.performEnum.TRIGGER.name, triggeredDevice);\n\t\t\t\t\t}\n\t\t\t\t\tself.timerEntranceGroupAtStart = null;\n\t\t\t\t}, self.delayForEntranceGroup * 1000);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.log(\"--- Security. Full Arming with Entrance Group\");\n\t\t\t\tself.vDev.set(\"metrics:level\", 'on');\n\t\t\t\tself.vDev.set(\"metrics:Clevel\", self.performEnum.CON.name);\n\t\t\t\tvar triggeredDevice = self.triggeredAtStart();\n\t\t\t\tif (triggeredDevice) {\n\t\t\t\t\tself.vDev.performCommand(self.performEnum.TRIGGER.name, triggeredDevice);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse {\n\t\t\tvar armFailureDevice = self.armFailureDatas.map(function(i) { return i.devices + \" = \" + i.level});\n\t\t\t// Run Failed Arming Actions\n\t\t\tself.shiftTriggerDevices(self.armFailureDatas, self.armFailureNots, 'disarm');\n\t\t\tself.log(\"warning\", self.langFile.arm_fail + armFailureDevice.toString() , false);\n\n\t\t\t// Disarming TEST\n\t\t\tself.vDev.set(\"metrics:level\", 'off');\n\t\t\tself.vDev.performCommand(self.performEnum.COFF.name);\n\t\t}\n\t}, function() {\n\t\t//self.shiftTriggerDevices(self.disconfirmDatas, self.disconfirmNots, 'disarm');\n\t});\n\t//--Alarming-State--\n\tself.alarmed = new this.State(this.StateStatus, this.StateEnum.ALARMED, function() {\n\t\tself.vDev.set(\"metrics:state\", self.StateEnum.ALARMED);\n\t\tself.vDev.set(\"metrics:level\", 'alarmed');\n\t\tself.vDev.set(\"metrics:Rlevel\", 'on');\n\t}, function(args) {\n\t\tif (args && args.device) {\n\t\t\tself.alarmTriggering(self.controller.devices.get(args.device).get(\"metrics:title\"));\n\t\t} else {\n\t\t\tself.alarmTriggering(\"By Scene\");\n\t\t}\n\n\t}, function() {\n\t\tself.alarmCancel();\n\t});\n};\n/**\n * Triggering the Alarm and starts the repeat timer\n * @param alarmMsg\n */\nSecurity.prototype.alarmTriggering = function(alarmMsg) {\n\tvar self = this;\n\n\tif (self.interval) {\n\t\tself.alarmInterval = this.minuteStandart * 1000 * self.interval;\n\t} else {\n\t\tself.alarmInterval = null;\n\t}\n\tif (self.silent) {\n\t\tself.alarmDelay = this.secondStandart * 1000 * self.silent;\n\t} else {\n\t\tself.alarmDelay = null;\n\t}\n\n\tif (!self.alarmtimer) {\n\t\tself.silenttriggerFunction(alarmMsg);\n\n\t\t// if no silent alarm, immediately fire normal alarm\n\t\tif (!self.alarmDelay) {\n\t\t\tself.triggerFunction(alarmMsg);\n\n\t\t\t// if needed setup repeat of alarm\n\t\t\tif (self.alarmInterval) {\n\t\t\t\tself.alarmtimer = setInterval(function() {\n\t\t\t\t\tself.triggerFunction(alarmMsg);\n\t\t\t\t}, self.alarmInterval);\n\t\t\t}\n\t\t// else wait for specific time\n\t\t} else {\n\t\t\tself.alarmtimerS2 = setInterval(function() {\n\n\t\t\t\tclearInterval(self.alarmtimerS2);\n\t\t\t\tself.alarmtimerS2 = null;\n\n\t\t\t\t// trigger alarm\n\t\t\t\tself.triggerFunction(alarmMsg);\n\n\t\t\t\t// if needed setup repeat of alarm\n\t\t\t\tif (self.alarmInterval) {\n\t\t\t\t\tself.alarmtimer = setInterval(function() {\n\t\t\t\t\t\tself.triggerFunction(alarmMsg);\n\t\t\t\t\t}, self.alarmInterval);\n\t\t\t\t}\n\t\t\t}, self.alarmDelay);\n\t\t}\n\t}\n};\n/**\n * Triggers the silent Alarms and his Timers\n * @param alarmMsg\n */\nSecurity.prototype.silenttriggerFunction = function(alarmMsg) {\n\tthis.log(\"warning\", this.langFile.alarm + alarmMsg, false);\n\tthis.shiftTriggerDevices(this.silentalarmDatas, this.silentalarmNots, 'arm');\n};\n/**\n * broadcast the Alarm to all Alarming devices and the Log and the own Alarm Scene Vdev\n * @param alarmMsg\n */\nSecurity.prototype.triggerFunction = function(alarmMsg) {\n\tthis.log(\"warning\", this.langFile.alarm_with_delay + alarmMsg, false);\n\tthis.controller.emit(\"alarm\", this);\n\tthis.vDevALARM.performCommand(\"on\");\n\n\tthis.shiftTriggerDevices(this.alarmDatas, this.alarmNots, 'arm');\n};\n/**\n * Second Main Method for State Transitions\n * @param condition before Condition when an Transition happends if wrong command gets ignored\n * @param newState state after the transition\n * @param args Arguments for the Make Method\n */\nSecurity.prototype.transition = function(condition, newState, args) {\n\tvar self = this;\n\tif (condition) {\n\t\tself.state.doExit();\n\t\t//newState.doEntry();\n\t\tself.state = newState;\n\t\tself.state.doEntry();\n\t\tself.state.doMake(args);\n\n\t}\n};\n\n/**\n * Condition for Trigger Transition\n * @returns {boolean}\n */\nSecurity.prototype.canTrigger = function() {\n\tvar self = this;\n\treturn self.state.stateEnum === this.StateEnum.LIVEON;\n\n};\n/**\n * Condition for Pending Transition\n * @returns {boolean}\n */\nSecurity.prototype.canTimer = function() {\n\tvar self = this;\n\treturn self.state.stateEnum === this.StateEnum.LIVEON;\n\n};\n/**\n * Condition for get the Module alarm ready\n * @returns {boolean}\n */\nSecurity.prototype.canOn = function() {\n\tvar self = this;\n\tif (self.state.stateEnum !== this.StateEnum.OFF) {\n\t\treturn false;\n\t}\n\treturn true;\n};\n/**\n * Condition for get the Module off\n * @returns {boolean}\n */\nSecurity.prototype.canOff = function() {\n\tvar self = this;\n\treturn [this.StateEnum.LIVEON, this.StateEnum.INITIAL].indexOf(self.state.stateEnum) !== -1;\n};\n/**\n * Condition for reset alarmed\n * @returns {boolean}\n */\nSecurity.prototype.canReset = function() {\n\tvar self = this;\n\treturn self.state.stateEnum === this.StateEnum.ALARMED;\n};\n/**\n * Looks if all Devices are on the right state that the module can get alarm ready\n * @returns {boolean}\n */\nSecurity.prototype.triggeredAtStart = function() {\n\tvar self = this;\n\tvar back = false;\n\n\tif (self.sensorsDatas) {\n\t\tself.sensorsDatas.forEach(\n\t\t\tfunction(args) {\n\t\t\t\tif (self.controller.devices.get(args.devices) && self.controller.devices.get(args.devices).get(\"metrics:level\") === args.conditions) {\n\t\t\t\t\tback = args.devices;\n\t\t\t\t\tself.lastTrigger(self.lastTriggerList, self.controller.devices.get(args.devices));\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\treturn back;\n};\n\n/**\n * Looks if Devices required for arming are on the right state that the module can get alarm ready\n * @returns {boolean}\n */\nSecurity.prototype.requiredDevicesInit = function() {\n\tvar self = this;\n\tvar back = true;\n\tif (self.sensorsDatas) {\n\t\tself.sensorsDatas.forEach(\n\t\t\tfunction(args) {\n\t\t\t\tif (args.armCondition == \"on\" && self.controller.devices.get(args.devices) && self.controller.devices.get(args.devices).get(\"metrics:level\") === args.conditions) {\n\t\t\t\t\tback = false;\n\t\t\t\t\tself.lastTrigger(self.lastTriggerList, self.controller.devices.get(args.devices));\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\tif (self.armingDevicesData) {\n\t\tself.armingDevicesData.forEach(\n\t\t\tfunction(args) {\n\t\t\t\tif (self.controller.devices.get(args.devices) && self.controller.devices.get(args.devices).get(\"metrics:level\") !== args.conditions) {\n\t\t\t\t\tback = false;\n\t\t\t\t\tself.lastTrigger(self.lastTriggerList, self.controller.devices.get(args.devices));\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\t}\n\n\treturn back;\n};\n\n/**\n * making the HTML REST RETURN for an command\n * @param code\n * @param message\n * @returns {{code: *, runningState: *, modulinfo: {id: string}}}\n */\nSecurity.prototype.makeReturnState = function(code, message) {\n\tvar self = this;\n\treturn {\n\t\t'code': code,\n\t\t'runningState': message,\n\t\t'modulinfo': {\n\t\t\tid: \"Security_\" + self.id\n\t\t}\n\t};\n};\n/**\n * writing log to console and UI\n * @param level\n * @param message\n * @param stringify\n */\nSecurity.prototype.log = function(level, message, stringify) {\n\tvar self = this;\n\tvar prefix = this.langFile.security;\n\tif (stringify) {\n\t\tself.controller.addNotification(level, prefix + JSON.stringify(message, null, 4), \"module\", \"Security\");\n\t\t//console.log(prefix + JSON.stringify(message, null, 4));\n\t} else {\n\t\tself.controller.addNotification(level, prefix + message, \"module\", \"Security\");\n\t\t//console.log(prefix + message);\n\t}\n};\n\nSecurity.prototype.contains = function(array, obj) {\n\tvar i = array.length;\n\twhile (i--) {\n\t\tif (array[i] === obj) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\nSecurity.prototype.test = function() {\n\tvar self = this;\n\tself.alarmTriggering(\"x\");\n};\n\nSecurity.prototype.doOnDeviceArray = function doOnDeviceArray(deviceArray, bin) {\n\tvar self = this;\n\tdeviceArray.forEach(function(name) {\n\t\tif (self.controller.devices.get(name.devices)) {\n\t\t\tswitch (self.controller.devices.get(name.devices).get(\"deviceType\")) {\n\t\t\t\tcase 'switchBinary':\n\t\t\t\t\tself.controller.devices.get(name.devices).performCommand(bin);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t});\n};\n/**\n * Ends the Alarm and cleans the timer\n */\nSecurity.prototype.alarmCancel = function() {\n\tclearInterval(this.alarmtimer);\n\tclearInterval(this.alarmtimerS2);\n\tclearInterval(this.alarmSilenttimerS2);\n\tthis.alarmtimer = null;\n\tthis.alarmSilenttimerS2 = null;\n\tthis.alarmtimerS2 = null;\n\tthis.doOnDeviceArray(this.alarmDatas, \"off\");\n\tif (this.vDevALARM) {\n\t\tthis.vDevALARM.performCommand(\"on\");\n\t}\n\tif (this.alarmDevice) {\n\t\tthis.alarmDevice = null;\n\t}\n\n\tthis.shiftTriggerDevices(this.cleanDatas, this.cleanNots, 'arm');\n};\n\n/**\n * Stops scheduling\n */\nSecurity.prototype.endschedule = function() {\n\tvar self = this;\n\n\tif (this.timerEntranceGroupAlarm) {\n\t\tclearTimeout(this.timerEntranceGroupAlarm);\n\t\tthis.timerEntranceGroupAlarm = null;\n\t}\n\tif (this.timerEntranceGroupAtStart) {\n\t\tclearTimeout(this.timerEntranceGroupAtStart);\n\t\tthis.timerEntranceGroupAtStart = null;\n\t}\n\n\tif (this.timerWaitDevicesAtStart) {\n\t\tclearTimeout(this.timerWaitDevicesAtStart);\n\t\tthis.timerWaitDevicesAtStart = null;\n\t}\n\n\tthis.cronListeningCollector.forEach(function(listenerName) {\n\t\tvar condition = listenerName.split('.')[0];\n\n\t\tself.controller.emit(\"cron.removeTask\", listenerName);\n\n\t\tif (condition === 'arm') {\n\t\t\tself.controller.off(listenerName, self.pollArm);\n\t\t} else if (condition === 'disarm') {\n\t\t\tself.controller.off(listenerName, self.pollDisarm);\n\t\t}\n\t});\n};\n\n/*\n * shift all devices that are triggered on state change\n */\nSecurity.prototype.shiftTriggerDevices = function(datas, notification, level) {\n\tvar self = this;\n\tif (datas) {\n\t\tdatas.forEach(function(args) {\n\t\t\t// args([deviceID],[level],[sendAction])\n\t\t\tvar vDev = self.controller.devices.get(args.devices);\n\n\t\t\tif (vDev) {\n\t\t\t\tvar type = vDev.get('deviceType') || null,\n\t\t\t\t\tlevel = vDev.get('metrics:level'),\n\t\t\t\t\tset = args.sendAction ? args.level !== vDev.get('metrics:level') : true;\n\t\t\t\t\n\t\t\t\tif (set) {\n\t\t\t\t\tswitch (type) {\n\t\t\t\t\t\tcase 'switchMultilevel':\n\t\t\t\t\t\t\t_.contains(['on', 'off'], args.level) ? vDev.performCommand(args.level) : vDev.performCommand(\"exact\", {\n\t\t\t\t\t\t\t\tlevel: args.level\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'switchRGBW':\n\t\t\t\t\t\t\t_.contains(['on', 'off'], new_level) ? vDev.performCommand(args.level) : vDev.performCommand(\"exact\", {\n\t\t\t\t\t\t\t\tred: args.level.r,\n\t\t\t\t\t\t\t\tgreen: args.level.g,\n\t\t\t\t\t\t\t\tblue: args.level.b\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'toggleButton':\n\t\t\t\t\t\t\tvDev.performCommand('on');\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tvDev.performCommand(args.level);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t}\n\n\tif (typeof notification.target && notification.target !== '') {\n\t\tthis.controller.notificationChannelSend(notification.target, notification.message ? notification.message : this.getInstanceTitle());\n\t}\n};\n"
  },
  {
    "path": "modules/Security/lang/en.json",
    "content": "{\n    \"m_title\":\"Security\",\n    \"m_descr\": \"Security\",\n    \"device_used_in_settings\": \" does not exist, but is used in the settings\",\n    \"arm_fail\": \"Arming failure due to \",\n    \"alarm\": \"Alarm! Triggered \",\n    \"alarm_with_delay\": \"Alarm with delay! Triggered \",\n    \"security\": \"Security: \",\n    \"disabled\": \"Disabled\"\n}"
  },
  {
    "path": "modules/Security/lang/ru.json",
    "content": "{\n    \"m_title\":\"Режим охраны\",\n    \"m_descr\": \"Режим охраны\",\n    \"device_used_in_settings\": \" не существует, но используется в настройках\",\n    \"arm_fail\": \"Сбой постановки на охранну из-за \",\n    \"alarm\": \"Тревога! Сработал \",\n    \"alarm_with_delay\": \"Тревога с задержкой! Сработал \",\n    \"security\": \"Режим охраны: \",\n    \"disabled\": \"Отключено\"\n}"
  },
  {
    "path": "modules/Security/module.json",
    "content": "{\n  \"singleton\": true,\n  \"dependencies\": [\n    \"Cron\"\n  ],\n  \"category\": \"system\",\n  \"author\": \"Z-Wave.Me\",\n  \"homepage\": \"http://razberry.z-wave.me\",\n  \"icon\": \"icon.png\",\n  \"moduleName\": \"Security\",\n  \"version\": \"2.1\",\n  \"maturity\": \"stable\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n  },\n  \"defaults\": {\n    \"title\": \"__m_title__\",\n    \"description\": \"__m_descr__\",\n    \"inputArming\": {},\n    \"input\": {},\n    \"alarms\": {},\n    \"silentAlarms\": {},\n    \"clean\": {},\n    \"controls\": {},\n    \"armConfirm\": {},\n    \"disarmConfirm\": {},\n    \"times\": {},\n    \"schedules\": {},\n    \"armFailureAction\": {},\n    \"entranceDetected\": {}\n  },\n  \"schema\": {},\n  \"options\": {}\n}\n\n\n"
  },
  {
    "path": "modules/SecurityMode/index.js",
    "content": "/*** SecurityMode Z-Way HA module *******************************************\n\nVersion: 2.0.0\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthors: Poltorak Serguei <ps@z-wave.me>\n         Yurkin Vitaliy   <aivs@z-wave.me>\nDescription:\n\tImplements Security rules and send notifications and activates scene on rule match.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction SecurityMode (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSecurityMode.super_.call(this, id, controller);\n\n\tvar self = this;\n\t\n\tthis._testRule = function () { // wrapper to correct this and parameters in testRule\n\t\tself.testRule.call(self, null);\n\t};\n\n\t// Create instance variables\n\tthis.timer = null;\n\n\tthis.isSensorsCanReact = 1;\n}\n\ninherits(SecurityMode, AutomationModule);\n\n_module = SecurityMode;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSecurityMode.prototype.init = function (config) {\n\tSecurityMode.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: \"SecurityMode_\"+ this.id,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: \"off\",\n\t\t\t\t\ticon: \"switch\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {},\n\t\t\thandler: function(command, args) {\n\t\t\t\tthis.set(\"metrics:level\", command);\n\t\t\t\t// Reset timer if Security Mode on\n\t\t\t\tif (command === \"on\") {\n\t\t\t\t\tif (this.timer) {\n\t\t\t\t\t\tclearTimeout(this.timer);\n\t\t\t\t\t}\n\t\t\t\t\t// Enable Sensors react \n\t\t\t\t\tself.isSensorsCanReact = 1;\n\t\t\t\t};\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\n\tself.attachDetach({device: this.vDev.id}, true);\n\n\tthis.config.tests.forEach(function(test) {\n\t\tif (test.testType === \"binary\") {\n\t\t\tself.attachDetach(test.testBinary, true);\n\t\t} else if (test.testType === \"multilevel\") {\n\t\t\tself.attachDetach(test.testMultilevel, true);\n\t\t} else if (test.testType === \"remote\") {\n\t\t\tself.attachDetach(test.testRemote, true);\n\t\t}\n\t});\t\n};\n\nSecurityMode.prototype.stop = function () {\n\tvar self = this;\n\n\tif (this.timer) {\n\t\tclearTimeout(this.timer);\n\t}\n\n\tif (this.vDev) {\n\t\tself.attachDetach(this.vDev.id, false);\n\t}\n\t\n\tthis.config.tests.forEach(function(test) {\n\t\tif (test.testType === \"binary\") {\n\t\t\tself.attachDetach(test.testBinary, false);\n\t\t} else if (test.testType === \"multilevel\") {\n\t\t\tself.attachDetach(test.testMultilevel, false);\n\t\t} else if (test.testType === \"remote\") {\n\t\t\tself.attachDetach(test.testRemote, false);\n\t\t}\n\t});\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tSecurityMode.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nSecurityMode.prototype.attachDetach = function (test, attachOrDetach) {\n\tif (attachOrDetach) {\n\t\tthis.controller.devices.on(test.device, \"change:metrics:level\", this._testRule);\n\t\tthis.controller.devices.on(test.device, \"change:metrics:change\", this._testRule);\n\t} else {\n\t\tthis.controller.devices.off(test.device, \"change:metrics:level\", this._testRule);\n\t\tthis.controller.devices.off(test.device, \"change:metrics:change\", this._testRule);\n\t}\n};\n\nSecurityMode.prototype.testRule = function (tree) {\n\n\tvar res = null,\n\t\ttopLevel = !tree;\n\t\tself = this;\n\t\n\tif (!tree) {\n\t\ttree = this.config;\n\t}\n\t\n\tif (this.vDev.get(\"metrics:level\") == \"off\")\n\t\treturn;\n\t\n\tif (!this.isSensorsCanReact) {\n\t\treturn;\n\t};\n\n\tres = false;\n\ttree.tests.forEach(function(test) {\n\t\tif (test.testType === \"multilevel\") {\n\t\t\tres = res || self.op(self.controller.devices.get(test.testMultilevel.device).get(\"metrics:level\"), test.testMultilevel.testOperator, test.testMultilevel.testValue);\n\t\t} else if (test.testType === \"binary\") {\n\t\t\tres = res || (self.controller.devices.get(test.testBinary.device).get(\"metrics:level\") === test.testBinary.testValue);\n\t\t} else if (test.testType === \"remote\") {\n\t\t\tvar dev = self.controller.devices.get(test.testRemote.device);\n\t\t\tres = res || ((_.contains([\"on\", \"off\"], test.testRemote.testValue) && dev.get(\"metrics:level\") === test.testRemote.testValue) || (_.contains([\"upstart\", \"upstop\", \"downstart\", \"downstop\"], test.testRemote.testValue) && dev.get(\"metrics:change\") === test.testRemote.testValue));\n\t\t}\n\t});\n\t\n\t\n\tif (topLevel && res) {\n\t\tvar self = this;\n\n\t\t// Disable sensors react to next period\n\t\tself.isSensorsCanReact = 0;\n\t\tself.timer = setTimeout(function () {\n\t\t\t// Enable Sensors react after timeout\n\t\t\tself.isSensorsCanReact = 1;\n\t\t\t// And clearing out this.timer variable\n\t\t\tself.timer = null;\n\t\t}, self.config.timeout*1000);\n\n\t\t// Send Notification\n\t\tself.addNotification(\"warning\", self.message, \"module\");\n\t\tself.controller.emit('SecurityMode.alert', self);\n\n\t\ttree.action.switches && tree.action.switches.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t}\n\t\t});\n\t\ttree.action.dimmers && tree.action.dimmers.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tvDev.performCommand(\"exact\", { level: devState.status });\n\t\t\t}\n\t\t});\n\t\ttree.action.locks && tree.action.locks.forEach(function(devState) {\n\t\t\tvar vDev = self.controller.devices.get(devState.device);\n\t\t\tif (vDev) {\n\t\t\t\tvDev.performCommand(devState.status);\n\t\t\t}\n\t\t});\n\t\ttree.action.scenes && tree.action.scenes.forEach(function(scene) {\n\t\t\tvar vDev = self.controller.devices.get(scene);\n\t\t\tif (vDev) {\n\t\t\t\tvDev.performCommand(\"on\");\n\t\t\t}\n\t\t});\n\t}\n};\n\nSecurityMode.prototype.op = function (dval, op, val) {\n\tif (op === \"=\") {\n\t\treturn dval === val;\n\t} else if (op === \"!=\") {\n\t\treturn dval !== val;\n\t} else if (op === \">\") {\n\t\treturn dval > val;\n\t} else if (op === \"<\") {\n\t\treturn dval < val;\n\t} else if (op === \">=\") {\n\t\treturn dval >= val;\n\t} else if (op === \"<=\") {\n\t\treturn dval <= val;\n\t}\n\t\t\n\treturn null; // error!!  \n};\n"
  },
  {
    "path": "modules/SecurityMode/lang/de.json",
    "content": "{\n\t\"m_title\":\"Sicherheitsmodus\",\n\t\"m_descr\":\"Der Sicherheitsmodus ermöglicht es bestimmte Szenarien/Aktionen abhängig vom Gerätestatus auszulösen. Sends a notification of type 'Warning' if one sensor of all triggered.\",\n\t\"action_msg\":\"Alarm!\",\n\t\"l_tests\":\"Sensoren:\",\n\t\"l_test_binary\":\"Binäre Bedingung\",\n\t\"l_test_multi\":\"Multilevel Bedingung\",\n\t\"l_tests_remote\":\"Fernbedienbefehl\",\n\t\"l_timeout\":\"Idle time after last sensor trigger\",\n\t\"h_timeout\":\"If any of the sensors triggered during this period, no additional message will be sent to reduce spam\",\n\t\"l_action\":\"Aktionen\",\n\t\"l_message\":\"Textnachricht:\",\n\t\"l_phone\":\"Telefonnummer an die eine SMS mit der Benachrichtigung geschikt werden soll. (z.B 79261234567)\",\n\t\"l_api_key_sms\":\"API-Key von sms.ru\",\n\t\"h_api_key_sms\":\"Nach der Registrierung auf sms.ru finden Sie auf der rechten Seite die benötigte 'api_id' (z.B. a43f6376-f57d-27e4-5981-ec48945d871f)\",\n\t\"l_email\":\"E-Mail-Adresse:\",\n\t\"l_api_key_email\":\"API key from https://mandrillapp.com\",\n\t\"h_api_key_email\":\"After registration email on the tab Setting create a key (looks like: VFfeEspkFL1YqVSihhfqHw)\",\n\t\"l_switches\":\"Schalter:\",\n\t\"on\":\"An\",\n\t\"off\":\"Aus\",\n\t\"l_dimmers\":\"Dimmer/Motorsteuerungen:\",\n\t\"l_status\":\"Status\",\n\t\"l_locks\":\"Schlösser:\",\n\t\"open\":\"Entriegeln\",\n\t\"close\":\"Verriegeln\",\n\t\"l_scenes\":\"Zu aktivierende Szenarios/Aktionen:\"\n}"
  },
  {
    "path": "modules/SecurityMode/lang/en.json",
    "content": "{\n\t\"m_title\":\"Security Mode\",\n\t\"m_descr\":\"This complex application will realize a complete House Alarm system using existing Z-Wave already installed in your home. You define they way to arm and to disarm the alarm and what devices will trigger an alarm condition. The app will create a new element that shows the alarm status and allows to arm and to disarm the alarm system as well. Furthermore the app allows defining the actions to be done and the alerts to be sent out on case of an alarm.<br><br>Settings:<br><ul><li>Pick all devices that shall arm and disarm the event. On default the element on the UI will do this all the time. That’s why it is ok not to define any further devices fort he arm/disarm control. In case you want to have a remote control or any other mobile device to arm/disarm the alarm you will need to install the app „Trap events from remotes“ first. You can also define any actor or sensor to arm and disarm the system. Examples for this are „As soon as the TV is turned off arm the alarm“ or „as soon as the light in bathroom turns on, disarm the alarm“. However you should note that a direct control of a publicly accessible device like the bathroom light switch my compromise your security system. A particularly smart idea is to disarm the alarm in case of a successful use of a user code on the main door lock.</li><li>Pick the devices that shall trip the alarm. These are usually door/window sensors, window handles, glass breaking sensors but can also be e.g. the light switch in the main lobby</li><li>Define the action to be done in case of a tripping alarm (when armed). This can be turning on a light switch or using one of the out-of-Band notifiers like SMS. With every action you can setup a delay time This allows you to escalate actions</li></ul><br>Usage: The Security App will create one new element in the UI showing status of the Alarm and offering to arm/disarm the system. Sends a notification of type 'Warning' if one sensor of all triggered.\",\n\t\"action_msg\":\"Alert!\",\n\t\"l_tests\":\"Sensors:\",\n\t\"l_test_binary\":\"Binary condition\",\n\t\"l_test_multi\":\"Multilevel condition\",\n\t\"l_tests_remote\":\"Remote condition\",\n\t\"l_timeout\":\"Idle time in seconds after last sensor trigger\",\n\t\"h_timeout\":\"If any of the sensors triggered during this period, no additional message will be sent to reduce spam\",\n\t\"l_action\":\"Actions\",\n\t\"l_message\":\"Text message\",\n\t\"l_phone\":\"Phone number to send SMS. In form of 79261234567\",\n\t\"l_api_key_sms\":\"API key from http://sms.ru\",\n\t\"h_api_key_sms\":\"After registration on the right you will see api_id (looks like: a43f6376-f57d-27e4-5981-ec48945d871f)\",\n\t\"l_email\":\"Email that will be notified\",\n\t\"l_api_key_email\":\"API key from https://mandrillapp.com\",\n\t\"h_api_key_email\":\"After registration email on the tab Setting create a key (looks like: VFfeEspkFL1YqVSihhfqHw)\",\n\t\"l_switches\":\"List of switches:\",\n\t\"on\":\"On\",\n\t\"off\":\"Off\",\n\t\"l_dimmers\":\"List of dimmers:\",\n\t\"l_status\":\"Level\",\n\t\"l_locks\":\"List of locks:\",\n\t\"open\":\"Open\",\n\t\"close\":\"Close\",\n\t\"l_scenes\":\"List of scenes to activate:\"\n}"
  },
  {
    "path": "modules/SecurityMode/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Режим охраны\",\n\t\"m_descr\":\"Режим охраны позволяет переводить датчики в режим охраны для запуска охранных сцен и включения устройств, например сирен. Отправляет уведомления типа 'Предупреждение' при срабатывании любого из датчиков.\",\n\t\"action_msg\":\"Сработал охранный датчик\",\n\t\"l_tests\":\"Датчики\",\n\t\"l_test_binary\":\"Условие бинарных устройств\",\n\t\"l_test_multi\":\"Условие многоканальных устройств\",\n\t\"l_tests_remote\":\"Условие кнопок пульта\",\n\t\"l_timeout\":\"Отправлять сообщения не чаще, чем 1 раз в указанное время\",\n\t\"h_timeout\":\"Если сработал любой из датчиков, то в течении заданного времени в секундах датчики не будут повторно реагировать, чтобы не спамить\",\n\t\"l_action\":\"Действия\",\n\t\"l_message\":\"Текстовое сообщение\",\n\t\"l_phone\":\"Номер телефона на который будет отправляться СМС. Формат: 79261234567\",\n\t\"l_api_key_sms\":\"API ключ с сайта http://sms.ru\",\n\t\"h_api_key_sms\":\"После регистрации телефона на http://sms.ru в правой колонке появится ключ api_id (пример: a43f6376-f57d-27e4-5981-ec48945d871f)\",\n\t\"l_email\":\"Email адрес на который будет отправляться сообщение\",\n\t\"l_api_key_email\":\"API ключ с сайта https://mandrillapp.com\",\n\t\"h_api_key_email\":\"После регистрации email на https://mandrillapp.com в разделе Setting создайте ключ (пример: VFfeEspkFL1YqVSihhfqHw)\",\n\t\"l_switches\":\"Список выключателей\",\n\t\"on\":\"Включить\",\n\t\"off\":\"Выключить\",\n\t\"l_dimmers\":\"Список диммеров\",\n\t\"l_status\":\"Уровень\",\n\t\"l_locks\":\"Список замков\",\n\t\"open\":\"Открыть\",\n\t\"close\":\"Закрыть\",\n\t\"l_scenes\":\"Список сцен\"\n}"
  },
  {
    "path": "modules/SecurityMode/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"complex_applications\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"https://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"SecurityMode\",\n\t\"version\": \"2.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"tests\": [],\n\t\t\"timeout\": 60,\n\t\t\"action\": {\n\t\t\t\"message\" : \"__action_msg__\"\n\t\t}\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"tests\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\"testType\": {\n\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\"enum\": [\"binary\", \"multilevel\",\"remote\"],\n\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\"default\": \"binary\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testBinary\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\" : \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testMultilevel\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_battery:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"=\", \"!=\", \">\", \">=\", \"<\", \"<=\"],\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"number\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"testRemote\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"dependencies\": \"testType\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"testValue\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\", \"upstart\", \"upstop\", \"downstart\", \"downstop\"],\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"default\" : \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"action\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"switches\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"enum\": [\"off\", \"on\"],\n\t\t\t\t\t\t\t\t\t\"default\" : \"on\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dimmers\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\t\t\t\"maximum\": 99\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"locks\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"type\": \"object\",\n\t\t\t\t\t\t\t\"properties\": {\n\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId\",\n\t\t\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\t\t\t\"enum\": [\"close\", \"open\"],\n\t\t\t\t\t\t\t\t\t\"default\" : \"open\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scenes\": {\n\t\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"required\": false\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"tests\": {\n\t\t\t\t\"label\": \"__l_tests__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"testType\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"default\": \"\"\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testBinary\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_test_binary__\",\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"binary\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testMultilevel\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_test_multi__\",\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"multilevel\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"testOperator\": {\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"=\", \"≠\", \">\", \"≥\", \"<\", \"≤\"]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"testRemote\": {\n\t\t\t\t\t\t\t\t\"label\": \"__l_tests_remote__\",\n\t\t\t\t\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\t\t\t\t\"testType\": \"remote\"\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"label\": \"__l_timeout__\",\n\t\t\t\t\"helper\": \"__h_timeout__\"\n\t\t\t},\n\t\t\t\"action\": {\n\t\t\t\t\"label\": \"__l_action__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"message\": {\n\t\t\t\t\t\t\"label\": \"__l_message__\"\n\t\t\t\t\t},\n\t\t\t\t\t\"switches\": {\n\t\t\t\t\t\t\"label\": \"__l_switches__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__off__\", \"__on__\"]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"dimmers\": {\n\t\t\t\t\t\t\"label\": \"__l_dimmers__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"__l_status__\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"integer\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"locks\": {\n\t\t\t\t\t\t\"label\": \"__l_locks__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\t\t\"device\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName\"\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\"status\": {\n\t\t\t\t\t\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": [\"__close__\", \"__open__\"]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t\"scenes\": {\n\t\t\t\t\t\t\"label\": \"__l_scenes__\",\n\t\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/SensorValueLogging/index.js",
    "content": "/*** SensorValueLogging Z-Way Home Automation module *************************************\n\n Version: 1.0.1\n (c) Z-Wave.Me, 2014\n\n -----------------------------------------------------------------------------\n Author: Poltorak Serguei <ps@z-wave.me>\n Description:\n\t Log sensor value in JSON file\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction SensorValueLogging (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSensorValueLogging.super_.call(this, id, controller);\n};\n\ninherits(SensorValueLogging, AutomationModule);\n\n_module = SensorValueLogging;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSensorValueLogging.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tSensorValueLogging.super_.prototype.init.call(this, config);\n\n\t// Remember \"this\" for detached callbacks (such as event listener callbacks)\n\tvar self = this;\n\n\tthis.handler = function (vDev) {\n\t\tif (self.config.logTo === \"JSONFile\") {\n\t\t\tvar storedLog = loadObject(\"SensorValueLogging_\" + vDev.id + \"_\" + self.id);\n\t\t\tif (!storedLog) {\n\t\t\t\tstoredLog = {\n\t\t\t\t\tdeviceId: vDev.id,\n\t\t\t\t\tdeviceName: vDev.get(\"metrics:title\"),\n\t\t\t\t\tsensorData: []\n\t\t\t\t};\n\t\t\t}\n\t\t\tstoredLog.sensorData.push({\"time\": Date.now(), \"value\": vDev.get(\"metrics:level\")});\n\t\t\tsaveObject(\"SensorValueLogging_\" + vDev.id + \"_\" + self.id, storedLog, 60);\n\t\t\tstoredLog = null;\n\t\t}\n\t\t\n\t\tif (self.config.logTo === \"HTTPGET\") {\n\t\t\thttp.request({\n\t\t\t\tmethod: 'GET',\n\t\t\t\turl: self.config.url.replace(\"${id}\", vDev.id).replace(\"${value}\", vDev.get('metrics:level'))\n\t\t\t});\n\t\t}\n\t};\n\n\t// Setup metric update event listener\n\tthis.controller.devices.on(this.config.device, \"change:metrics:level\", this.handler);\n};\n\nSensorValueLogging.prototype.stop = function () {\n\tSensorValueLogging.super_.prototype.stop.call(this);\n\n\tthis.controller.devices.off(this.config.device, \"change:metrics:level\", this.handler);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n// This module doesn't have any additional methods\n"
  },
  {
    "path": "modules/SensorValueLogging/lang/de.json",
    "content": "{\n\t\"m_title\":\"Sensorwert Protokollierung\",\n\t\"m_descr\":\"Mit dieser App können alle im Smart Home gesammelten Informationen protokolliert und über einen externen Dienstleister gespeichert werden. Z-way bietet weder einen Aufzeichnungsservice noch eine Datenanalysesoftware an. Dafür gibt es genügend Dienste im Internet. Die Anwendung dieser App erfordert detaillierte Kenntnisse im Datalogging Interface und Analytics-Service.<br><br>Einstellungen:<br><ul><li> <li>Wählen Sie den Sensorwert aus, den sie aufzeichnen wollen.</li><li>Bestimmen Sie die Methode (JSON oder HTTP), mit welcher Sie die Werte an einen Online Dienst Ihrer Wahl senden wollen. </li><li>Definieren Sie den HTTP Befehl, den Sie anwenden, um den Wert an ein Online-Logging-Service zuzustellen. Das gilt nur für Protokollierungsdienste Dritter. Für deren Serviceleistungen benötigen Sie eventuell ein eingerichtetes Konto.</li></ul>\",\n\t\"l_device\":\"Sensor der protokolliert werden soll:\",\n\t\"l_logTo\":\"Wie soll protokolliert werden?\",\n\t\"l_logTo_json\":\"als JSON-Datei im Z-Way Speicher\",\n\t\"l_logTo_http\":\"als HTTP-Request versenden\",\n\t\"l_url\":\"Sende einen HTTP-Request an: \",\n\t\"h_url\":\"Example: http://meindomainname.org/pfad/zu/irgendwas/${id}?meinwert=${value} - '${id}' und '${value}' werden mit der Sensor ID und dem entsprechenden Wert ersetzt.\"\n}\n"
  },
  {
    "path": "modules/SensorValueLogging/lang/en.json",
    "content": "{\n\t\"m_title\":\"Sensor Values Logging\",\n\t\"m_descr\":\"This app allows recording all information gathered in the Smart Home System and store them on an external service. Z-way does not offer any recording service or data analytics software but there are services in the Internet doing this. The use of this app requires detailed knowledge about the interface of the data logging and analytics service used.<br><br>Settings:<br><ul><li> Pick the sensor value you want to log.</li><li>Pick the method (JSON or HTTP) you want to use to send the values to an online service of your choice.</li><li>Define the HTTP command to use to deliver the value to an online logging service. This is for third party logging services only. You may need to setup an account with such a service.</li></ul>\",\n\t\"l_device\":\"Sensor to log\",\n\t\"l_logTo\":\"How to store:\",\n\t\"l_logTo_json\":\"to JSON file in storage\",\n\t\"l_logTo_http\":\"send via HTTP request\",\n\t\"l_url\":\"HTTP request to do. Strings ${id} and ${value} are replaced by sensor ID and value correspondingly\",\n\t\"h_url\":\"Example: http://mydomainname.org/path/to/something/${id}?myval=${value}\"\n}"
  },
  {
    "path": "modules/SensorValueLogging/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Логирование значений датчиков\",\n\t\"m_descr\":\"Сохранять значения датчиков в JSON файл или отправлять HTTP запрос на ваш сервер база данных.\",\n\t\"l_device\":\"Датчик\",\n\t\"l_logTo\":\"Способ сохранения значений датчика:\",\n\t\"l_logTo_json\":\"в JSON файл в папке storage/\",\n\t\"l_logTo_http\":\"отправлять HTTP запрос\",\n\t\"l_url\":\"Задайте HTTP запрос. Строки ${id} и ${value} в запросе заменяются на ID датчика и его значение\",\n\t\"h_url\":\"Например: http://mydomainname.org/path/to/something/${id}?myval=${value}\"\n}"
  },
  {
    "path": "modules/SensorValueLogging/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"support_external_dev\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"SensorValueLogging\",\n\t\"version\": \"1.0.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"device\": \"\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"device\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId,namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId,namespaces:devices_doorlock:deviceId,namespaces:devices_switchControl:deviceId,namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"logTo\": {\n\t\t\t\t\"enum\": [\"JSONFile\", \"HTTPGET\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"url\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"depends\": \"logTo\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"logTo\"\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"device\": {\n\t\t\t\t\"label\": \"__l_device__\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName,namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName,namespaces:devices_doorlock:deviceName,namespaces:devices_switchControl:deviceName,namespaces:devices_toggleButton:deviceName\"\n\t\t\t},\n\t\t\t\"logTo\": {\n\t\t\t\t\"label\": \"__l_logTo__\",\n\t\t\t\t\"optionLables\": [\"__l_logTo_json__\", \"__l_logTo_http__\"]\n\t\t\t},\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__l_url__\",\n\t\t\t\t\"helper\": \"__h_url__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"logTo\": \"HTTPGET\"\n\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/SensorsPolling/htdocs/js/postRender.js",
    "content": "function modulePostRender() {\n\n\tvar self = this,\n\t\tbatteries = [],\n\t\tnodeMarkers = [];\n\n\t$('#alpaca_data .nonBatteryDevices').bind('DOMNodeInserted', 'select[name^=devices_]', function () {\n\t  \t\n\t\tif (batteries.length < 1) {\n\t\t\tbatteries = $(this).find('option').filter(function() { return $(this).val() === $(this).text(); });\n\t\t  \tbatteries = batteries.map( function() { return $(this).val() });\n\n\t\t  \tbatteries = $.each(batteries, function(index, id) {\n\t\t  \t\t\n\t\t  \t\tvar nodeMark = id.split('-');\n\n\t\t  \t\tif (nodeMarkers.indexOf(nodeMark[0]) === -1){\n\t\t  \t\t\tnodeMarkers.push(nodeMark[0]);\n\t\t  \t\t}\n\t\t  \t});\n\t\t}\n\n\t\t$(this).find('option').each(function(index, el) {\n\t\t\tvar nodeMark = $(el).val().split('-');\n\t\t\t\n\t\t\tif(nodeMarkers.indexOf(nodeMark[0]) > -1) {\n\t\t\t\t$(el).hide();\n\t\t\t}\n\t\t});\n\t});\n\n\t\n\n\t$('#alpaca_data .batteryDevices').bind('DOMNodeInserted', 'select[name^=devicesWithBattery_]', function () {\n\t  \t\n\t\tif (batteries.length < 1) {\n\t\t\tbatteries = $(this).find('option').filter(function() { return $(this).val() === $(this).text(); });\n\t\t  \tbatteries = batteries.map( function() { return $(this).val() });\n\n\t\t  \tbatteries = $.each(batteries, function(index, id) {\n\t\t  \t\t\n\t\t  \t\tvar nodeMark = id.split('-');\n\n\t\t  \t\tif (nodeMarkers.indexOf(nodeMark[0]) === -1){\n\t\t  \t\t\tnodeMarkers.push(nodeMark[0]);\n\t\t  \t\t}\n\t\t  \t});\n\t\t}\n\n\t\t$(this).find('option').each(function(index, el) {\n\t\t\tvar nodeMark = $(el).val().split('-');\n\t\t\t\n\t\t\tif(nodeMarkers.indexOf(nodeMark[0]) === -1 || $(el).val() === $(el).text()) {\n\t\t\t\t$(el).hide();\n\t\t\t}\n\t\t});\n\t});\n};"
  },
  {
    "path": "modules/SensorsPolling/index.js",
    "content": "/*** SensorsPolling Z-Way HA module *******************************************\n\nVersion: 1.2.0\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>, Niels Roche <nir@zwave.eu>\nDescription:\n\tThis module periodically requests all sensors\n\tThe period MUST be factor of minues, hours or days. No fraction of minute, hour or day is possible.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction SensorsPolling (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSensorsPolling.super_.call(this, id, controller);\n}\n\ninherits(SensorsPolling, AutomationModule);\n\n_module = SensorsPolling;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSensorsPolling.prototype.init = function (config) {\n\tSensorsPolling.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t// Here we assume that period is factor of minute and less than hour, or factor of hours and less than day, or factor of days\n\tvar p = Math.round(this.config.period);\n\tvar m = (p < 60) ? [0, 59, p] : 0;\n\tvar h = p >= 24*60 ? 0 : (p/60 >=1 ? [0, 23, Math.round(p/60)] : null);\n\tvar wd = p/24/60 >=1 ? [0, 6, Math.round(p/24/60)] : null;\n\tvar currentPoll, lastPoll, devJSON;\n\t \n\tthis.controller.emit(\"cron.addTask\", \"SensorsPolling.poll\", {\n\t\tminute: m,\n\t\thour: h,\n\t\tweekDay: wd,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\tthis.onPoll = function () {\n\n\t\tvar currentPoll = Math.floor(Date.now() / 1000),\n\t\t\tdevicesToUpdate = [],\n\t\t\tbatteries = [],\n\t\t\tdevJSON;\n\n\t\t// if betty devices should not be polled, find their node ids and add them to batteries list\n\t\tif(!self.config.pollDevsWithBatteries) {\n\t\t\tbatteries = self.controller.devices.filter(function(dev) {\n\t\t\t\treturn dev.get('deviceType') === 'battery' && dev.id.split('_').length > 2;\n\t\t\t}).map(function(dev){\n\t\t\t\treturn self.getDevNodeId(dev.id);\n\t\t\t});\n\t\t}\n\n\t\t//update only binary and multilevel sensors that has no change during the update interval\n\t\tdevicesToUpdate = self.controller.devices.filter(function (dev) {\n\t\t\tdevJSON = dev.toJSON();\n\n\t\t\t// check if battery devices should be polled first\n\t\t\tif (batteries.indexOf(self.getDevNodeId(dev.id)) === -1) {\n\t\t\t\treturn  _.unique(self.config.devices).indexOf(dev.id) === -1 && \n\t\t\t\t\t\t\t_.unique(self.config.devicesWithBattery).indexOf(dev.id) === -1 &&\n\t\t\t\t\t\t\t\tdevJSON.updateTime <= lastPoll && \n\t\t\t\t\t\t\t\t\t(dev.get('deviceType') === 'sensorBinary' || \n\t\t\t\t\t\t\t\t\t\tdev.get('deviceType') === 'sensorMultilevel');\n\t\t\t}\n\t\t});\n\n\t\tif (devicesToUpdate.length > 0) {\n\t\t\tdevicesToUpdate.forEach(function (dev) {\n\t\t\t\tdev.performCommand(\"update\");\n\t\t\t});\n\t\t}\n\n\t\tlastPoll = currentPoll;\n\t};\n\t\n\tthis.controller.on('SensorsPolling.poll', self.onPoll);\n};\n\nSensorsPolling.prototype.stop = function () {\n\t\n\tthis.controller.off('SensorsPolling.poll', this.onPoll);\n\tthis.controller.emit(\"cron.removeTask\", \"SensorsPolling.poll\");\n\n\tSensorsPolling.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nSensorsPolling.prototype.getDevNodeId = function (vDevId) {\n\tvar match = vDevId.split('_'),\n\t\tnodeId = null;\n\t\t\n\t\t// should work for all ZWay /-Remote and Enocean devices\n\t\tfor (var i = 0; i < match.length; i++) {\n\t\t\tnodeId = parseInt(match[i]);\n\t\t\t\n\t\t\tif (!_.isNaN(nodeId)) {\n\t\t\t\treturn nodeId;\n\t\t\t}\n\t\t}\n\n\treturn nodeId;\n};"
  },
  {
    "path": "modules/SensorsPolling/lang/de.json",
    "content": "{\n\t\"m_title\":\"Periodische Sensorabfrage\",\n\t\"m_descr\":\"Die Sensorabfrage App veranlasst, dass regelmäßig alle Sensoren ihren Wert im User Interface aktualisieren. Sollte ein Modul nicht aktiv sein, laufen alle Funktionen des Z-Wave Systems zwar weiter, aber die in der UI angezeigten und für Logical Rules verwendeten Werte können veraltet sein. Das bedeutet, um die  Informationen auf der UI möglichst aktuell zu halten, wäre eine häufige Abfrage sehr vorteilhaft. Bei batteriebetriebenen Geräten wird der jüngste Wert durch dessen Aufwach-Intervall definiert. In der Zeit zwischen zwei Aufwachmomenten ruht das Gerät und sendet dem Sensor keine aktuellen Informationen, es sei denn es unterstützt die sogenannte unaufgeforderte Sensorberichterstattung, welche bei Änderungen des Sensorwertes angestoßen wird. Das bedeutet, dass die Abfragefrequenz von batteriebetriebenen Geräten ohnehin begrenzt ist, und häufigere Abfragen damit zu keiner erhöhten Benutzerfreundlichkeit führen können.Am Netz angeschlossene Geräte können dagegen beliebig oft abgefragt werden. Um jedoch eine Überlastung des Z-Wave Netzwerks durch ständige Abfrage- und Antwortpakete zu vermeiden, sollte diese Abfrage stets mit Vorsicht behandelt werden. Die App ermöglicht daher, Geräte von der Abfrage auszuschließen (von Vorteil bei batteriebetriebenen Geräten ohne Aufwachintervall, um deren Batterie zu sparen) und das Abfrageintervall anzupassen.  <br><br>Einstellungen:<br><ul><li>Im Grundzustand werden alle Sensoren im vorgegebenen Intervall abgefragt. Wählen Sie die Sensoren, die Sie von der Abfrage ausschließen möchten in der Dropdownliste aus.</li><li>Wählen Sie das Abfrageintervall.</li></ul>\",\n\t\"l_devices\":\"Keine Abfrage folgender strombetriebener Sensoren:\",\n\t\"l_period\":\"Abfrageintervall für alle Sensoren:\",\n\t\"one_m\":\"1 Minute\", \n\t\"two_m\":\"2 Minuten\", \n\t\"five_m\":\"5 Minuten\", \n\t\"ten_m\":\"10 Minuten\", \n\t\"twenty_m\":\"20 Minuten\", \n\t\"thirty_m\":\"30 Minuten\", \n\t\"one_h\":\"1 Stunde\", \n\t\"two_h\":\"2 Stunden\", \n\t\"four_h\":\"4 Stunden\", \n\t\"six_h\":\"6 Stunden\", \n\t\"half_d\":\"zweimal am Tag\", \n\t\"daily\":\"einmal täglich\", \n\t\"weekly\":\"einmal wöchentlich\",\n\t\"rl_pollBatteries\":\"Erlaube Abfrage von batteriebetriebenen Sensoren\",\n\t\"h_pollBatteries\":\"Achtung! Abhängig vom eingestellten Abfrageintervall, können regelmäßige Statusabfragen von batteriebetriebenen Geräten die Lebenzeit der Batterien deutlich verringern. Seien Sie sich ebenso im klaren darüber, dass einige Geräte mit mehreren Sensoren auch mehrmals wärend der Abfragezeit abgefragt werden - z.B. ein batteriebetriebenes Gerät mit 4 Sensoren wird 4mal aufgeweckt (WakeUp / Wachphase ist standardmäßig auf 20 s gestellt), somit könnte das Gerät bis zu 80 s während der Abfrage wach sein.\",\n\t\"l_batteryDevs\":\"Keine Abfrage folgender batteriebetriebener Sensoren:\"\n}"
  },
  {
    "path": "modules/SensorsPolling/lang/en.json",
    "content": "{\n\t\"m_title\":\"Periodical Sensor Polling\",\n\t\"m_descr\":\"The Sensor Polling App will organize to periodically ask all sensors to update their value into the User Interface. In case the module is not active, all functions of the Z-Wave System will still work but the Values shown in the UI and used for Logical Rules may be just outdated. This means a frequent polling is highly desirable to always the most recent information on the UI. However for battery-operated devices the most recent value is defined by the wakeup interval of the device.  In the time between two wakeups the device remain sleeping and will only report sensor updated if the device supports so called unsolicited sensor reports driven by a change of the sensor value. This means that the polling frequency of a battery-operated device is limited anyway and any more-frequent polling will not increase the user experience. Mains operated devices can be polled as often as you want. In order to prevent the Z-Wave network from overflowing with request and response packets this polling should be handled with care.   Hence the app allows to exclude certain devices from polling (good idea for always awake battery devices to extend their battery life!) and to define the polling interval.<br><br>Settings:<br><ul><li> Select the Sensor you do not want to poll. On default all sensors are polled within the interval set.</li><li>Choose the polling interval.</li></ul>\",\n\t\"l_devices\":\"Do not poll this electrically powered Sensors:\",\n\t\"l_period\":\"Poll period for other devices:\",\n\t\"one_m\":\"1 minute\", \n\t\"two_m\":\"2 minute\", \n\t\"five_m\":\"5 minute\", \n\t\"ten_m\":\"10 minute\", \n\t\"twenty_m\":\"20 minute\", \n\t\"thirty_m\":\"30 minute\", \n\t\"one_h\":\"1 hour\", \n\t\"two_h\":\"2 hours\", \n\t\"four_h\":\"4 hours\", \n\t\"six_h\":\"6 hours\", \n\t\"half_d\":\"12 hours\", \n\t\"daily\":\"daily\", \n\t\"weekly\":\"weekly\",\n\t\"rl_pollBatteries\":\"Poll battery powered Sensors\",\n\t\"h_pollBatteries\":\"Be careful! Depending on the configured interval regularly polling of battery powered devices could reduce there battery lifetime a lot. Be also clear about that some devices with multiple sensors will be woken up multiple times a poll time is triggered - e.g. battery powered device with 4 Sensors will wake up (default is 20s) four times, so this device will about 80s awake during poll time is triggered.\",\n\t\"l_batteryDevs\":\"Do not poll this battery powered Sensors:\"\n}"
  },
  {
    "path": "modules/SensorsPolling/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Периодический опрос устройств\",\n\t\"m_descr\":\"Опрашивать состояние устройств через опредленное время.\",\n\t\"l_devices\":\"Устройства исключенные из опроса:\",\n\t\"l_period\":\"Период опроса\",\n\t\"one_m\":\"1 минута\", \n\t\"two_m\":\"2 минуты\", \n\t\"five_m\":\"5 минут\", \n\t\"ten_m\":\"10 минут\", \n\t\"twenty_m\":\"20 минут\", \n\t\"thirty_m\":\"30 минут\", \n\t\"one_h\":\"1 час\", \n\t\"two_h\":\"2 часа\", \n\t\"four_h\":\"4 часа\", \n\t\"six_h\":\"6 часов\", \n\t\"half_d\":\"12 часов\", \n\t\"daily\":\"1 раз в день\", \n\t\"weekly\":\"1 раз в неделю\",\n\t\"rl_pollBatteries\":\"Poll battery powered Sensors\",\n\t\"h_pollBatteries\":\"Be careful! Depending on the configured interval regularly polling of battery powered devices could reduce there battery lifetime a lot. Be also clear about that some devices with multiple sensors will be woken up multiple times a poll time is triggered - e.g. battery powered device with 4 Sensors will wake up (default is 20s) four times, so this device will about 80s awake during poll time is triggered.\",\n\t\"l_batteryDevs\":\"Do not poll this battery powered Sensors:\"\n}\n"
  },
  {
    "path": "modules/SensorsPolling/module.json",
    "content": "{\n\t\"dependencies\": [\"Cron\"],\n\t\"singleton\": true,\n\t\"category\": \"basic_gateway_modules\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"SensorsPolling\",\n\t\"version\": \"1.2.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"pollDevsWithBatteries\": false,\n\t\t\"devices\": [],\n\t\t\"devicesWithBattery\": [],\n\t\t\"period\": 60\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"pollDevsWithBatteries\":{\n\t\t\t\t\"type\":\"boolean\",\n\t\t\t\t\"required\" : false\n\t\t\t},\n\t\t\t\"period\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [1, 2, 5, 10, 20, 30, 60, 120, 240, 360, 720, 1440, 10080]\n\t\t\t},\n\t\t\t\"devices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId,namespaces:devices_battery:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"devicesWithBattery\": {\n\t\t\t\t\"dependencies\":\"pollDevsWithBatteries\",\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId,namespaces:devices_battery:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"pollDevsWithBatteries\":{\n\t\t\t\t\"type\":\"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_pollBatteries__\",\n\t\t\t\t\"helper\":\"__h_pollBatteries__\"\n\t\t\t},\n\t\t\t\"period\": {\n\t\t\t\t\"label\": \"__l_period__\",\n\t\t\t\t\"optionLabels\": [\"__one_m__\", \"__two_m__\", \"__five_m__\", \"__ten_m__\", \"__twenty_m__\", \"__thirty_m__\", \"__one_h__\", \"__two_h__\", \"__four_h__\", \"__six_h__\", \"__half_d__\", \"__daily__\", \"__weekly__\"]\n\t\t\t},\n\t\t\t\"devices\": {\n\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\"fieldClass\": \"nonBatteryDevices\",\n\t\t\t\t\"actionbar\": {\n\t\t\t\t\t\"actions\": [{\n\t\t\t\t\t\t\"action\": \"up\",\n\t\t\t\t\t\t\"enabled\": false\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"action\": \"down\",\n\t\t\t\t\t\t\"enabled\": false\n\t\t\t\t\t}]\n\t\t\t\t},\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"devicesWithBattery\": {\n\t\t\t\t\"label\": \"__l_batteryDevs__\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"pollDevsWithBatteries\": true\n\t\t\t\t},\n\t\t\t\t\"fieldClass\": \"batteryDevices\",\n\t\t\t\t\"actionbar\": {\n\t\t\t\t\t\"actions\": [{\n\t\t\t\t\t\t\"action\": \"up\",\n\t\t\t\t\t\t\"enabled\": false\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"action\": \"down\",\n\t\t\t\t\t\t\"enabled\": false\n\t\t\t\t\t}]\n\t\t\t\t},\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t\"postRender\": \"loadFunction:postRender.js\"\n}\n"
  },
  {
    "path": "modules/SensorsPolling/patchnotes.txt",
    "content": "v1.2.0 - feature:\n- devide between batterie and non batterie powered devices\n- by default battery powered sensors were not polled\n- descriptions overworked"
  },
  {
    "path": "modules/SensorsPollingLogging/index.js",
    "content": "/*** SensorsPollingLogging Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Alexey Vinogradov <klirichek@sphinxsearch.com>\nBased on SensorsPolling and logging modules of\nAuthor: Serguei Poltorak <ps@z-wave.me>\nDescription:\n\tThis module periodically request determined sensors\n\tAnd log their values into file or remote HTTP.\n\tUseful, for example, to trace electricity counter\n\t\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction SensorsPollingLogging (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSensorsPollingLogging.super_.call(this, id, controller);\n}\n\ninherits(SensorsPollingLogging, AutomationModule);\n\n_module = SensorsPollingLogging;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSensorsPollingLogging.prototype.init = function (config) {\n\tSensorsPollingLogging.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t// Here we assume that period is factor of minute and less than hour, or factor of hours and less than day, or factor of days\n\tvar p = Math.round(this.config.period);\n\tvar m = (p < 60) ? [0, 59, p] : 0;\n\tvar h = p >= 24*60 ? 0 : (p/60 >=1 ? [0, 23, Math.round(p/60)] : null);\n\tvar wd = p/24/60 >=1 ? [0, 6, Math.round(p/24/60)] : null;\n\t \n\tthis.controller.emit(\"cron.addTask\", \"sensorsPollingLogging.poll\", {\n\t\tminute: m,\n\t\thour: h,\n\t\tweekDay: wd,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\tthis.handler = function (vDev) {\n\t\tif (self.config.logTo === \"JSONFile\") {\n\t\t\tvar storedLog = loadObject(\"SensorValueLogging_\" + vDev.id + \"_\" + self.id);\n\t\t\tif (!storedLog) {\n\t\t\t\tstoredLog = {\n\t\t\t\t\tdeviceId: vDev.id,\n\t\t\t\t\tdeviceName: vDev.get(\"metrics:title\"),\n\t\t\t\t\tsensorData: []\n\t\t\t\t};\n\t\t\t};\n\t\t\tstoredLog.sensorData.push({\"time\": Date.now(), \"value\": vDev.get(\"metrics:level\")});\n\t\t\tsaveObject(\"SensorValueLogging_\" + vDev.id + \"_\" + self.id, storedLog, 60);\n\t\t\tstoredLog = null;\n\t\t};\n\t\tif (self.config.logTo === \"HTTPGET\") {\n\t\t\thttp.request({\n\t\t\t\tmethod: 'GET',\n\t\t\t\turl: self.config.url.replace(\"${id}\", vDev.id).replace(\"${value}\", vDev.get('metrics:level'))\n\t\t\t});\n\t\t};\n\n\t\t// Clear the watchdog timer\n\t\tif (self.watchdogtimer)\n\t\t\tclearTimeout (self.watchdogtimer);\n\t\tself.watchdogtimer = null;\n\t\tvDev.off(\"change:metrics:level\", self.handler);\n\t};\n\n\tthis.onPoll = function () {\n\t\tself.config.devices.forEach(function(vDevId) {\n\t\t\tvar vDev = this.controller.devices.get(vDevId);\n\t\t\tif (vDev) {\n\t\t\t\t// If the watchdog timer still active, that means that Polling interval is less\n\t\t\t\t// than watchdog timer. That is bad, but not fatal.\n\t\t\t\tif (self.watchdogtimer)\n\t\t\t\t{\n\t\t\t\t\t// that will also clean the timer and unsubscribe\n\t\t\t\t\tself.handler(vDev);\n\t\t\t\t} else\n\t\t\t\t{\n\t\t\t\t\tself.watchdogtimer = setTimeout ( function() {self.handler(vDev);}, self.config.polling*1000);\n\t\t\t\t\tvDev.on(\"change:metrics:level\",self.handler);\n\t\t\t\t\tvDev.performCommand(\"update\");\n\t\t\t\t};\n\t\t\t};\n\t\t});\n\t};\n\n\tthis.controller.on('sensorsPollingLogging.poll', this.onPoll);\n};\n\nSensorsPollingLogging.prototype.stop = function () {\n\tSensorsPollingLogging.super_.prototype.stop.call(this);\n\n\tthis.controller.off('sensorsPollingLogging.poll', this.onPoll);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/SensorsPollingLogging/module.json",
    "content": "{\n\t\"dependencies\": [\"Cron\"],\n\t\"autoload\": false,\n\t\"singleton\": false,\n\t\"userView\": true,\n\t\"icon\": \"icon.png\",\n\t\"category\": \"logging\",\n\t\"moduleName\": \"SensorsPollingLogging\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"version\":\"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"Poll sensors and log values periodically\",\n\t\t\"description\": \"This app just combines the Sensor Polling service with the Sensor Value Logging Service. Please refer to the description of the two apps for more information\",\n\t\t\"devices\": [],\n\t\t\"period\": 60\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"devices\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId,namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t },\n\t\t\"period\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"required\": true,\n\t\t\t\"enum\": [1, 2, 5, 10, 20, 30, 60, 120, 240, 360, 720, 1440, 10080]\n\t\t},\n\t\t\"polling\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"required\": true,\n\t\t\t\"enum\": [1, 2, 5, 10, 30, 60, 120, 300, 600, 1200, 2400, 3600]\n\t\t},\n\t\t\"logTo\": {\n\t\t\t\t\"enum\": [\"JSONFile\", \"HTTPGET\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"url\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"depends\": \"logTo\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"dependencies\": \"logTo\"\n\t\t }\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"devices\": {\n\t\t\t\t\t\"label\": \"Sensors to poll:\",\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName,namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t},\n\t\t\t\"period\": {\n\t\t\t\t\"label\": \"Poll period\",\n\t\t\t\t\"optionLabels\": [\"1 minute\", \"2 minute\", \"5 minute\", \"10 minute\", \"20 minute\", \"30 minute\", \"1 hour\", \"2 hours\", \"4 hours\", \"6 hours\", \"twice per day\", \"daily\", \"weekly\"]\n\t\t\t},\n\t\t\t\"polling\": {\n\t\t\t\t\"label\": \"Poll timeout\",\n\t\t\t\t\"helper\": \"Polling will issue 'update' command to the items and then wait for a while untill it's value changed. This timeout limits the time of waiting\",\n\t\t\t\t\"optionLabels\": [\"1 second\", \"2 seconds\", \"5 seconds\", \"10 seconds\", \"30 seconds\", \"1 minute\", \"2 minutes\", \"5 minutes\", \"10 minutes\", \"20 minutes\", \"40 minutes\", \"1 hour\"]\n\t\t\t},\n\t\t\t\"logTo\": {\n\t\t\t\t\"label\": \"How to store:\",\n\t\t\t\t\"optionLables\": [\"to JSON file in storage\", \"send via HTTP request\"]\n\t\t\t},\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"HTTP request to do. Strings ${id} and ${value} are replaced by sensor ID and value correspondingly\",\n\t\t\t\t\"helper\": \"Example: http://mydomainname.org/path/to/something/${id}?myval=${value}\",\n\t\t\t\t\"dependencies\": {\n\t\t\t\t\t\"logTo\": \"HTTPGET\"\n\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/SmartLight/index.js",
    "content": "/*** SmartLight Z-Way Home Automation module *************************************\n\n Version: 1.1.1\n (c) Z-Wave.Me, 2014\n\n -----------------------------------------------------------------------------\n Author: Yurkin Vitaliy <aivs@z-wave.me>, Niels Roche <nir@zwave.eu>\n Description: In the daytime the light turns on for 100%, at night the light turns on for 20%.\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\nfunction SmartLight (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSmartLight.super_.call(this, id, controller);\n\n\t// by default dimmer button status not pressed\n\tthis.dimmerButtonStatus = 0;\n\n\t// Sensor Enable or Disable\n\tthis.sensorEnable = 1;\n\n\tthis.timerSmartLight = null;\n\n\t// Create instance variables\n\tthis.timerAutoOff = null;\n};\n\ninherits(SmartLight, AutomationModule);\n_module = SmartLight;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\nSmartLight.prototype.init = function (config) {\n\t// Call superclass' init (this will process config argument and so on)\n\tSmartLight.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t// Dimmer levels for day and night\n\tvar dayLevel = this.config.Level.DayLevel;\n\tvar nightLevel = this.config.Level.NightLevel;\n\n\t// Day start\n\tvar time_07_00_arr = this.config.Day.DayTimeStart.split(\":\").map(function(x) { return parseInt(x, 10); });\n\tthis.Time_07_00 = time_07_00_arr[0] * 60 + time_07_00_arr[1];\n\t// Day end\n\tvar time_23_59_arr = this.config.Day.DayTimeEnd.split(\":\").map(function(x) { return parseInt(x, 10); });\n\tthis.Time_23_59 = time_23_59_arr[0] * 60 + time_23_59_arr[1];\n\n\t// handler for Sensor\n\tthis.sensorTriggered = function (Sensor) {\n\t\t// Now Time in minutes\n\t\tvar nowDate = new Date();\n\t\tvar nowTime = nowDate.getHours() * 60 + nowDate.getMinutes();\n\n\t\t// Check Motion Sensor and turn on light\n\t\tif ((Sensor.get(\"metrics:level\") == \"on\") && self.sensorEnable === 1) {\n\t\t\t// In the daytime or the dimmer Button pressed the light turns on for 100%  \n\t\t\tif ((nowTime >= self.Time_07_00 && nowTime <= self.Time_23_59) || self.dimmerButtonStatus === 1) {\n\t\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"exact\", { level: dayLevel });\n\t\t\t\tif (self.config.Level.sendOnAfterLevel) {\n\t\t\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"on\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t// At night the light turns on for 20%\n\t\t\telse {\n\t\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"exact\", { level: nightLevel });\n\t\t\t\tif (self.config.Level.sendOnAfterLevel) {\n\t\t\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"on\");\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Disable timer when \"on\"\n\t\t\tif (self.config.timeout !==0 && typeof self.config.timeout !== 'undefined') {\n\t\t\t\tif (self.timerAutoOff) {\n\t\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\t\tclearTimeout(self.timerAutoOff);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\telse if (self.sensorEnable === 0) {\n\t\t\tconsole.log(\"Sensor Disabled for 1 minute\");\n\t\t}\n\n\t\t// Start autoOff only when motion send \"on\" or \"off\"\n\t\tif ((Sensor.get(\"metrics:level\") == self.config.MotionEventToStartTimer) && self.sensorEnable === 1) {\n\t\t\t// If timeout setted, start timer autooff\n\t\t\tif (self.config.timeout !==0 && typeof self.config.timeout !== 'undefined') {\n\t\t\t\tif (self.timerAutoOff) {\n\t\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\t\tclearTimeout(self.timerAutoOff);\n\t\t\t\t}\n\t\t\t\tconsole.log(\"start AutoOff with \"+ self.config.MotionEventToStartTimer);\n\t\t\t\tself.timerAutoOff = setTimeout(function () {\n\t\t\t\t\t// Timeout fired, so we send \"off\" command to the virtual device\n\t\t\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"off\");\n\t\t\t\t\t// And clearing out this.timer variable\n\t\t\t\t\tself.timerAutoOff = null;\n\t\t\t\t}, self.config.timeout*1000);\n\t\t\t}\t\n\t\t}\n\t\telse if (self.sensorEnable === 0) {\n\t\t\tconsole.log(\"Sensor Disabled for 1 minute\");\n\t\t}\n\t};\n\n\t// handler for Dimmer Light \n\tthis.dimmerLevelChanged = function (Dimmer) {\n\t\t// when light off, dimmer button status not pressed\n\t\tif (self.controller.devices.get(self.config.Dimmer).get(\"metrics:level\") === 0) {\n\t\t\tself.dimmerButtonStatus = 0;\n\t\t}\n\t};\n\n\t// handler for Dimmer Button\n\tthis.dimmerButtonPressed = function (DimmerButton) {\n\t\t// if pressed up, turn on the light\n\t\tconsole.log(\"button pressed\");\n\t\tif (DimmerButton.get(\"metrics:level\")=== \"on\") {\n\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"exact\", { level: dayLevel });\n\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"exact\", { level: 255 });\n\t\t\tself.dimmerButtonStatus = 1; \n\t\t\tif (self.timerSmartLight) {\n\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\tclearTimeout(self.timerSmartLight);\n\t\t\t}\n\t\t\tself.sensorEnable = 1;\n\t\t} \n\t\t// if pressed down, turn off the light and does not respond to the sensor one minute\n\t\telse if (DimmerButton.get(\"metrics:level\")=== \"off\") {\n\t\t\tconsole.log(\"Sensor Disabled for 1 minute\");\n\t\t\tself.controller.devices.get(self.config.Dimmer).performCommand(\"off\");\n\t\t\tself.sensorEnable = 0;\n\n\t\t\tif (self.timerSmartLight) {\n\t\t\t// Timer is set, so we destroy it\n\t\t\tclearTimeout(self.timerSmartLight);\n\t\t\t}\n\n\t\t\t// pressed down, set (or reset) timer to new timeout\n\t\t\tself.timerSmartLight = setTimeout(function () {\n\t\t\t\tself.sensorEnable = 1;\n\t\t\t\tconsole.log(\"Sensor Enabled\");\n\t\t\t\t// And clearing out this.timer variable\n\t\t\t\tself.timerSmartLight = null;\n\t\t\t}, 60*1000);\n\t\t} \n\t};\n\n\t// Setup metric update event listener\n\tthis.controller.devices.on(this.config.MotionSensor, 'change:metrics:level', this.sensorTriggered);\n\tthis.controller.devices.on(this.config.Dimmer, 'change:metrics:level', this.dimmerLevelChanged);\n\t// Check if Dimmer Button exist\n\tif (this.config.DimmerButton) {\n\t\tthis.controller.devices.on(this.config.DimmerButton, 'change:metrics:level', this.dimmerButtonPressed);\n\t}\n};\n\nSmartLight.prototype.stop = function () {\n\tSmartLight.super_.prototype.stop.call(this);\n\n\tif (this.timerAutoOff){\n\t\tclearTimeout(this.timerAutoOff);\n\t}\n\n\tif (this.timerSmartLight) {\n\t\tclearTimeout(this.timerSmartLight);\n\t}\n\n\tthis.controller.devices.off(this.config.MotionSensor, 'change:metrics:level', this.sensorTriggered);\n\tthis.controller.devices.off(this.config.Dimmer, 'change:metrics:level', this.dimmerLevelChanged);\n\n\t// Check if Dimmer Button exist\n\tif (this.config.DimmerButton) {\n\t\tthis.controller.devices.off(this.config.DimmerButton, 'change:metrics:level', this.dimmerButtonPressed);\n\t}\n};\n"
  },
  {
    "path": "modules/SmartLight/lang/de.json",
    "content": "{\n\t\"m_title\":\"Intelligente Lichtregelung\",\n\t\"m_descr\":\"Diese App regelt auf intelligente Weise eine dimmbare Beleuchtung in Verbindung mit einem Bewegungsmelder. Bei erkannter Bewegung wird die Beleuchtung tagsüber auf 100%, nachts dagegen nur auf 20% eingeschalten. Sollten Sie einen Dimmer mit Lokalsteuerung wählen, können Sie diese automatische Einstellung durch Verwendung der lokalen Wippen überschreiben. Bei einer Überschreibung auf „0“ wird bei einer Bewegung nichts ausgeschalten.<br><br>Einstellungen:<br><ul><li>Wählen Sie den Bewegungsmelder aus.</li><li>Wählen Sie den zu regelnden Dimmer aus.</li><li><Ändern Sie – falls nötig – die Tag und Nacht Dimmstufe</li><li>Ändern Sie – falls nötig – den Zeitintervall für Tag und Nacht </li><li>Wählen Sie die Buttons zur Regelung des Dimmers</li></ul><br>Anwendung: Es ist kein Element erstellt.\",\n\t\"l_MotionSensor\":\"Bewegungssensor:\",\n\t\"l_Dimmer\":\"Dimmer\",\n\t\"l_Level\":\"Dimmerlevel für Tag und Nacht\",\n\t\"l_DayLevel\":\"Tageslicht\",\n\t\"l_NightLevel\":\"Nachtlicht\",\n\t\"l_sendOnAfterLevel\":\"Send command ON after command Dim\",\n\t\"h_sendOnAfterLevel\":\"For Z-Wave.Me Dimmer 3 gen need to send command ON to save it state.\",\n\t\"l_Day\":\"Tageszeiten zu denen das Tageslicht de/aktiviert wird:\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_DayTimeStart\":\"Start\",\n\t\"l_DayTimeEnd\":\"Ende\",\n\t\"l_DimmerButton\":\"Dimmertaste\",\n\t\"l_MotionEventToStartTimer\":\"What event from the motion sensor to start the timer\",\n\t\"l_timeout\":\"AutoOff timeout in seconds\",\n\t\"h_timeout\":\"To disable AutoOff set 0 or leave the field empty\",\n\t\"h_DimmerButton\":\"Um eine Dimmertaste zu erzeugen, aktivieren Sie die App 'Erzeuge Schaltersteuerung' und drücken Sie dort auf 'Dimmer Button'.\"\n}"
  },
  {
    "path": "modules/SmartLight/lang/en.json",
    "content": "{\n\t\"m_title\":\"Smart Light\",\n\t\"m_descr\":\"This app controls a dimmable light in a smart way in combination with a motion detector. At daytime and detected motion light is switched on for 100%, at night the light turns on for 20% only. If you select a dimmer with local control you can overwrite this automated setting using the local rockers. When overwritten to 0 the motion will not turn it off.<br><br>Settings:<br><ul><li>Select the motion sensor</li><li>Select the dimmer to control.</li><li>Change – if needed – the dimmer level for day and night</li><li>Change – if needed – the time interval for day and night</li><li>Pick the buttons to control the dimmer</li></ul><br>Usage: No element is created.\",\n\t\"l_MotionSensor\":\"Motion Sensor\",\n\t\"l_Dimmer\":\"Dimmer\",\n\t\"l_Level\":\"Dimmer levels for day and night\",\n\t\"l_DayLevel\":\"Day Level\",\n\t\"l_NightLevel\":\"Night Level\",\n\t\"l_sendOnAfterLevel\":\"Send command ON after command Dim\",\n\t\"h_sendOnAfterLevel\":\"For Z-Wave.Me Dimmer 3 gen need to send command ON to save it state.\",\n\t\"l_Day\":\"The time interval when the light is switched on for Day Level\",\n\t\"timeFormat\":\"hh:mm\",\n\t\"l_DayTimeStart\":\"Start\",\n\t\"l_DayTimeEnd\":\"End\",\n\t\"l_DimmerButton\":\"Dimmer Button\",\n\t\"l_MotionEventToStartTimer\":\"What event from the motion sensor to start the timer\",\n\t\"l_timeout\":\"AutoOff timeout in seconds\",\n\t\"h_timeout\":\"To disable AutoOff set 0 or leave the field empty\",\n\t\"h_DimmerButton\":\"To generate dimmer button activate module SwitchControlGenerator and then press dimmer button\"\n}"
  },
  {
    "path": "modules/SmartLight/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Умное освещение\",\n\t\"m_descr\":\"В дневное время свет включается на 100%, в ночное на 20%. Если нажать клавишу диммера вверх, то свет включится на 100% даже ночью, если нажать клавишу вниз, то свет выключится и диммер не будет реагировать на датчик движения в течении 1 минуты.\",\n\t\"l_MotionSensor\":\"Датчик движения\",\n\t\"l_Dimmer\":\"Диммер\",\n\t\"l_Level\":\"Уровень освещения\",\n\t\"l_DayLevel\":\"Дневной уровень\",\n\t\"l_NightLevel\":\"Ночной уровень\",\n\t\"l_sendOnAfterLevel\":\"Отправлять команду ВКЛ сразу за командой установки уровня освещения\",\n\t\"h_sendOnAfterLevel\":\"Диммерам Z-Wave.Me 3 поколения для сохранения уровня диммирования требуется отправить команду ВКЛ, другим диммерам это не требуется.\",\n\t\"l_Day\":\"Дневное время, когда диммер включается на дневной уровень\",\n\t\"timeFormat\":\"чч:мм\",\n\t\"l_DayTimeStart\":\"Начало\",\n\t\"l_DayTimeEnd\":\"Конец\",\n\t\"l_DimmerButton\":\"Клавиша диммера\",\n\t\"l_MotionEventToStartTimer\":\"По какому событию от датчика движения запустить таймер автовыключения\",\n\t\"l_timeout\":\"Автовыключение в секундах\",\n\t\"h_timeout\":\"Для отмены автовыключения установите 0 или оставьте поле пустым\",\n\t\"h_DimmerButton\":\"Для генерирования клавиши диммера активируйте модуль SwitchControlGenerator и нажмите клавишу на диммере\"\n}"
  },
  {
    "path": "modules/SmartLight/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"complex_applications\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"SmartLight\",\n\t\"version\": \"1.1.2\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"MotionSensor\": null,\n\t\t\"Dimmer\": null,\n\t\t\"Level\": {\n\t\t\t\"DayLevel\":\"99\",\n\t\t\t\"NightLevel\":\"20\"\n\t\t},\n\t\t\"Day\": {\n\t\t\t\"DayTimeStart\": \"07:00\",\n\t\t\t\"DayTimeEnd\": \"23:59\"\n\t\t},\n\t\t\"MotionEventToStartTimer\":\"on\",\n\t\t\"timeout\": 0,\n\t\t\"DimmerButton\": null\t\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"MotionSensor\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_all:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"Dimmer\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"Level\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"DayLevel\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"NightLevel\": {\n\t\t\t\t\t\t\"type\": \"integer\",\n\t\t\t\t\t\t\"minimum\": 0,\n\t\t\t\t\t\t\"maximum\": 99,\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"sendOnAfterLevel\": {\n\t\t\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\t\"default\" : false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"Day\": {\n\t\t\t\t\"type\": \"object\",\n\t\t\t\t\"properties\": {\n\t\t\t\t\t\"DayTimeStart\": {\n\t\t\t\t\t\t\"format\":\"time\",\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t},\n\t\t\t\t\t\"DayTimeEnd\": {\n\t\t\t\t\t\t\"format\":\"time\",\n\t\t\t\t\t\t\"type\": \"string\",\n\t\t\t\t\t\t\"required\": true\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"MotionEventToStartTimer\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"on\", \"off\"],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": false\n\t\t\t},\n\t\t\t\"DimmerButton\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchControl:deviceId,namespaces:devices_toggleButton:deviceId\",\n\t\t\t\t\"required\": false\n\t\t\t}\n\t\t},\n\t\t\"required\": true\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"MotionSensor\": {\n\t\t\t\t\"label\": \"__l_MotionSensor__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_all:deviceName\"\n\t\t\t},\n\t\t\t\"Dimmer\": {\n\t\t\t\t\"label\": \"__l_Dimmer__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t},\n\t\t\t\"Level\": {\n\t\t\t\t\"label\": \"__l_Level__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"DayLevel\": {\n\t\t\t\t\t\t\"label\": \"__l_DayLevel__\"\n\t\t\t\t\t},\n\t\t\t\t\t\"NightLevel\": {\n\t\t\t\t\t\t\"label\": \"__l_NightLevel__\"\n\t\t\t\t\t},\n\t\t\t\t\t\"sendOnAfterLevel\": {\n\t\t\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\t\t\"rightLabel\": \"__l_sendOnAfterLevel__\",\n\t\t\t\t\t\t\"helper\": \"__h_sendOnAfterLevel__\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"Day\": {\n\t\t\t\t\"label\": \"__l_Day__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"DayTimeStart\": {\n\t\t\t\t\t\t\"label\": \"__l_DayTimeStart__\",\n\t\t\t\t\t\t\"type\": \"time\",\n\t\t\t\t\t\t\"maskString\": \"99:99\",\n\t\t\t\t\t\t\"dateFormat\": \"HH:mm\"\n\t\t\t\t\t},\n\t\t\t\t\t\"DayTimeEnd\": {\n\t\t\t\t\t\t\"label\": \"__l_DayTimeEnd__\",\n\t\t\t\t\t\t\"type\": \"time\",\n\t\t\t\t\t\t\"maskString\": \"99:99\",\n\t\t\t\t\t\t\"dateFormat\": \"HH:mm\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"MotionEventToStartTimer\": {\n\t\t\t\t\"label\": \"__l_MotionEventToStartTimer__\",\n\t\t\t\t\"type\": \"select\"\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"label\": \"__l_timeout__\",\n\t\t\t\t\"helper\":\"__h_timeout__\"\n\n\t\t\t},\n\t\t\t\"DimmerButton\": {\n\t\t\t\t\"label\": \"__l_DimmerButton__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchControl:deviceName,namespaces:devices_toggleButton:deviceName\",\n\t\t\t\t\"helper\":\"__h_DimmerButton__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/SmartLight/patchnotes.txt",
    "content": "v1.1.1\n- format of time input field changed (HH:mm 24h)"
  },
  {
    "path": "modules/Sonos/index.js",
    "content": "/*** Sonos Z-Way HA module *******************************************\n\n Version: 1.2.4\n (c) Z-Wave.Me, 2020\n -----------------------------------------------------------------------------\n Author: Poltorak Serguei <ps@z-wave.me>\n Modified by: Martin Petzold <mp@zwave.eu>, Niels Roche <nir@zwave.eu>, Karsten Reichel <kar@zwave.eu>\n Description:\n Implements Sonos support\n ******************************************************************************/\n\n/*\n TODO\n\n Add periodic M-SEARCH if needed\n */\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction Sonos (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSonos.super_.call(this, id, controller);\n\n\tthis.players = [];\n\tthis.subscribeTimer = [];\n\tthis.hostnames = {};\n}\n\ninherits(Sonos, AutomationModule);\n\n_module = Sonos;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSonos.prototype.init = function (config) {\n\tSonos.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.householdFinder();\n\tthis.playersFinder();\n\tthis.notifier();\n\n\tthis.config.households.forEach(function(household) {\n\t\tself.playersFinderLookup(household);\n\t});\n};\n\nSonos.prototype.stop = function () {\n\tvar self = this;\n\n\tthis.sockHouseholdFinder && this.sockHouseholdFinder.close();\n\tthis.sockHouseholdFinder = null;\n\tthis.sockPlayerFinder && this.sockPlayerFinder.close();\n\tthis.sockPlayerFinder = null;\n\tthis.sockNotifier && this.sockNotifier.close();\n\tthis.sockNotifier = null;\n\n\tthis.players.forEach(function(player) {\n\t\tself.controller.devices.remove('Sonos_Device_' + player.host + '_' + this.id);\n\t\tself.controller.devices.remove('Sonos_Device_Play_' + player.host + '_' + self.id);\n\t\tself.controller.devices.remove('Sonos_Device_Volume_' + player.host + '_' + self.id);\n\t\tself.controller.devices.remove('Sonos_Device_Previous_' + player.host + '_' + self.id);\n\t\tself.controller.devices.remove('Sonos_Device_Next_' + player.host + '_' + self.id);\n\t});\n\n\tthis.subscribeTimer.forEach(function(timer) {\n\t\tclearInterval(timer);\n\t});\n\n\tSonos.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nSonos.prototype.householdFinder = function () {\n\tvar self = this;\n\n\tvar sockHouseholdFinder = new sockets.udp();\n\tsockHouseholdFinder.reusable();\n\tsockHouseholdFinder.bind('255.255.255.255', 6969);\n\tsockHouseholdFinder.onrecv = function(data, host, port) {\n\t\tvar arr = new Uint8Array(data);\n\n\t\tvar pos = 4;\n\t\tpos += 1 + arr[pos];\n\t\tpos += 9;\n\t\tpos += 1 + arr[pos];\n\t\tpos += 2;\n\n\t\tvar household = String.fromCharCode.apply(null, arr.subarray(pos + 1, pos + 1 + arr[pos]));\n\n\t\tif (self.config.households.filter(function(el) { return el == household; }).length === 0) {\n\t\t\tconsole.log('Detected Sonos Household:', household);\n\t\t\tself.config.households.push(household);\n\t\t\tself.saveConfig();\n\t\t\tself.playersFinderLookup(household);\n\t\t}\n\t};\n\tsockHouseholdFinder.listen();\n\tconsole.log('Waiting for Sonos to send announcement');\n\n\tthis.sockHouseholdFinder = sockHouseholdFinder;\n};\n\nSonos.prototype.playersFinder = function () {\n\tvar self = this;\n\n\tvar sockPlayerFinder = new sockets.udp();\n\tsockPlayerFinder.reusable();\n\tsockPlayerFinder.onrecv = function(data, host, port) {\n\t\tvar msg = String.fromCharCode.apply(null, new Uint8Array(data));\n\t\tvar header_loc = 'LOCATION: ';\n\t\tvar headers_loc = msg.split('\\r\\n').filter(function(str) { return str.slice(0, header_loc.length) == header_loc; });\n\t\tvar header_hh = 'X-RINCON-HOUSEHOLD: ';\n\t\tvar headers_hh = msg.split('\\r\\n').filter(function(str) { return str.slice(0, header_hh.length) == header_hh; });\n\t\tif (headers_loc.length && headers_hh.length) {\n\t\t\tvar url = headers_loc[0].slice(header_loc.length),\n\t\t\t\t_household = headers_hh[0].slice(header_hh.length);\n\t\t\tself.checkPlayer(_household, host, url);\n\t\t}\n\t};\n\tsockPlayerFinder.listen();\n\n\tthis.sockPlayerFinder = sockPlayerFinder;\n};\n\nSonos.prototype.playersFinderLookup = function (household) {\n\tthis.sockPlayerFinder.sendto('M-SEARCH * HTTP/1.1\\r\\nHOST: 239.255.255.250:1900\\r\\nMAN: \"ssdp:discover\"\\r\\nMX: 1\\r\\nST: urn:schemas-upnp-org:device:ZonePlayer:1\\r\\nX-RINCON-HOUSEHOLD: ' + household + '\\r\\n\\r\\n', '239.255.255.250', 1900);\n};\n\nSonos.prototype.checkPlayer = function(household, host, metadata) {\n\tvar self = this;\n\n\tif (!this.hostnames[household]) {\n\t\tthis.detectHostname(household, host);\n\t}\n\n\tif (this.players.filter(function (player) { return player.host == host; }).length) return; // this player was tested already\n\tthis.players.push({\n\t\thousehold: household,\n\t\thost: host\n\t});\n\n\thttp.request({\n\t\turl: metadata,\n\t\tasync: true,\n\t\tmethod: 'GET',\n\t\theader: {\n\t\t\t'Content-Type': 'text/xml'\n\t\t},\n\t\tsuccess: function(response) {\n\t\t\tvar AVcaps = response.data.findOne('//t:controlURL[text()=\"/MediaRenderer/AVTransport/Control\"]', {t: 'urn:schemas-upnp-org:device-1-0'});\n\t\t\tif (AVcaps) {\n\t\t\t\tconsole.log('Detected AV capable Sonos player on', host);\n\t\t\t\tself.renderPlayer(household, host);\n\t\t\t}\n\t\t},\n\t\terror: function(response) {\n\t\t\tconsole.log('Failed to fetch Sonos metadata from', host);\n\t\t}\n\t});\n};\n\nSonos.prototype.detectHostname = function(household, host) {\n\tvar self = this;\n\n\tvar sockHost = new sockets.tcp();\n\tsockHost.onclose = function (remoteHost, remotePort, localHost, localPort) {\n\t\tif (localHost && self.hostnames[household] !== localHost) {\n\t\t\tconsole.log('Detected own hostname:', localHost);\n\t\t\tself.hostnames[household] = localHost;\n\t\t}\n\t};\n\tsockHost.onconnect = function(remoteHost, remotePort, localHost, localPort) {\n\t\tthis.close();\n\t};\n\tsockHost.connect(host, 1400);\n};\n\nSonos.prototype.renderPlayer = function(household, host) {\n\tvar self = this;\n\tvar vDevPlayer = this.controller.devices.create({\n\t\tdeviceId: 'Sonos_Device_' + host + '_' + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: 'audioPlayer',\n\t\t\tmetrics: {\n\t\t\t\ttitle: 'Sonos ' + host + ' ' + this.id,\n\t\t\t\ticon: '/ZAutomation/api/v1/load/modulemedia/Sonos/icon.png',\n\t\t\t\tlevel: '0',\n\t\t\t\tpStatus:'Stop'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\tvar level=this.get('metrics:level');\n\t\t\tvar levelOld=level;\n\t\t\tvar pStatus=this.get('metrics:pStatus');\n\t\t\tvar pStatusOld=pStatus;\n\t\t\tswitch (command) {\n\t\t\t\tcase 'on':\n\t\t\t\t\tpStatus = 'Play';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'off':\n\t\t\t\t\tpStatus = 'Stop';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'exact':\n\t\t\t\t\tlevel = parseInt(args.level, 10);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'previous':\n\t\t\t\t\tself.action(host, 'Previous');\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'next':\n\t\t\t\t\tself.action(host, 'Next');\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'play':\n\t\t\t\t\tpStatus='Play';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'pause':\n\t\t\t\t\tpStatus='Pause';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'stop':\n\t\t\t\t\tpStatus='Stop';\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif(level!==levelOld) {\n\t\t\t\tself.volume(host, level);\n\t\t\t}\n\t\t\tif(pStatus!==pStatusOld) {\n\t\t\t\tself.action(host, pStatus);\n\t\t\t}\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\tvar vDevSwitch = this.controller.devices.create({\n\t\tdeviceId: 'Sonos_Device_Play_' + host + '_' + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: 'switchBinary',\n\t\t\tmetrics: {\n\t\t\t\ttitle: 'Sonos Play ' + host + ' ' + this.id,\n\t\t\t\ticon: '/ZAutomation/api/v1/load/modulemedia/Sonos/icon.png'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\tself.action(host, command === 'on' ? 'Play' : 'Pause');\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\tvar vDevVolume = this.controller.devices.create({\n\t\tdeviceId: 'Sonos_Device_Volume_' + host + '_' + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: 'switchMultilevel',\n\t\t\tmetrics: {\n\t\t\t\ttitle: 'Sonos Volume ' + host + ' ' + this.id,\n\t\t\t\ticon: '/ZAutomation/api/v1/load/modulemedia/Sonos/icon.png',\n\t\t\t\tprobeType: 'multilevel'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\tvar level;\n\t\t\tif (command === 'on') level = 100;\n\t\t\tif (command === 'off') level = 0;\n\t\t\tif (command === 'exact') level = parseInt(args.level, 10);\n\t\t\tself.volume(host, level);\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\tvar vDevPrevious = this.controller.devices.create({\n\t   deviceId: 'Sonos_Device_Previous_' + host + '_' + this.id,\n\t   defaults: {\n\t\t\tdeviceType: 'toggleButton',\n\t\t\tmetrics: {\n\t\t\t\ttitle: 'Sonos Previous ' + host + ' ' + this.id,\n\t\t\t\ticon: '/ZAutomation/api/v1/load/modulemedia/Sonos/icon.png',\n\t\t\t\tlevel: 'on'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\tself.action(host, 'Previous');\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\tvar vDevNext = this.controller.devices.create({\n\t\tdeviceId: 'Sonos_Device_Next_' + host + '_' + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: 'toggleButton',\n\t\t\tmetrics: {\n\t\t\t\ttitle: 'Sonos Next ' + host + ' ' + this.id,\n\t\t\t\ticon: '/ZAutomation/api/v1/load/modulemedia/Sonos/icon.png',\n\t\t\t\tlevel: 'on'\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\tself.action(host, 'Next');\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\n\t// by default hide addiitonal elements, but allow to use them in Apps\n\tvDevVolume.set('visibility', false, {silent: true});\n\tvDevSwitch.set('visibility', false, {silent: true});\n\tvDevPrevious.set('visibility', false, {silent: true});\n\tvDevNext.set('visibility', false, {silent: true});\n\t\n\t// subscribe to notifications\n\tthis.subscribe(household, host);\n\n\t// repeat subscription every hour\n\tthis.subscribeTimer.push(setInterval(function() {\n\t\tself.subscribe(household, host);\n\t}, 3600*1000));\n};\n\nSonos.prototype.subscribe = function (household, host) {\n\tvar self = this;\n\n\t[\n\t\t'/MediaRenderer/AVTransport/Event',\n\t\t'/MediaRenderer/RenderingControl/Event'\n\t\t/* we don't need these notifications\n\t\t '/MediaServer/ContentDirectory/Event',\n\t\t '/ZoneGroupTopology/Event',\n\t\t '/AlarmClock/Event',\n\t\t '/MusicServices/Event',\n\t\t '/SystemProperties/Event',\n\t\t '/MediaServer/ContentDirectory/Event',\n\t\t */\n\t].map(function(subscriber) {\n\t\tvar sock = new sockets.tcp();\n\t\tsock.onconnect = function() {\n\t\t\tthis.send(\n\t\t\t\t\"SUBSCRIBE \" + subscriber +\" HTTP/1.1\\r\\n\" +\n\t\t\t\t\"HOST: \" + host + \":1400\\r\\n\" +\n\t\t\t\t\"USER-AGENT: Linux UPnP/1.0 Sonos/28.1-83040 (MDCR_MacBookPro11,1)\\r\\n\" +\n\t\t\t\t\"CALLBACK: <http://\" + self.hostnames[household] + \":3400/notify>\\r\\n\" +\n\t\t\t\t\"NT: upnp:event\\r\\n\" +\n\t\t\t\t\"TIMEOUT: Second-3600\\r\\n\"+\n\t\t\t\t\"\\r\\n\"\n\t\t\t);\n\t\t\tthis.close();\n\t\t};\n\t\tsock.connect(host, 1400);\n\t});\n};\n\nSonos.prototype.notifier = function () {\n\tvar self = this;\n\n\tvar sockNotifier = new sockets.tcp();\n\tsockNotifier.reusable();\n\tsockNotifier.bind(3400);\n\tsockNotifier.onconnect = function(host, port) {\n\t\tthis.msg = '';\n\t};\n\tsockNotifier.onrecv = function(data, host, port) {\n\t\tthis.msg += String.fromCharCode.apply(null, new Uint8Array(data));\n\t\tvar indx = this.msg.indexOf('\\r\\n\\r\\n');\n\t\tif (indx != -1) {\n\t\t\tvar header_len_str = 'CONTENT-LENGTH';\n\t\t\tvar header = this.msg.slice(0, indx).split('\\r\\n');\n\t\t\tvar header_len = header.filter(function(str) { return str.slice(0, header_len_str.length) === header_len_str; });\n\t\t\tif (header_len.length) {\n\t\t\t\tdata_len = parseInt(header_len[0].split(':')[1], 10);\n\t\t\t\tdata = this.msg.slice(indx + 4);\n\t\t\t\tif (data.length >= data_len) {\n\t\t\t\t\t// full message received\n\t\t\t\t\tthis.send(\"HTTP/1.1 200 OK\\r\\nServer: Linux UPnP/1.0 Sonos/28.1-83040 (MDCR_MacBookPro11,1)\\r\\nConnection: close\\r\\n\\r\\n\");\n\t\t\t\t\tthis.close();\n\n\t\t\t\t\tvar x = new ZXmlDocument(data);\n\t\t\t\t\tvar lastChange = x.findOne('//LastChange/text()');\n\t\t\t\t\tif (lastChange) {\n\t\t\t\t\t\tlastChange = lastChange.replace(' xmlns=\\\"urn:schemas-upnp-org:metadata-1-0/RCS/\\\"', ''); // TODO: temp hack until we fix xmlns problem // fixed, but need time to redo this part\n\t\t\t\t\t\tlastChange = lastChange.replace(' xmlns=\\\"urn:schemas-upnp-org:metadata-1-0/AVT/\\\"', ''); // TODO: temp hack until we fix xmlns problem\n\t\t\t\t\t\t//self.controller.addNotification('error', JSON.stringify(lastChange, null, 4), 'module', 'Sonos');\n\t\t\t\t\t\tvar vol = (new ZXmlDocument(lastChange)).findOne('/Event/InstanceID/Volume[@channel=\"Master\"]/@val');\n\n\t\t\t\t\t\tvar vDevPlayer = self.controller.devices.get('Sonos_Device_' + host + '_' + self.id);\n\n\t\t\t\t\t\tif (vol) {\n\t\t\t\t\t\t\tvar vDevVolume = self.controller.devices.get('Sonos_Device_Volume_' + host + '_' + self.id);\n\t\t\t\t\t\t\tif (vDevVolume) {\n\t\t\t\t\t\t\t\tvDevVolume.set('metrics:level', parseInt(vol, 10));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (vDevPlayer) {\n\t\t\t\t\t\t\t\tvDevPlayer.set('metrics:level', parseInt(vol, 10));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar play = (new ZXmlDocument(lastChange)).findOne('/Event/InstanceID/TransportState/@val');\n\t\t\t\t\t\tif (play) {\n\t\t\t\t\t\t\tvar vDevSwitch = self.controller.devices.get('Sonos_Device_Play_' + host + '_' + self.id);\n\t\t\t\t\t\t\tif (vDevSwitch) {\n\t\t\t\t\t\t\t\tvDevSwitch.set('metrics:level', play === 'PLAYING' ? 'on' : 'off');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (vDevPlayer) {\n\t\t\t\t\t\t\t\tswitch (play) {\n\t\t\t\t\t\t\t\t\tcase 'PLAYING':\n\t\t\t\t\t\t\t\t\t\tvDevPlayer.set('metrics:pStatus', 'Play');\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 'PAUSED_PLAYBACK':\n\t\t\t\t\t\t\t\t\t\tvDevPlayer.set('metrics:pStatus', 'Pause');\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 'STOPPED':\n\t\t\t\t\t\t\t\t\t\tvDevPlayer.set('metrics:pStatus', 'Stop');\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tvDevPlayer.set('metrics:pStatus', 'Stop');\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\tsockNotifier.listen();\n\tconsole.log('Binding Sonos notifier');\n\n\tthis.sockNotifier = sockNotifier;\n};\n\nSonos.prototype.action = function (host, action) {\n\tvar self = this;\n\thttp.request({\n\t\tasync: true,\n\t\theaders: {\n\t\t\t'Content-Type': 'text/xml',\n\t\t\t'SOAPACTION': 'urn:schemas-upnp-org:service:AVTransport:1#' + action\n\t\t},\n\t\turl: 'http://' + host + ':1400/MediaRenderer/AVTransport/Control',\n\t\tmethod: 'POST',\n\t\tdata: '\\\n\t\t\t<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\\\n\t\t\t\t<s:Body>\\\n\t\t\t\t\t<u:' + action + ' xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\">\\\n\t\t\t\t\t\t<InstanceID>0</InstanceID>\\\n\t\t\t\t\t\t<Speed>1</Speed>\\\n\t\t\t\t\t</u:' + action + '>\\\n\t\t\t\t</s:Body>\\\n\t\t\t</s:Envelope>',\n\n\t\tsuccess: function() {\n\t\t\tvDevPlayer = self.controller.devices.get('Sonos_Device_' + host + '_' + self.id);\n\t\t\tif (vDevPlayer) {\n\t\t\t\tvDevPlayer.set('metrics:pStatus', action);\n\t\t\t}\n\n\t\t\tvar vDevSwitch = self.controller.devices.get('Sonos_Device_Play_' + host + '_' + self.id);\n\t\t\tif (vDevSwitch) {\n\t\t\t\tif (action == 'Play') {\n\t\t\t\t\tvDevSwitch.set('metrics:level', 'on');\n\t\t\t\t}\n\t\t\t\telse if (action == 'Stop' || action == 'Pause') {\n\t\t\t\t\tvDevSwitch.set('metrics:level', 'off');\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\terror: function(response) {\n\t\t\tconsole.log('Can not make request: ' + response.statusText);\n\t\t}\n\t});\n};\n\nSonos.prototype.volume = function (host, level) {\n\tvar self = this;\n\thttp.request({\n\t\tasync: true,\n\t\theaders: {\n\t\t\t'Content-Type': 'text/xml',\n\t\t\t'SOAPACTION': 'urn:schemas-upnp-org:service:RenderingControl:1#SetVolume'\n\t\t},\n\t\turl: 'http://' + host + ':1400/MediaRenderer/RenderingControl/Control',\n\t\tmethod: 'POST',\n\t\tdata: '\\\n\t\t\t<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\\\n\t\t\t\t<s:Body>\\\n\t\t\t\t\t<u:SetVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\">\\\n\t\t\t\t\t\t<InstanceID>0</InstanceID>\\\n\t\t\t\t\t\t<Channel>Master</Channel>\\\n\t\t\t\t\t\t<DesiredVolume>' + level + '</DesiredVolume>\\\n\t\t\t\t\t</u:SetVolume>\\\n\t\t\t\t</s:Body>\\\n\t\t\t</s:Envelope>',\n\t\tsuccess: function() {\n\t\t\tvar vDevPlayer = self.controller.devices.get('Sonos_Device_' + host + '_' + self.id);\n\t\t\tif (vDevPlayer) {\n\t\t\t\tvDevPlayer.set('metrics:level', level);\n\t\t\t}\n\n\t\t\tvar vDevVolume = self.controller.devices.get('Sonos_Device_Volume_' + host + '_' + self.id);\n\t\t\tif (vDevVolume) {\n\t\t\t\tvDevVolume.set('metrics:level', level);\n\t\t\t}\n\t\t},\n\t\terror: function(response) {\n\t\t\tconsole.log('Can not make request: ' + response.statusText);\n\t\t}\n\t});\n};\n"
  },
  {
    "path": "modules/Sonos/lang/de.json",
    "content": "{\n\t\"m_title\":\"Sonos\",\n\t\"m_descr\":\"Die App integriert Ihr SONOS Musiksystem in Ihre Smart Home UI. Sie erstellt eine Schaltvorrichtung zur Sonos Wiedergabe-, Pause-, Vorwärts-, Rückwärts- und Lautstärke-Regelung.\",\n\t\"l_household\":\"Sonos household (filled automatically on Mute + Volume Up key press)\"\n}\n"
  },
  {
    "path": "modules/Sonos/lang/en.json",
    "content": "{\n\t\"m_title\":\"Sonos\",\n\t\"m_descr\":\"The app integrates your SONOS music system into your SmartHome UI.  It creates a  toggle device for Sonos Play, Pause, Forward, Backward and Volume controls.\",\n\t\"l_household\":\"Sonos household (filled automatically on Mute + Volume Up key press)\"\n}"
  },
  {
    "path": "modules/Sonos/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Sonos\",\n\t\"m_descr\":\"Создает элементы управления колонкой Sonos: проигрывание, пауза и громкоть.\",\n\t\"l_household\":\"Имя сети Sonos (заполняется автоматически при нажатии на кнопки Mute + Volume Up)\"\n}"
  },
  {
    "path": "modules/Sonos/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"support_external_dev\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n        \"moduleName\": \"Sonos\",\n\t\"version\": \"1.2.3\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"households\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"households\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"type\": \"string\"\n\t\t\t\t},\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"households\": {\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"label\": \"__l_household__\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/SwitchControlGenerator/index.js",
    "content": "/*** SwitchControlGenerator Z-Way HA module *******************************************\n\nVersion: 1.2.0\n(c) Z-Wave.Me, 2020\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>, Niels Roche <nir@zwave.eu>\nDescription:\n\tGenerates new widgets on the fly for Remote Switches and other devices sending control commands to controller\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction SwitchControlGenerator (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSwitchControlGenerator.super_.call(this, id, controller);\n}\n\ninherits(SwitchControlGenerator, AutomationModule);\n\n_module = SwitchControlGenerator;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSwitchControlGenerator.prototype.init = function (config) {\n\tSwitchControlGenerator.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.CC = {\n\t\t\"Basic\": 0x20,\n\t\t\"SwitchBinary\": 0x25,\n\t\t\"SwitchMultilevel\": 0x26,\n\t\t\"SceneActivation\": 0x2b,\n\t\t\"SimpleAVControl\": 0x94,\n\t};\n\n\tthis.ZWAY_DEVICE_CHANGE_TYPES = {\n\t\t\"DeviceAdded\": 0x01,\n\t\t\"DeviceRemoved\": 0x02,\n\t\t\"InstanceAdded\": 0x04,\n\t\t\"InstanceRemoved\": 0x08,\n\t\t\"CommandAdded\": 0x10,\n\t\t\"CommandRemoved\": 0x20,\n\t};\n\n\tthis.CL = {\n\t\t\"Scenes\": 0x05,\n\t\t\"OnOff\": 0x06,\n\t\t\"LevelControl\": 0x08,\n\t};\n\n\tthis.ZBEE_DEVICE_CHANGE_TYPES = {\n\t\t\"DeviceAdded\": 0x01,\n\t\t\"DeviceRemoved\": 0x02,\n\t\t\"EndPointAdded\": 0x04,\n\t\t\"EndPointRemoved\": 0x08,\n\t\t\"ClusterAdded\": 0x10,\n\t\t\"ClusterRemoved\": 0x20,\n\t};\n\n\tthis.ZWAY_DATA_CHANGE_TYPE = {\n\t\t\"Updated\": 0x01,\t   // Value updated or child created\n\t\t\"Invalidated\": 0x02,   // Value invalidated\n\t\t\"Deleted\": 0x03,\t   // Data holder deleted - callback is called last time before being deleted\n\t\t\"ChildCreated\": 0x04,  // New direct child node created\n\n\t\t// ORed flags\n\t\t\"PhantomUpdate\": 0x40, // Data holder updated with same value (only updateTime changed)\n\t\t\"ChildEvent\": 0x80\t // Event from child node\n\t};\n\n\t\n\tthis.generated = this.config.generated; // used to stop after config changed\n\t\n\t// Z-Wave\n\t\n\tthis.bindingsZWay = {};\n\t\t\n\tthis.zwayReg = function (zwayName) {\n\t\tvar zway = global.ZWave && global.ZWave[zwayName].zway;\n\t\t\n\t\tif (!zway) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// create devices\n\t\tself.generated.filter(function(el) { return !!el && el.indexOf(\"ZWayVDev_\" + zwayName + \"_Remote_\") === 0; }).forEach(function(name) {\n\t\t\tif (self.config.banned.indexOf(name) === -1) {\n\n\t\t\t\tvar vendor = \"\",\n\t\t\t\t\tisFailed = false,\n\t\t\t\t\tids = [],\n\t\t\t\t\tidString = \"\";\n\t\t\t\ttry {\n\t\t\t\t\tids = name.split('_').pop().split('-').slice(0, -1);\n\t\t\t\t\tidString = ids && ids.length > 0? \" (\" + ids.join(\".\") + \") \" : idString;\n\n\t\t\t\t\tvar v = zway.devices[ids[0]].data.vendorString.value;\n\t\t\t\t\tvendor = !!v? v : vendor;\n\t\t\t\t\t\n\t\t\t\t\tisFailed = zway.devices[ids[0]].data.isFailed.value;\n\t\t\t\t} catch (e) {}\n\n\t\t\t\tself.controller.devices.create({\n\t\t\t\t\tdeviceId: name,\n\t\t\t\t\tdefaults: {\n\t\t\t\t\t\tdeviceType: name[name.length-1] === \"S\" ? \"toggleButton\" : \"switchControl\",\n\t\t\t\t\t\ttechnology: \"Z-Wave\",\n\t\t\t\t\t\tbindingName: zwayName,\n\t\t\t\t\t\tnodeId: ids[0],\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ttitle: vendor + idString + \"Button\", // this is always not the initial creation, so the default title is already filled \n\t\t\t\t\t\t\tchange: \"\",\n\t\t\t\t\t\t\tisFailed: isFailed\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\toverlay: {\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: \"gesture\",\n\t\t\t\t\t\t\tlevel: \"\"\n\t\t\t\t\t\t} \n\t\t\t\t\t},\n\t\t\t\t\thandler: self.widgetHandler,\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t\t\t\n\t\tself.bindingsZWay[zwayName] = [];\n\n\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, \"lastExcludedDevice\", function(type) {\n\t\t\tvar _id = this.value;\n\t\t\t// remove vDev and cleanup vDev info\n\t\t\tself.generated.filter(function(el) { return !!el && el.indexOf(\"ZWayVDev_\" + zwayName + \"_Remote_\" + _id) === 0; }).forEach(function(name) {\n\t\t\t\tself.controller.devices.remove(name);\n\t\t\t\tself.controller.devices.cleanup(name);\n\t\t\t});\n\t\t\t// remove from generated and banned lists\n\t\t\tself.generated = self.generated.filter(function(el) { return !!el && el.indexOf(\"ZWayVDev_\" + zwayName + \"_Remote_\" + _id) !== 0; });\n\t\t\tself.config.generated = self.config.generated.filter(function(el) { return !!el && el.indexOf(\"ZWayVDev_\" + zwayName + \"_Remote_\" + _id) !== 0; });\n\t\t\tself.config.banned = self.config.banned.filter(function(el) { return !!el && el.indexOf(\"ZWayVDev_\" + zwayName + \"_Remote_\" + _id) !== 0; });\n\t\t\tself.saveConfig();\n\t\t}, \"\");\n\n\t\tvar ctrlNodeId = zway.controller.data.nodeId.value,\n\t\t\tinsts = zway.devices[ctrlNodeId].instances;\n\t\tfor (var i in insts) {\n\t\t\t(function(n) {\n\t\t\t\tvar dataB = insts[n].Basic && insts[n].Basic.data,\n\t\t\t\t    dataSB = insts[n].SwitchBinary && insts[n].SwitchBinary.data,\n\t\t\t\t    dataSML = insts[n].SwitchMultilevel && insts[n].SwitchMultilevel.data,\n\t\t\t\t    dataSc = insts[n].SceneActivation && insts[n].SceneActivation.data,\n\t\t\t\t    dataSAV = insts[n].SimpleAVControl && insts[n].SimpleAVControl.data;\n\t\t\t   \n\t\t\t\tif (dataB) {\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"Basic\"], \"level\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataB.srcNodeId.value, dataB.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar val, par = {};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (this.value === 0) {\n\t\t\t\t\t\t\t\tval = \"off\";\n\t\t\t\t\t\t\t} else if (this.value === 255) {\n\t\t\t\t\t\t\t\tval = \"on\";\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tval = \"exact\";\n\t\t\t\t\t\t\t\tpar = { level: this.value };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, val, par, [dataB.srcNodeId.value, dataB.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (dataSB) {\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"SwitchBinary\"], \"level\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataSB.srcNodeId.value, dataSB.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, this.value ? \"on\" : \"off\", {}, [dataSB.srcNodeId.value, dataSB.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (dataSML) {\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"SwitchMultilevel\"], \"level\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataSML.srcNodeId.value, dataSML.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar val, par = {};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (this.value === 0) {\n\t\t\t\t\t\t\t\tval = \"off\";\n\t\t\t\t\t\t\t} else if (this.value === 255) {\n\t\t\t\t\t\t\t\tval = \"on\";\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tval = \"exact\";\n\t\t\t\t\t\t\t\tpar = { level: this.value };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, val, par, [dataSML.srcNodeId.value, dataSML.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"SwitchMultilevel\"], \"startChange\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataSML.srcNodeId.value, dataSML.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, this.value ? \"upstart\" : \"downstart\", {}, [dataSML.srcNodeId.value, dataSML.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"SwitchMultilevel\"], \"stopChange\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataSML.srcNodeId.value, dataSML.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, dataSML.startChange.value ? \"upstop\" : \"downstop\", {}, [dataSML.srcNodeId.value, dataSML.srcInstanceId.value, n, \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (dataSc) {\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"SceneActivation\"], \"currentScene\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataSc.srcNodeId.value, dataSc.srcInstanceId.value, n, this.value, \"S\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, \"on\", {}, [dataSc.srcNodeId.value, dataSc.srcInstanceId.value, n, this.value, \"S\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (dataSAV) {\n\t\t\t\t\tself.controller.emit(\"ZWave.dataBind\", self.bindingsZWay[zwayName], zwayName, ctrlNodeId, n, self.CC[\"SimpleAVControl\"], \"key\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZWay\", zwayName, [dataSAV.srcNodeId.value, dataSAV.srcInstanceId.value, n, this.value, \"S\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZWay\", zwayName, \"on\", {}, [dataSAV.srcNodeId.value, dataSAV.srcInstanceId.value, n, this.value, \"S\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t})(i);\n\t\t}\n\t};\n\t\n\tthis.zwayUnreg = function(zwayName) {\n\t\t// detach handlers\n\t\tif (self.bindingsZWay[zwayName]) {\n\t\t\tself.controller.emit(\"ZWave.dataUnbind\", self.bindingsZWay[zwayName]);\n\t\t}\n\t\t// remove devices\n\t\tself.generated.filter(function(el) { return !!el && el.indexOf(\"ZWayVDev_\" + zwayName + \"_Remote_\") === 0; }).forEach(function(name) {\n\t\t\tself.controller.devices.remove(name);\n\t\t});\n\t\tself.bindingsZWay[zwayName] = null;\n\t\tdelete self.bindingsZWay[zwayName];\n\t};\n\t\n\tthis.controller.on(\"ZWave.register\", this.zwayReg);\n\tthis.controller.on(\"ZWave.unregister\", this.zwayUnreg);\n\n\t// walk through existing ZWave\n\tif (global.ZWave) {\n\t\tfor (var name in global.ZWave) {\n\t\t\tthis.zwayReg(name);\n\t\t}\n\t}\n\t\n\t// Zigbee\n\t\n\tthis.bindingsZBee = {};\n\t\n\tthis.zbeeReg = function (zbeeName) {\n\t\tvar zbee = global.Zigbee && global.Zigbee[zbeeName].zbee;\n\t\t\n\t\tif (!zbee) {\n\t\t\treturn;\n\t\t}\n\t\t\n\t\t// create devices\n\t\tself.generated.filter(function(el) { return !!el && el.indexOf(\"ZBeeVDev_\" + zbeeName + \"_Remote_\") === 0; }).forEach(function(name) {\n\t\t\tif (self.config.banned.indexOf(name) === -1) {\n\n\t\t\t\t\n\t\t\t\tvar vendor = \"\",\n\t\t\t\t\tisFailed = false,\n\t\t\t\t\tids = [],\n\t\t\t\t\tidString = \"\";\n\t\t\t\ttry {\n\t\t\t\t\tids = name.split('_').pop().split('-').slice(0, -1);\n\t\t\t\t\tidString = ids && ids.length > 0? \" (\" + ids.join(\".\") + \") \" : idString;\n\n\t\t\t\t\tif (zbee.devices[ids[0]].endpoints[1] && zbee.devices[ids[0]].endpoints[1].Basic) {\n\t\t\t\t\t\tvar v = zbee.devices[ids[0]].endpoints[1].Basic.data.manufacturerName.value;\n\t\t\t\t\t\tvendor = !!v? v : vendor;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tisFailed = zbee.devices[ids[0]].data.isFailed.value;\n\t\t\t\t} catch (e) {}\n\n\t\t\t\tself.controller.devices.create({\n\t\t\t\t\tdeviceId: name,\n\t\t\t\t\tdefaults: {\n\t\t\t\t\t\tdeviceType: name[name.length-1] === \"S\" ? \"toggleButton\" : \"switchControl\",\n\t\t\t\t\t\ttechnology: \"Zigbee\",\n\t\t\t\t\t\tbindingName: zbeeName,\n\t\t\t\t\t\tnodeId: ids[0],\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ttitle: vendor + idString + \"Button\", // this is always not the initial creation, so the default title is already filled \n\t\t\t\t\t\t\tchange: \"\",\n\t\t\t\t\t\t\tisFailed: isFailed\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\toverlay: {\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: \"gesture\",\n\t\t\t\t\t\t\tlevel: \"\"\n\t\t\t\t\t\t} \n\t\t\t\t\t},\n\t\t\t\t\thandler: self.widgetHandler,\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t\t\t\n\t\tself.bindingsZBee[zbeeName] = [];\n\n\t\tself.controller.emit(\"Zigbee.dataBind\", self.bindingsZBee[zbeeName], zbeeName, \"lastExcludedDevice\", function(type) {\n\t\t\tvar _id = this.value;\n\t\t\t// remove vDev and cleanup vDev info\n\t\t\tself.generated.filter(function(el) { return !!el && el.indexOf(\"ZBeeVDev_\" + zbeeName + \"_Remote_\" + _id) === 0; }).forEach(function(name) {\n\t\t\t\tself.controller.devices.remove(name);\n\t\t\t\tself.controller.devices.cleanup(name);\n\t\t\t});\n\t\t\t// remove from generated and banned lists\n\t\t\tself.generated = self.generated.filter(function(el) { return !!el && el.indexOf(\"ZBeeVDev_\" + zbeeName + \"_Remote_\" + _id) !== 0; });\n\t\t\tself.config.generated = self.config.generated.filter(function(el) { return !!el && el.indexOf(\"ZBeeVDev_\" + zbeeName + \"_Remote_\" + _id) !== 0; });\n\t\t\tself.config.banned = self.config.banned.filter(function(el) { return !!el && el.indexOf(\"ZBeeVDev_\" + zbeeName + \"_Remote_\" + _id) !== 0; });\n\t\t\tself.saveConfig();\n\t\t}, \"\");\n\n\t\tvar ctrlNodeId = zbee.controller.data.nodeId.value,\n\t\t\tinsts = zbee.devices[ctrlNodeId].endpoints;\n\t\tfor (var i in insts) {\n\t\t\t(function(n) {\n\t\t\t\tvar dataOnOff = insts[n].OnOff && insts[n].OnOff.data,\n\t\t\t\t    dataLevel = insts[n].LevelControl && insts[n].LevelControl.data,\n\t\t\t\t    dataScenes = insts[n].Scene && insts[n].Scenes.data;\n\t\t\t   \n\t\t\t\tif (dataOnOff) {\n\t\t\t\t\tself.controller.emit(\"Zigbee.dataBind\", self.bindingsZBee[zbeeName], zbeeName, ctrlNodeId, n, self.CL[\"OnOff\"], \"onOff\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZBee\", zbeeName, [dataOnOff.srcNodeId.value, dataOnOff.srcEndpointId.value, n, \"OnOff\", \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZBee\", zbeeName, this.value ? \"on\" : \"off\", {}, [dataOnOff.srcNodeId.value, dataOnOff.srcEndpointId.value, n, \"OnOff\", \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (dataLevel) {\n\t\t\t\t\tself.controller.emit(\"Zigbee.dataBind\", self.bindingsZBee[zbeeName], zbeeName, ctrlNodeId, n, self.CL[\"LevelControl\"], \"currentLevel\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZBee\", zbeeName, [dataLevel.srcNodeId.value, dataLevel.srcEndpointId.value, n, \"Level\", \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar val, par = {};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (this.value === 0) {\n\t\t\t\t\t\t\t\tval = \"off\";\n\t\t\t\t\t\t\t} else if (this.value === 254) { // OnOff max value is 254\n\t\t\t\t\t\t\t\tval = \"on\";\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tval = \"exact\";\n\t\t\t\t\t\t\t\tpar = { level: this.value * 99 / 254 };\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.handler(\"ZBee\", zbeeName, val, par, [dataLevel.srcNodeId.value, dataLevel.srcEndpointId.value, n, \"Level\", \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t\tself.controller.emit(\"Zigbee.dataBind\", self.bindingsZBee[zbeeName], zbeeName, ctrlNodeId, n, self.CL[\"LevelControl\"], \"startChange\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZBee\", zbeeName, [dataLevel.srcNodeId.value, dataLevel.srcEndpointId.value, n, \"Level\", \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZBee\", zbeeName, this.value ? \"upstart\" : \"downstart\", {}, [dataLevel.srcNodeId.value, dataLevel.srcEndpointId.value, n, \"Level\", \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t\tself.controller.emit(\"Zigbee.dataBind\", self.bindingsZBee[zbeeName], zbeeName, ctrlNodeId, n, self.CL[\"LevelControl\"], \"stopChange\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZBee\", zbeeName, [dataLevel.srcNodeId.value, dataLevel.srcEndpointId.value, n, \"Level\", \"B\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZBee\", zbeeName, dataLevel.startChange.value ? \"upstop\" : \"downstop\", {}, [dataLevel.srcNodeId.value, dataLevel.srcEndpointId.value, n, \"Level\", \"B\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (dataScenes) {\n\t\t\t\t\tself.controller.emit(\"Zigbee.dataBind\", self.bindingsZBee[zbeeName], zbeeName, ctrlNodeId, n, self.CL[\"Scenes\"], \"currentScene\", function(type) {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.remove(\"ZBee\", zbeeName, [dataScenes.srcNodeId.value, dataScenes.srcEndpointId.value, n, this.value, \"S\", \"S\"]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.handler(\"ZBee\", zbeeName, \"on\", {}, [dataScenes.srcNodeId.value, dataScenes.srcEndpointId.value, n, this.value, \"S\", \"S\"]);\n\t\t\t\t\t\t}\n\t\t\t\t\t}, \"\");\n\t\t\t\t}\n\t\t\t})(i);\n\t\t}\n\t};\n\t\n\tthis.zbeeUnreg = function(zbeeName) {\n\t\t// detach handlers\n\t\tif (self.bindingsZBee[zbeeName]) {\n\t\t\tself.controller.emit(\"Zigbee.dataUnbind\", self.bindingsZBee[zbeeName]);\n\t\t}\n\t\t// remove devices\n\t\tself.generated.filter(function(el) { return !!el && el.indexOf(\"ZBeeVDev_\" + zbeeName + \"_Remote_\") === 0; }).forEach(function(name) {\n\t\t\tself.controller.devices.remove(name);\n\t\t});\n\t\tself.bindingsZBee[zbeeName] = null;\n\t\tdelete self.bindingsZBee[zbeeName];\n\t};\n\t\n\tthis.controller.on(\"Zigbee.register\", this.zbeeReg);\n\tthis.controller.on(\"Zigbee.unregister\", this.zbeeUnreg);\n\n\t// walk through existing Zigbee\n\tif (global.Zigbee) {\n\t\tfor (var name in global.Zigbee) {\n\t\t\tthis.zbeeReg(name);\n\t\t}\n\t}\n\t\n\tthis.api = function(zPrefix, zName /* srcNodeId, srcInstanceId, dstInstanceId, [sceneId], type */) {\n\t\tvar _trapNew = self.config.trapNew;\n\t\tself.config.trapNew = true; // to force creation of new elements even if not allowed to do it on event trap\n\t\tself.handler(zPrefix, zName, \"\", {}, Array.prototype.slice.call(arguments, 1));\n\t\tself.config.trapNew = _trapNew;\n\t};\n\t\n\tthis.controller.on(\"SwitchControlGenerator.register\", this.api);\n}\n\nSwitchControlGenerator.prototype.stop = function () {\n\t// unsign event handlers\n\tthis.controller.off(\"ZWave.register\", this.zwayReg);\n\tthis.controller.off(\"ZWave.unregister\", this.zwayUnreg);\n\t\n\tthis.controller.off(\"Zigbee.register\", this.zwayReg);\n\tthis.controller.off(\"Zigbee.unregister\", this.zwayUnreg);\n\t\n\tthis.controller.off(\"SwitchControlGenerator.register\", this.api);\n\n\t// detach handlers\n\tfor (var name in this.bindingsZWay) {\n\t\tthis.controller.emit(\"ZWave.dataUnbind\", this.bindingsZWay[name]);\n\t}\n\t\n\tthis.bindingsZWay = {};\n\t\n\t// detach handlers\n\tfor (var name in this.bindingsZBee) {\n\t\tthis.controller.emit(\"Zigbee.dataUnbind\", this.bindingsZBee[name]);\n\t}\n\t\n\tthis.bindingsZBee = {};\n\n\tvar self = this;\n\t\n\t// remove devices\n\tif (this.generated) {\n\t\tthis.generated.forEach(function(name) {\n\t\t\tself.controller.devices.remove(name);\n\t\t});\n\t\tthis.generated = [];\n\t}\n\n\tSwitchControlGenerator.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nSwitchControlGenerator.prototype.widgetHandler = function(command, params) {\n\tif (command === \"on\" || command === \"off\") {\n\t\tthis.set(\"metrics:level\", command);\n\t}\n\tif (command === \"exact\") {\n\t\tthis.set(\"metrics:level\", params.level);\n\t}\n\tif (command === \"upstart\" || command === \"upstop\" || command === \"downstart\" || command === \"downstop\") {\n\t\tthis.set(\"metrics:change\", command);\n\t}\n};\n\nSwitchControlGenerator.prototype.handler = function(zPrefix, zName, cmd, par, ids) {\n\tvar postfix = ids.join(\"-\"),\n\t\ttype = ids[ids.length - 1],\n\t\tname = zPrefix + \"VDev_\" + zName + \"_Remote_\" + postfix;\n\t\t\n\tif (this.config.generated.indexOf(name) === -1) {\n\t\tif (!this.config.trapNew || this.config.banned.indexOf(name) !== -1) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar vendor = \"\";\n\t\tvar isFailed = false;\n\n\t\tif (zPrefix === \"ZWay\") {\n\t\t\ttry {\n\t\t\t\tvar v = global.ZWave[zName].zway.devices[ids[0]].data.vendorString.value;\n\t\t\t\tvendor = !!v? v : vendor;\n\t\t\t} catch (e) {}\n\t\t\t\n\t\t\ttry {\n\t\t\t\tisFailed = global.ZWave[zName].zway.devices[ids[0]].data.isFailed.value;\n\t\t\t} catch (e) {}\n\t\t}\n\t\t\n\t\tif (zPrefix === \"ZBee\") {\n\t\t\ttry {\n\t\t\t\tvar v = global.Zigbee[zName].zbee.devices[ids[0]].endpoints[1].Basic.data.manufacturerName.value;\n\t\t\t\tvendor = !!v? v : vendor;\n\t\t\t} catch (e) {}\n\t\t\t\n\t\t\ttry {\n\t\t\t\tisFailed = global.Zigbee[zName].zbee.devices[ids[0]].data.isFailed.value;\n\t\t\t} catch (e) {}\n\t\t}\n\t\t\n\t\tthis.controller.devices.create({\n\t\t\tdeviceId: name,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: type === \"S\" ? \"toggleButton\" : \"switchControl\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ttitle: vendor + \" (\" + ids.slice(0, -1).join(\".\") + \") Button\",\n\t\t\t\t\tchange: \"\",\n\t\t\t\t\tisFailed: isFailed\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"gesture\",\n\t\t\t\t\tlevel: \"\"\n\t\t\t\t} \n\t\t\t},\n\t\t\thandler: this.widgetHandler,\n\t\t\tmoduleId: this.id\n\t\t});\n\t\t\n\t\tthis.config.generated.push(name);\n\t\tthis.generated = this.config.generated;\n\t\tthis.saveConfig();\n\t}\n\n\tvar vDev = this.controller.devices.get(name);\n\t\n\tif (vDev === null) {\n\t\tvar langFile = this.loadModuleLang();\n\t\tthis.addNotification(\"critical\", langFile.err, \"controller\");\n\t\treturn;\n\t}\n\t\n\tthis.widgetHandler.call(vDev, cmd, par);\n};\n\nSwitchControlGenerator.prototype.remove = function(zPrefix, zName, ids) {\n\tvar postfix = ids.join(\"-\"),\n\t\tname = zPrefix + \"VDev_\" + zName + \"_Remote_\" + postfix;\n\t\t\n\tif (this.config.generated.indexOf(name) === -1) {\n\t\tthis.controller.devices.remove(name);\n\t}\n};\n"
  },
  {
    "path": "modules/SwitchControlGenerator/lang/de.json",
    "content": "{\n\t\"m_title\":\"Erzeuge Schaltersteuerung\",\n\t\"m_descr\":\"Fernbedienungen und andere mobile Steuerungen sowie auch batteriebetriebene Wandsteuerungen erstellen kein Element in der UI sondern nur Ereignisse. Diese App vereinfacht die Verwendung dieser Ereignisse. Ein Element erstellt veranschaulichend den Status der Fernbedienung. Gleichzeitig kann dieses Element als auslösendes Ereignis für Szenen etc. verwendet werden.\",\n\t\"l_trapNew\": \"Erzeuge ein Kontrollgerät für neue Fernbedienungen und Schalter\",\n\t\"l_banned\": \"Nicht instanziierte Fernbedienungen und Schalter\",\n\t\"l_generated\": \"Instanziierte Fernbedienungen und Schalter (wird automatisch geladen)\",\n\t\"err\":\"SwitchControlGenerator: Das virtuelle Geräte sollte existieren, wurde aber nicht gefunden.\"\n}"
  },
  {
    "path": "modules/SwitchControlGenerator/lang/en.json",
    "content": "{\n\t\"m_title\":\"Trap events from Remotes and Sensors\",\n\t\"m_descr\":\"Remote Controls and other mobile controller but also battery operated wall controllers do not create an element in the UI but create events only.  This app simplifies the use of these events. An element creates visualizing the status of the remote control. The same time this element can be used as triggering event for scenes etc.\",\n\t\"l_trapNew\": \"Create control device for new remote controls and switches\",\n\t\"l_banned\": \"List of remotes and switches not to instantiate\",\n\t\"l_generated\": \"List of remotes and switches to instantiate (filled automatically)\",\n\t\"err\":\"SwitchControlGenerator: Virtual device should exist, but was not found.\"\n}"
  },
  {
    "path": "modules/SwitchControlGenerator/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Генератор кнопок от пультов\",\n\t\"m_descr\":\"Генерирует виджеты кнопок при нажатии на пульте, которые затем можно использовать в правилах автоматизации. Если устройство отправит контроллеру команду Set(255) или Set(0), то для него сгенерируется виджет кнопки.\",\n\t\"l_trapNew\": \"Генерировать виджеты кнопок для новых устройств\",\n\t\"l_banned\": \"Список устройств для которых не нужно генерировать виджеты кнопок\",\n\t\"l_generated\": \"Список устройств для которых нужно генерировать виджеты кнопок (заполняется автоматически)\",\n\t\"err\":\"SwitchControlGenerator: Виртуальное устройство должно существовать, но не найдено.\"\n}"
  },
  {
    "path": "modules/SwitchControlGenerator/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"automation_basic\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"SwitchControlGenerator\",\n\t\"version\": \"1.2.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"trapNew\": true,\n\t\t\"generated\": [],\n\t\t\"banned\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"trapNew\": {\n\t\t\t\t\"type\": \"boolean\"\n\t\t\t},\n\t\t\t\"banned\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId,namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"generated\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_toggleButton:deviceId,namespaces:devices_switchControl:deviceId\",\n\t\t\t\t\t\"required\": true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"trapNew\": {\n\t\t\t\t\"label\": \"\",\n\t\t\t\t\"rightLabel\": \"__l_trapNew__\"\n\t\t\t},\n\t\t\t\"banned\": {\n\t\t\t\t\"label\": \"__l_banned__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName,namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"generated\": {\n\t\t\t\t\"label\": \"__l_generated__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"readonly\": true,\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_toggleButton:deviceName,namespaces:devices_switchControl:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/SwitchPolling/index.js",
    "content": "/*** SwitchPolling Z-Way HA module *******************************************\n\nVersion: 1.0.1\n(c) Z-Wave.Me, 2015\n-----------------------------------------------------------------------------\nAuthor: Niels Roche <nir@zwave.eu>\nDescription:\n\tThis module periodically requests all switches\n\tThe period MUST be factor of minues, hours or days. No fraction of minute, hour or day is possible.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction SwitchPolling (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tSwitchPolling.super_.call(this, id, controller);\n}\n\ninherits(SwitchPolling, AutomationModule);\n\n_module = SwitchPolling;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nSwitchPolling.prototype.init = function (config) {\n\tSwitchPolling.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t// Here we assume that period is factor of minute and less than hour, or factor of hours and less than day, or factor of days\n\tvar p = Math.round(this.config.period);\n\tvar m = (p < 60) ? [0, 59, p] : 0;\n\tvar h = p >= 24*60 ? 0 : (p/60 >=1 ? [0, 23, Math.round(p/60)] : null);\n\tvar wd = p/24/60 >=1 ? [0, 6, Math.round(p/24/60)] : null;\n\tvar currentPoll, lastPoll, devJSON;\n\t \n\tthis.controller.emit(\"cron.addTask\", \"SwitchPolling.poll\", {\n\t\tminute: m,\n\t\thour: h,\n\t\tweekDay: wd,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\tthis.onPoll = function () {\n\n\t\tvar currentPoll = Math.floor(Date.now() / 1000),\n\t\t\tdevicesToUpdate = [],\n\t\t\tdevJSON;\n\n\t\t//update only binary and multilevel switches that has no change during the update interval\n\t\tdevicesToUpdate = self.controller.devices.filter(function (dev) {\n\t\t\tdevJSON = dev.toJSON();\n\n\t\t\treturn _.unique(self.config.devices).indexOf(dev.id) === -1 && \n\t\t\t\t\t\tdevJSON.updateTime <= lastPoll && \n\t\t\t\t\t\t\t(dev.get('deviceType') === 'switchBinary' || \n\t\t\t\t\t\t\t\tdev.get('deviceType') === 'switchMultilevel');\n\t\t});\n\n\t\tif (devicesToUpdate.length > 0) {\n\t\t\tdevicesToUpdate.forEach(function (dev) {\n\t\t\t\tdev.performCommand(\"update\");\n\t\t\t});\n\t\t}\n\n\t\tlastPoll = currentPoll;\n\t};\n\n\tthis.controller.on('SwitchPolling.poll', this.onPoll);\n};\n\nSwitchPolling.prototype.stop = function () {\n\n\tthis.controller.off('SwitchPolling.poll', this.onPoll);\n\tthis.controller.emit(\"cron.removeTask\", \"SwitchPolling.poll\");\n\n\tSwitchPolling.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/SwitchPolling/lang/de.json",
    "content": "{\t\n\t\"m_title\":\"Periodische Schalterabfrage\",\n\t\"m_descr\":\"Aufgrund eines bestimmten US Patents senden einige nordamerikanische Schalter (Wandschalter und Smart Plugs) keine Statusmeldung, wenn der Status durch eine lokale Aktion geändert wird. Damit die korrekten Status angezeigt werden, müssen die Schalter regelmäßig im Gateway abgefragt werden. Diese App kontrolliert diese Abfrage. Es werden alle Schalter im Gateway abgefragt, die keine Statusänderung innerhalb des festgelegten Intervalls gesendet haben. Schalter die nicht abgefragt werden sollen, können im Dropdown ausgeschlossen werden. Bitte beachten Sie, dass diese App ein Workaround für ein bekanntes Problem der älteren nordamerikanischen Geräte ist. Sie müssen diese App nicht auf Geräte anwenden, die Sie außerhalb der Vereinigten Staten (US) gekauft haben. Mittlerweile gibt es auch in den Vereinigten Staaten moderne Geräte, die ihren Status von selbst senden. Das ist der Grund, warum Sie diese App als Workaround ausschließlich für ältere US Schalter benötigen.<br><br>Einstellungen:<br><ul><li>Update den Status aller Schalter, die nicht ausgeschlossen sind. </li><li>Definiere eine Intervallfrequenz, wie oft Geräte abgefragt werden sollen. Bitte beachten Sie, dass häufige Abfragen den Traffic in ihrem Z-Wave Netzwerk vergrößern und dadurch andere Anwendungen verlangsamen kann. Das ist auch der Grund, warum nur minimal einmal pro Minute abgefragt werden kann.</li></ul>\",\n\t\"l_devices\":\"Von der Abfrage ausgeschlossene Schalter:\",\n\t\"l_period\":\"Abfrageintervall:\",\n\t\"one_m\":\"1 Minute\", \n\t\"two_m\":\"2 Minuten\", \n\t\"five_m\":\"5 Minuten\", \n\t\"ten_m\":\"10 Minuten\", \n\t\"twenty_m\":\"20 Minuten\", \n\t\"thirty_m\":\"30 Minuten\", \n\t\"one_h\":\"1 Stunde\", \n\t\"two_h\":\"2 Stunden\", \n\t\"four_h\":\"4 Stunden\", \n\t\"six_h\":\"6 Stunden\", \n\t\"half_d\":\"zweimal am Tag\", \n\t\"daily\":\"einmal täglich\", \n\t\"weekly\":\"einmal wöchentlich\"\n}"
  },
  {
    "path": "modules/SwitchPolling/lang/en.json",
    "content": "{\n\t\"m_title\":\"Periodical Switch Polling\",\n\t\"m_descr\":\"Due to a US patent some North American Switches (Wall Switches and Smart Plugs) don’t report a status change caused by local action. In order to have the correct statuses displayed these switches need to be regularly polled by the gateway. This app controls this polling. The devices and the polling frequency can be set. Please note this this app is a work around for a legacy problem of the North American Devices. You do not need to apply this app for devices sold outside the United States. Even some modern devices in the US have overcome the restriction. That’s why you can consider this app as a work around for legacy US switches only.<br><br>Settings:<br><ul><li>Poll all switches in Gateway, that are not updated within the defined polling frequency. Exclude switches and dimmers from this polling as you like via dropdown list. </li><li>Define the polling frequency. How often shall the devices be polled. Please note that heavy polling may create heavy traffic in the Z-Wave network and slow down other applications. That’s why there is no option to poll more often than every minute.</li></ul>\",\n\t\"l_devices\":\"Switches excluded from polling:\",\n\t\"l_period\":\"Poll period\",\n\t\"one_m\":\"1 minute\", \n\t\"two_m\":\"2 minute\", \n\t\"five_m\":\"5 minute\", \n\t\"ten_m\":\"10 minute\", \n\t\"twenty_m\":\"20 minute\", \n\t\"thirty_m\":\"30 minute\", \n\t\"one_h\":\"1 hour\", \n\t\"two_h\":\"2 hours\", \n\t\"four_h\":\"4 hours\", \n\t\"six_h\":\"6 hours\", \n\t\"half_d\":\"twice per day\", \n\t\"daily\":\"daily\", \n\t\"weekly\":\"weekly\"\n}"
  },
  {
    "path": "modules/SwitchPolling/module.json",
    "content": "{\n\t\"dependencies\": [\"Cron\"],\n\t\"singleton\": true,\n\t\"category\": \"legacy_products_workaround\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"SwitchPolling\",\n\t\"version\": \"1.0.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"devices\": [],\n\t\t\"period\": 60\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"devices\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId\",\n\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t}\n\t\t\t},\n\t\t\t\"period\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"required\": true,\n\t\t\"enum\": [1, 2, 5, 10, 20, 30, 60, 120, 240, 360, 720, 1440, 10080]\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"devices\": {\n\t\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t},\n\t\t\t\"period\": {\n\t\t\t\t\"label\": \"__l_period__\",\n\t\t\t\t\"optionLabels\": [\"__one_m__\", \"__two_m__\", \"__five_m__\", \"__ten_m__\", \"__twenty_m__\", \"__thirty_m__\", \"__one_h__\", \"__two_h__\", \"__four_h__\", \"__six_h__\", \"__half_d__\", \"__daily__\", \"__weekly__\"]\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/TPLinkHS100/index.js",
    "content": "/*** TPLinkHS100 Z-Way HA module *******************************************\n\nVersion: 1.0.1\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Karsten Reichel <kar@zwave.eu>\nDescription:\n\tThis module allows to switch the TP-Link HS100 plug.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\n\nfunction TPLinkHS100 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tTPLinkHS100.super_.call(this, id, controller);\n}\n\ninherits(TPLinkHS100, AutomationModule);\n\n_module = TPLinkHS100;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nTPLinkHS100.prototype.init = function (config) {\n\tTPLinkHS100.super_.prototype.init.call(this, config);\n\n\t\tvDevId = \"TPLinkHS100_\" + this.id;\n\n\t\tthis.commands = {\n\t\t\ton: \t'{\"system\":{\"set_relay_state\":{\"state\":1}}}',\n\t\t\toff: \t'{\"system\":{\"set_relay_state\":{\"state\":0}}}',\n\t\t\tupdate: '{\"system\":{\"get_sysinfo\":{}}}'\n\t\t};\n\n\t\tthis.encrypt = function(data) {\n\t\t\tvar key = 171;\n\t\t\tvar result = \"\";\n\t\t\tfor (var i = 3 ; i >= 0 ; i--) {\n\t\t\t\t\tresult += String.fromCharCode( (data.length>>(8*i))&255 );\n\t\t\t}\n\t\t\tfor (var i = 0, len = data.length; i < len; i++) {\n\t\t\t\t\tkey = key^data.charCodeAt(i);\n\t\t\t\t\tresult += String.fromCharCode(key);\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\n\t\tthis.decrypt = function(data) {\n\t\t\tvar key = 171;\n\t\t\tvar result = \"\";\n\t\t\tfor (var i = 4, len = data.length; i < len; i++) {\n\t\t\t\tvar a = key^data.charCodeAt(i);\n\t\t\t\tkey = data.charCodeAt(i);\n\t\t\t\tresult += String.fromCharCode(a);\n\t\t\t}\n\t\t\treturn JSON.parse(result);\n\t\t}\n\n\t\tvar self = this;\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: 'switch',\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t},\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tdeviceType: 'switchBinary'\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar sock = new sockets.tcp();\n\t\t\t\tsock.onconnect = function() {\n\t\t\t\t\tthis.send(self.encrypt(self.commands[command]));\n\t\t\t\t\tif (command != 'update') {\n\t\t\t\t\t\tthis.close();\n\t\t\t\t\t\tself.vDev.set('metrics:level', command);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tif (command == 'update') {\n\t\t\t\t\tsock.onrecv = function(data, host, port) {\n\t\t\t\t\t\tvar msg = String.fromCharCode.apply(null, new Uint8Array(data));\n\t\t\t\t\t\tvar res = self.decrypt(msg);\n\t\t\t\t\t\tif (typeof res.system.get_sysinfo.relay_state != 'undefined') {\n\t\t\t\t\t\t\tself.vDev.set('metrics:level', res.system.get_sysinfo.relay_state == 1 ? 'on' : 'off');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.close();\n\t\t\t\t\t};\n\n\t\t\t\t}\n\t\t\t\tsock.connect(self.config.url, 9999);\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n};\n\nTPLinkHS100.prototype.stop = function () {\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tTPLinkHS100.super_.prototype.stop.call(this);\n};\n"
  },
  {
    "path": "modules/TPLinkHS100/lang/de.json",
    "content": "{\n\t\"m_title\":\"TP-Link HS100\",\n\t\"m_descr\":\"Diese App ermöglicht Ihnen die Steuerung Ihrer TP-Link HS100 WLAN Steckdose. Geben Sie dazu einfach die IP-Adresse der komplett eingerichteten WLAN Steckdose an.\",\n\t\"ip\":\"IP-Adresse des Schalters\",\n\t\"h_ip\":\"Beispielformat: '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/TPLinkHS100/lang/en.json",
    "content": "{\n\t\"m_title\":\"TP-Link HS100\",\n\t\"m_descr\":\"This app allows you to control your TP-Link HS100 WLAN plugs. Simply enter the IP address of the completely configured WLAN plug.\",\n\t\"ip\":\"Plug IP URL\",\n\t\"h_ip\":\"in the format '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/TPLinkHS100/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"wifiplug\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://www.tp-link.com/\",\n    \"state\": null,\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"TPLinkHS100\",\n    \"version\": \"1.0.1\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n            \"type\": \"git\",\n            \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n\t\"url\": \"\"\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"url\": {\n                \"required\": true\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"url\": {\n                \"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\n                \"required\": true\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/TPLinkHS110/index.js",
    "content": "/*** TPLinkHS110 Z-Way HA module *******************************************\n\nVersion: 1.0.1\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Karsten Reichel <kar@zwave.eu>\nDescription:\n\tThis module allows to switch the TP-Link HS110 plug.\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\n\nfunction TPLinkHS110 (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tTPLinkHS110.super_.call(this, id, controller);\n}\n\ninherits(TPLinkHS110, AutomationModule);\n\n_module = TPLinkHS110;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nTPLinkHS110.prototype.init = function (config) {\n\tTPLinkHS110.super_.prototype.init.call(this, config);\n\n\t\tvDevId = \"TPLinkHS110_\" + this.id;\n\n\t\tthis.commands = {\n\t\t\ton: \t'{\"system\":{\"set_relay_state\":{\"state\":1}}}',\n\t\t\toff: \t'{\"system\":{\"set_relay_state\":{\"state\":0}}}',\n\t\t\tupdate: '{\"system\":{\"get_sysinfo\":{}}}'\n\t\t};\n\n\t\tthis.encrypt = function(data) {\n\t\t\tvar key = 171;\n\t\t\tvar result = \"\";\n\t\t\tfor (var i = 3 ; i >= 0 ; i--) {\n\t\t\t\t\tresult += String.fromCharCode( (data.length>>(8*i))&255 );\n\t\t\t}\n\t\t\tfor (var i = 0, len = data.length; i < len; i++) {\n\t\t\t\t\tkey = key^data.charCodeAt(i);\n\t\t\t\t\tresult += String.fromCharCode(key);\n\t\t\t}\n\t\t\treturn result\n\t\t}\n\n\t\tthis.decrypt = function(data) {\n\t\t\tvar key = 171;\n\t\t\tvar result = \"\";\n\t\t\tfor (var i = 4, len = data.length; i < len; i++) {\n\t\t\t\tvar a = key^data.charCodeAt(i);\n\t\t\t\tkey = data.charCodeAt(i);\n\t\t\t\tresult += String.fromCharCode(a);\n\t\t\t}\n\t\t\treturn JSON.parse(result);\n\t\t}\n\n\t\tvar self = this;\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: 'switch',\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t},\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tdeviceType: 'switchBinary'\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar sock = new sockets.tcp();\n\t\t\t\tsock.onconnect = function() {\n\t\t\t\t\tthis.send(self.encrypt(self.commands[command]));\n\t\t\t\t\tif (command != 'update') {\n\t\t\t\t\t\tthis.close();\n\t\t\t\t\t\tself.vDev.set('metrics:level', command);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tif (command == 'update') {\n\t\t\t\t\tsock.onrecv = function(data, host, port) {\n\t\t\t\t\t\tvar msg = String.fromCharCode.apply(null, new Uint8Array(data));\n\t\t\t\t\t\tvar res = self.decrypt(msg);\n\t\t\t\t\t\tif (typeof res.system.get_sysinfo.relay_state != 'undefined') {\n\t\t\t\t\t\t\tself.vDev.set('metrics:level', res.system.get_sysinfo.relay_state == 1 ? 'on' : 'off');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.close();\n\t\t\t\t\t};\n\n\t\t\t\t}\n\t\t\t\tsock.connect(self.config.url, 9999);\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n};\n\nTPLinkHS110.prototype.stop = function () {\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tTPLinkHS110.super_.prototype.stop.call(this);\n};\n"
  },
  {
    "path": "modules/TPLinkHS110/lang/de.json",
    "content": "{\n\t\"m_title\":\"TP-Link HS110\",\n\t\"m_descr\":\"Diese App ermöglicht Ihnen die Steuerung Ihrer TP-Link HS110 WLAN Steckdose. Geben Sie dazu einfach die IP-Adresse der komplett eingerichteten WLAN Steckdose an.\",\n\t\"ip\":\"IP-Adresse des Schalters\",\n\t\"h_ip\":\"Beispielformat: '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/TPLinkHS110/lang/en.json",
    "content": "{\n\t\"m_title\":\"TP-Link HS110\",\n\t\"m_descr\":\"This app allows you to control your TP-Link HS110 WLAN plugs. Simply enter the IP address of the completely configured WLAN plug.\",\n\t\"ip\":\"Plug IP URL\",\n\t\"h_ip\":\"in the format '192.168.0.50'\"\n}"
  },
  {
    "path": "modules/TPLinkHS110/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"wifiplug\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://www.tp-link.com/\",\n    \"state\": null,\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"TPLinkHS110\",\n    \"version\": \"1.0.1\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n            \"type\": \"git\",\n            \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n\t\"url\": \"\"\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"url\": {\n                \"required\": true\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"url\": {\n                \"label\": \"__ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\n                \"required\": true\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/TagOnOff/index.js",
    "content": "/*** TagOnOff Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2014\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tMark devices with On/Off tags depending on their state\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction TagOnOff (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tTagOnOff.super_.call(this, id, controller);\n}\n\ninherits(TagOnOff, AutomationModule);\n\n_module = TagOnOff;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nTagOnOff.prototype.init = function (config) {\n\tTagOnOff.super_.prototype.init.call(this, config);\n\tvar self = this;\n\n\tthis.controller.devices.forEach(function (vDev) {\n\t\tself.setTagOnOff(vDev);\n\t});\n\t\n\tthis.handler = function(vDev) {\n\t\tself.setTagOnOff(vDev);\n\t};\n\t\n\tthis.controller.devices.on('change:metrics:level', this.handler);\n};\n\nTagOnOff.prototype.stop = function () {\n\tvar self = this;\n\t// Remove tags on and off\n\tthis.controller.devices.forEach(function (vDev) {\n\t\tvDev.removeTag(self.config.tagOff);\n\t\tvDev.removeTag(self.config.tagOn);\n\t});\n\t\n\tthis.controller.devices.off('change:metrics:level', this.handler);\n\n\tTagOnOff.super_.prototype.stop.call(this);\n};\n\nTagOnOff.prototype.setTagOnOff = function(vDev) {\n\tvar type = vDev.get('deviceType'),\n\t\tlevel = vDev.get('metrics:level'),\n\t\tcolor = vDev.get('metrics:color')\n\n\tif (\n\t\t(type === 'switchBinary' && level === 'on') ||\n\t\t(type === 'switchMultilevel' && parseInt(level, 10) > 0) ||\n\t\t(type === 'switchRGBW' && level === 'on' && (color.r > 0 || color.g > 0 || color.b > 0))\n\t) {\n\t\tvDev.addTag(this.config.tagOn);\n\t\tvDev.removeTag(this.config.tagOff);\n\t}\n\t\n\tif (\n\t\t(type === 'switchBinary' && level === 'off') ||\n\t\t(type === 'switchMultilevel' && parseInt(level, 10) === 0) ||\n\t\t(type === 'switchRGBW' && (level === 'off' || (color.r === 0 && color.g === 0 && color.b === 0)))\n\t) {\t\t\n\t\tvDev.removeTag(this.config.tagOn);\n\t\tvDev.addTag(this.config.tagOff);\n\t}\n};\n"
  },
  {
    "path": "modules/TagOnOff/lang/de.json",
    "content": "{\n\t\"m_title\":\"Erzeuge An/Aus-'tags'\",\n\t\"m_descr\":\"Jedes Element kann durch den Benutzer mittels eines Konfigurationsdialogs gekennzeichnet werden. Die App kennzeichnet automatisch schaltende Geräte je nach deren Schaltzustand.<br><br>Einstellungen: Wählen Sie einfach das Zeichen für den An- und Ausstatus.\",\n\t\"l_tagOn\":\"tag für An-Status:\",\n\t\"l_tagOff\":\"tag für Aus-Status:\"\n}"
  },
  {
    "path": "modules/TagOnOff/lang/en.json",
    "content": "{\n\t\"m_title\":\"Tag devices with On/Off\",\n\t\"m_descr\":\"Every element can be tagged by the user using the configuration dialog. The app automatically tags switching devices depending on their switching state.<br>Settings: Just pick the tag of the on state and the off state.\",\n\t\"l_tagOn\":\"Tag for On state\",\n\t\"l_tagOff\":\"Tag for Off state\"\n}"
  },
  {
    "path": "modules/TagOnOff/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Помечать устройства включено/выключено\",\n\t\"m_descr\":\"Выключенные устройства помещаются в группу с меткой 'Off' (Выключено), включенные устройства помещаются в группу с меткой 'On' (Включено).\",\n\t\"l_tagOn\":\"Метка для включенного состояния\",\n\t\"l_tagOff\":\"Метка для выключенного состояния\"\n}"
  },
  {
    "path": "modules/TagOnOff/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"tagging\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"TagOnOff\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"tagOn\": \"On\",\n\t\t\"tagOff\": \"Off\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"tagOn\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"tagOff\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"tagOn\": {\n\t\t\t\t\"label\": \"__l_tagOn__\"\n\t\t\t},\n\t\t\t\"tagOff\": {\n\t\t\t\t\"label\": \"__l_tagOff__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/TamperAutoOff/index.js",
    "content": "/*** TamperAutoOff Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Yurkin Vitaliy <aivs@z-wave.me>\nDescription:\n\tTurn Off tamper widgets after 30 seconds\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction TamperAutoOff (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tTamperAutoOff.super_.call(this, id, controller);\n\n\t// Create instance variables\n\tthis.vDevsWithTimers = {};\n};\n\ninherits(TamperAutoOff, AutomationModule);\n\n_module = TamperAutoOff;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nTamperAutoOff.prototype.init = function (config) {\n\tTamperAutoOff.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.handler = function (vDev) {\n\t\tvar value = vDev.get(\"metrics:level\");\n\t\tif ((\"on\" === value || (parseInt(value) && value > 0)) && self.config.devices.indexOf(vDev.id) === -1) {\n\t\t\t// Device reported \"on\", set (or reset) timer to new timeout\n\t\t\t// If vDev exist\n\t\t\tif (self.vDevsWithTimers && self.vDevsWithTimers[vDev.id]) {\n\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\tclearTimeout(self.vDevsWithTimers[vDev.id]);\n\t\t\t\tself.vDevsWithTimers[vDev.id] = null;\n\t\t\t}\n\t\t\t// Notice: self.config.timeout set in seconds\n\t\t\t(function(_vDev) {\n\t\t\t\tself.vDevsWithTimers[_vDev.id] = setTimeout(function () {\n\t\t\t\t\t// Timeout fired, so we send \"off\" command to the virtual device\n\t\t\t\t\t// Set tamper off for vDev or Z-Wave Device\n\t\t\t\t\tvar id;\n\t\t\t\t\tif ((id = _vDev.id.match(\"(ZWayVDev_([^_]+)_([0-9]+))-([0-9]+)-([0-9]+)-([0-9]+)\")) === null) {\n\t\t\t\t\t\t_vDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else {\n        \t\t\t\t\tzway.devices[parseInt(id[3])].instances[parseInt(id[4])].commandClasses[parseInt(id[5])].data[parseInt(id[6])].level.value = false;\n\t\t\t\t\t}\t\t\t\t\t\n\t\t\t\t\t// And clearing out this timer variable\n\t\t\t\t\tdelete self.vDevsWithTimers[_vDev.id];\n\t\t\t\t}, self.config.timeout*1000);\n\t\t\t})(vDev);\n\t\t} else {\n\t\t\t// Turned off\n\t\t\tif (self.vDevsWithTimers[vDev.id]) {\n\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\tclearTimeout(self.vDevsWithTimers[vDev.id]);\n\t\t\t\tdelete self.vDevsWithTimers[vDev.id];\n\t\t\t}\n\t\t}\n\t};\n\n\tthis.deviceCreated = function (vDev) {\n\t\tif (vDev.get(\"probeType\") === \"tamper\") {\n\t\t\tself.controller.devices.on(vDev.id, 'change:metrics:level', self.handler);\n\t\t}\n\t}\n\n\tthis.deviceRemoved = function (vDev) {\n\t\tif (vDev.get(\"probeType\") === \"tamper\") {\n\t\t\t// Stop binding for device\n\t\t\tself.controller.devices.off(vDev.id, 'change:metrics:level', self.handler);\n\t\t\t// Remove device taimer\n\t\t\tif (self.vDevsWithTimers[vDev.id]) {\n\t\t\t\t// Timer is set, so we destroy it\n\t\t\t\tclearTimeout(self.vDevsWithTimers[vDev.id]);\n\t\t\t\tdelete self.vDevsWithTimers[vDev.id];\n\t\t\t}\n\t\t}\n\t}\n\n\t// Bind to event \"Added new device\" -- > Bind to new device\n\tthis.controller.devices.on('created', this.deviceCreated);   \n\n\t // Bind to event \"Removed device\" --> Unbind device\n\tthis.controller.devices.on('removed', this.deviceRemoved); \n\n\t// If module started after devices created, pass all tampers and bind to them\n\tthis.controller.devices.forEach(function(vDev, i, arr) {\n\t\tif (vDev.get(\"probeType\") === \"tamper\") {\n\t\t\tself.controller.devices.on(vDev.id, 'change:metrics:level', self.handler);\n\t\t}\n\t});\n\n};\n\nTamperAutoOff.prototype.stop = function () {\n\tTamperAutoOff.super_.prototype.stop.call(this);\n\tvar self = this;\n\n\t// Clear all timers\n\tfor(var index in this.vDevsWithTimers) {\n\t\tclearTimeout(this.vDevsWithTimers[index]);\n\t\tdelete self.vDevsWithTimers[index];\n\t}\n\n\t// At stop unbind from all Tampers\n\tthis.controller.devices.forEach(function(vDev, i, arr) {\n\t\tif (vDev.get(\"probeType\") === \"tamper\") {\n\t\t\tself.controller.devices.off(vDev.id, 'change:metrics:level', self.handler);\n\t\t}\n\t});\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n"
  },
  {
    "path": "modules/TamperAutoOff/lang/de.json",
    "content": "{\n\t\"m_title\":\"Tamper Auto Off\",\n\t\"m_descr\":\"Some devices can't send command, when tamper state goes to off. This app sets tamper state to off after timeout.\",\n\t\"l_devices\":\"Tamper excluded from autooff:\",\n\t\"l_timeout\":\"Timeout\"\n}"
  },
  {
    "path": "modules/TamperAutoOff/lang/en.json",
    "content": "{\n\t\"m_title\":\"Tamper Auto Off\",\n\t\"m_descr\":\"Some devices can't send command, when tamper state goes to off. This app sets tamper state to off after timeout.\",\n\t\"l_devices\":\"Tamper excluded from autooff:\",\n\t\"l_timeout\":\"Timeout\"\n}"
  },
  {
    "path": "modules/TamperAutoOff/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Авто выключение тампера\",\n\t\"m_descr\":\"Некоторые устройство не могут прислать команду, что тампер перешел в выключенное состояние. Это приложение переводит тампер в выключенное состояние через определенное время.\",\n\t\"l_devices\":\"Тамперы, которые не нужно автоматически выключать\",\n\t\"l_timeout\":\"Задержка на выключение тампера в секундах\"\n}"
  },
  {
    "path": "modules/TamperAutoOff/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"legacy_products_workaround\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"TamperAutoOff\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"devices\": [],\n\t\t\"timeout\": 30\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"devices\": {\n\t\t\t\t\t\"type\": \"array\",\n\t\t\t\t\t\"items\": {\n\t\t\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"enum\": \"namespaces:devices_sensorBinary:deviceId\",\n\t\t\t\t\t\t\t\"required\": false\n\t\t\t\t\t}\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"devices\": {\n\t\t\t\t\t\"label\": \"__l_devices__\",\n\t\t\t\t\t\"fields\": {\n\t\t\t\t\t\t\"item\": {\n\t\t\t\t\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorBinary:deviceName\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t},\n\t\t\t\"timeout\": {\n\t\t\t\t\"label\": \"__l_timeout__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/TechnaxxTX65/index.js",
    "content": "/*** TechnaxxTX65 Z-Way HA module *******************************************\n\nVersion: 0.0.1\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Michael Hensche mh@zwave.eu\nDescription:\n    This module stores params of TechnaxxTX65\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction TechnaxxTX65 (id, controller) {\n    // Call superconstructor first (AutomationModule)\n    TechnaxxTX65.super_.call(this, id, controller);\n}\n\ninherits(TechnaxxTX65, AutomationModule);\n\n_module = TechnaxxTX65;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(TechnaxxTX65.prototype, {\n    init: function (config) {\n        TechnaxxTX65.super_.prototype.init.call(this, config);\n\n        var that = this,\n            vDevId = \"TechnaxxTX65Device_\" + this.id;\n        \n        var opener = function(command) {\n            config.doorDevices.forEach(function(el) {\n                var vDev = that.controller.devices.get(el);\n                \n                if (vDev) {\n                    var type = vDev.get(\"deviceType\");\n                    if (type === \"switchBinary\" || \"switchMultilevel\") {\n                        vDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n                    } else if (type === \"doorlock\") {\n                            vDev.performCommand(command);\n                    }\n                }\n            });\n        };\n\n        this.proxy_screen_url = \"/\" + vDevId + \"/screen\";\n        this.screen_url = config.ip + config.screenUrl;\n        ws.proxify(this.proxy_screen_url, this.screen_url, config.user, config.password);\n\n        this.proxy_url = \"/\" + vDevId + \"/stream\";\n        this.url = config.ip + config.streamUrl;\n        ws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n        this.vDev = this.controller.devices.create({\n            deviceId: vDevId,\n            defaults: {\n                deviceType: \"camera\",\n                metrics: {\n                    icon: \"camera\",\n                    title: that.getInstanceTitle()\n                }\n            },\n            overlay: {\n                metrics: {\n                    url: this.proxy_url,\n                    screenUrl: this.proxy_screen_url,\n                    hasOpen: !!config.openUrl || (config.doorDevices && config.doorDevices.length),\n                    hasClose: !!config.closeUrl || (config.doorDevices && config.doorDevices.length)\n                }\n            },\n            handler: function(command) {\n                var url = null;\n\n                if (command == \"open\") {\n                    url = config.openUrl;\n                    opener(command);\n                } else if (command == \"close\") {\n                    url = config.closeUrl;\n                    opener(command);\n                };\n\n                if (url) {\n                    http.request({\n                        url: url,\n                        async: true,\n                        auth: {\n                            login: config.user,\n                            password: config.password\n                        }\n                    });\n                }\n            },\n            moduleId: this.id\n        });\n    },\n    stop: function () {\n        TechnaxxTX65.super_.prototype.stop.call(this);\n\n        ws.proxify(this.proxy_url, null);\n        ws.proxify(this.proxy_screen_url, null);\n        \n        if (this.vDev) {\n            this.controller.devices.remove(this.vDev.id);\n            this.vDev = null;\n        }\n    }\n});\n"
  },
  {
    "path": "modules/TechnaxxTX65/lang/de.json",
    "content": "{\n  \"m_title\":\"Technaxx TX-65\",\n  \"m_descr\":\"Unterstützt die Technaxx TX-65 Outdoor Kamera\",\n  \"l_cam_ip\": \"Kamera IP URL\",\n  \"l_user\": \"Benutzername für HTTP Authentifizierung\",\n  \"h_http_auth\": \"Lassen Sie das Feld frei, wenn die Kamera nicht mit einem Passwort geschütztt ist.\",\n  \"l_pw\":\"Passwort für HTTP Authentifiziereung.\",\n  \"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/TechnaxxTX65/lang/en.json",
    "content": "{\n\t\"m_title\":\"Technaxx TX-65\",\n\t\"m_descr\":\"Support the Technaxx TX-65 Outdoor Camera.\",\n\t\"l_cam_ip\":\"Camera IP URL\",\n  \t\"l_user\": \"Username for HTTP authentication\",\n  \t\"l_pw\": \"Password for HTTP authentication\",\n  \t\"h_http_auth\": \"Leave empty if camera is not protected by a password\",\n  \t\"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/TechnaxxTX65/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"surveillance\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://razberry.z-wave.me\",\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"TechnaxxTX65\",\n    \"version\": \"0.0.1\",\n    \"maturity\": \"beta\",\n    \"repository\": {\n            \"type\": \"git\",\n            \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"ip\": \"\",\n        \"streamUrl\": \"/cgi-bin/mjpg/video.cgi?channel=0&subtype=1\",\n        \"screenUrl\": \"/cgi-bin/snapshot.cgi?\",\n        \"user\": \"\",\n        \"password\": \"\",\n        \"doorDevices\": []\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"ip\": {\n                \"format\": \"uri\",\n                \"required\": true\n            },\n            \"user\": {\n                \"required\": false\n            },\n            \"password\": {\n                \"format\": \"password\",\n                \"required\": false\n            },\n            \"doorDevices\": {\n                \"type\": \"array\",\n                \"items\": {\n                    \"field\": \"enum\",\n                    \"datasource\": \"namespaces\",\n                    \"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId\",\n                    \"required\": false\n                }\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"ip\": {\n                \"label\": \"__l_cam_ip__\",\n                \"type\": \"url\",\n                \"allowIntranet\": true,\n                \"required\": true\n            },\n            \"user\": {\n                \"label\": \"__l_user__\",\n\t\t        \"helper\": \"__h_http_auth__\",\n                \"required\": false\n            },\n            \"password\": {\n                \"label\": \"__l_pw__\",\n\t\t        \"helper\": \"__h_http_auth__\",\n                \"required\": false\n            },\n            \"doorDevices\": {\n                \"label\": \"__l_door_dev__\",\n                \"fields\": {\n                    \"item\": {\n\t\t\t        \"type\": \"select\",\n                        \"datasource\": \"namespaces\",\n                        \"field\": \"optionLabels\",\n                        \"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/TechnaxxTX66/index.js",
    "content": "/*** TechnaxxTX66 Z-Way HA module *******************************************\n\n Version: 0.0.1\n (c) Z-Wave.Me, 2017\n -----------------------------------------------------------------------------\n Author: Michael Hensche mh@zwave.eu\n Description:\n This module stores params of TechnaxxTX66\n\n ******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction TechnaxxTX66 (id, controller) {\n    // Call superconstructor first (AutomationModule)\n    TechnaxxTX66.super_.call(this, id, controller);\n}\n\ninherits(TechnaxxTX66, AutomationModule);\n\n_module = TechnaxxTX66;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(TechnaxxTX66.prototype, {\n    init: function (config) {\n        TechnaxxTX66.super_.prototype.init.call(this, config);\n\n        var that = this,\n            vDevId = \"TechnaxxTX66Device_\" + this.id;\n\n        var opener = function(command) {\n            config.doorDevices.forEach(function(el) {\n                var vDev = that.controller.devices.get(el);\n\n                if (vDev) {\n                    var type = vDev.get(\"deviceType\");\n                    if (type === \"switchBinary\" || \"switchMultilevel\") {\n                        vDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n                    } else if (type === \"doorlock\") {\n                        vDev.performCommand(command);\n                    }\n                }\n            });\n        };\n\n        this.proxy_screen_url = \"/\" + vDevId + \"/screen\";\n        this.screen_url = config.ip + config.screenUrl;\n        ws.proxify(this.proxy_screen_url, this.screen_url, config.user, config.password);\n\n        this.proxy_url = \"/\" + vDevId + \"/stream\";\n        this.url = config.ip + config.streamUrl;\n        ws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n        this.vDev = this.controller.devices.create({\n            deviceId: vDevId,\n            defaults: {\n                deviceType: \"camera\",\n                metrics: {\n                    icon: \"camera\",\n                    title: that.getInstanceTitle()\n                }\n            },\n            overlay: {\n                metrics: {\n                    url: this.proxy_url,\n                    screenUrl: this.proxy_screen_url,\n                    hasOpen: !!config.openUrl || (config.doorDevices && config.doorDevices.length),\n                    hasClose: !!config.closeUrl || (config.doorDevices && config.doorDevices.length)\n                }\n            },\n            handler: function(command) {\n                var url = null;\n\n                if (command == \"open\") {\n                    url = config.openUrl;\n                    opener(command);\n                } else if (command == \"close\") {\n                    url = config.closeUrl;\n                    opener(command);\n                };\n\n                if (url) {\n                    http.request({\n                        url: url,\n                        async: true,\n                        auth: {\n                            login: config.user,\n                            password: config.password\n                        }\n                    });\n                }\n            },\n            moduleId: this.id\n        });\n    },\n    stop: function () {\n        TechnaxxTX66.super_.prototype.stop.call(this);\n\n        ws.proxify(this.proxy_url, null);\n        ws.proxify(this.proxy_screen_url, null);\n\n        if (this.vDev) {\n            this.controller.devices.remove(this.vDev.id);\n            this.vDev = null;\n        }\n    }\n});\n"
  },
  {
    "path": "modules/TechnaxxTX66/lang/de.json",
    "content": "{\n  \"m_title\":\"Technaxx TX-66\",\n  \"m_descr\":\"Unterstützt die Technaxx TX-66 Outdoor Kamera\",\n  \"l_cam_ip\": \"Kamera IP URL\",\n  \"l_user\": \"Benutzername für HTTP Authentifizierung\",\n  \"h_http_auth\": \"Lassen Sie das Feld frei, wenn die Kamera nicht mit einem Passwort geschütztt ist.\",\n  \"l_pw\":\"Passwort für HTTP Authentifiziereung.\",\n  \"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/TechnaxxTX66/lang/en.json",
    "content": "{\n\t\"m_title\":\"Technaxx TX-66\",\n\t\"m_descr\":\"Support the Technaxx TX-66 Outdoor Camera.\",\n\t\"l_cam_url\":\"Camera IP URL\",\n  \t\"l_user\": \"Username for HTTP authentication\",\n  \t\"l_pw\": \"Password for HTTP authentication\",\n  \t\"h_http_auth\": \"Leave empty if camera is not protected by a password\",\n  \t\"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/TechnaxxTX66/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"surveillance\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://razberry.z-wave.me\",\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"TechnaxxTX66\",\n    \"version\": \"0.0.1\",\n    \"maturity\": \"beta\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"ip\": \"\",\n        \"streamUrl\": \"/cgi-bin/mjpg/video.cgi?channel=0&subtype=1\",\n        \"screenUrl\": \"/cgi-bin/snapshot.cgi?\",\n        \"user\": \"\",\n        \"password\": \"\",\n        \"doorDevices\": []\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"ip\": {\n                \"format\": \"uri\",\n                \"required\": true\n            },\n            \"user\": {\n                \"required\": false\n            },\n            \"password\": {\n                \"format\": \"password\",\n                \"required\": false\n            },\n            \"doorDevices\": {\n                \"type\": \"array\",\n                \"items\": {\n                    \"field\": \"enum\",\n                    \"datasource\": \"namespaces\",\n                    \"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId\",\n                    \"required\": false\n                }\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"ip\": {\n                \"label\": \"__l_cam_url__\",\n                \"type\": \"url\",\n                \"allowIntranet\": true,\n                \"required\": true\n            },\n            \"user\": {\n                \"label\": \"__l_user__\",\n                \"helper\": \"__h_http_auth__\",\n                \"required\": false\n            },\n            \"password\": {\n                \"label\": \"__l_pw__\",\n                \"helper\": \"__h_http_auth__\",\n                \"required\": false\n            },\n            \"doorDevices\": {\n                \"label\": \"__l_door_dev__\",\n                \"fields\": {\n                    \"item\": {\n                        \"type\": \"select\",\n                        \"datasource\": \"namespaces\",\n                        \"field\": \"optionLabels\",\n                        \"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/TechnaxxTX67/index.js",
    "content": "/*** TechnaxxTX67 Z-Way HA module *******************************************\n\n Version: 1.0.1\n (c) Z-Wave.Me, 2017\n -----------------------------------------------------------------------------\n Author: Michael Hensche mh@zwave.eu\n Description:\n This module stores params of TechnaxxTX67\n\n ******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction TechnaxxTX67 (id, controller) {\n    // Call superconstructor first (AutomationModule)\n    TechnaxxTX67.super_.call(this, id, controller);\n}\n\ninherits(TechnaxxTX67, AutomationModule);\n\n_module = TechnaxxTX67;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(TechnaxxTX67.prototype, {\n    init: function (config) {\n        TechnaxxTX67.super_.prototype.init.call(this, config);\n\n        var that = this,\n            vDevId = \"TechnaxxTX67Device_\" + this.id;\n\n        var opener = function(command) {\n            config.doorDevices.forEach(function(el) {\n                var vDev = that.controller.devices.get(el);\n\n                if (vDev) {\n                    var type = vDev.get(\"deviceType\");\n                    if (type === \"switchBinary\" || \"switchMultilevel\") {\n                        vDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n                    } else if (type === \"doorlock\") {\n                        vDev.performCommand(command);\n                    }\n                }\n            });\n        };\n\n        this.proxy_screen_url = \"/\" + vDevId + \"/screen\";\n        this.screen_url = config.ip + config.screenUrl+ \"&user=\" + config.user +\"&password=\" + config.password;\n        ws.proxify(this.proxy_screen_url, this.screen_url, config.user, config.password);\n\n        this.proxy_url = \"/\" + vDevId + \"/stream\";\n        this.url = config.ip + config.streamUrl + \"&user=\" + config.user +\"&password=\" + config.password;\n        ws.proxify(this.proxy_url, this.url, config.user, config.password);\n\n        this.vDev = this.controller.devices.create({\n            deviceId: vDevId,\n            defaults: {\n                deviceType: \"camera\",\n                metrics: {\n                    icon: \"camera\",\n                    title: that.getInstanceTitle()\n                }\n            },\n            overlay: {\n                metrics: {\n                    url: this.proxy_url,\n                    screenUrl: this.proxy_screen_url,\n                    hasLeft: true,\n                    hasRight: true,\n                    hasUp: true,\n                    hasDown: true,\n                    hasOpen: !!config.openUrl || (config.doorDevices && config.doorDevices.length),\n                    hasClose: !!config.closeUrl || (config.doorDevices && config.doorDevices.length)\n                }\n            },\n            handler: function(command) {\n                var url = null;\n\n                if (command == \"left\") {\n                    url = config.ip +config.leftUrl + \"&user=\" + config.user +\"&password=\" + config.password;\n                } else if (command == \"right\") {\n                    url = config.ip + config.rightUrl + \"&user=\" + config.user +\"&password=\" + config.password;\n                } else if (command == \"up\") {\n                    url = config.ip + config.upUrl + \"&user=\" + config.user +\"&password=\" + config.password;\n                } else if (command == \"down\") {\n                    url = config.ip + config.downUrl + \"&user=\" + config.user +\"&password=\" + config.password;\n                } else if (command == \"open\") {\n                    url = config.openUrl;\n                    opener(command);\n                } else if (command == \"close\") {\n                    url = config.closeUrl;\n                    opener(command);\n                };\n                console.log(\"url\", url);\n                if (url) {\n                    http.request({\n                        url: url,\n                        async: true,\n                        auth: {\n                            login: config.user,\n                            password: config.password\n                        }\n                    });\n                    // send stop command after any move command\n                    var stopUrl = config.ip + config.stopUrl + \"&user=\" + config.user +\"&password=\" + config.password;\n                    setTimeout(function() {\n                        http.request({\n                            url: stopUrl,\n                            async: true,\n                            auth: {\n                                login: config.user,\n                                password: config.password\n                            }\n                        });\n                    }, 500);\n                }\n            },\n            moduleId: this.id\n        });\n    },\n    stop: function () {\n        TechnaxxTX67.super_.prototype.stop.call(this);\n\n        ws.proxify(this.proxy_url, null);\n        ws.proxify(this.proxy_screen_url, null);\n\n        if (this.vDev) {\n            this.controller.devices.remove(this.vDev.id);\n            this.vDev = null;\n        }\n    }\n});\n"
  },
  {
    "path": "modules/TechnaxxTX67/lang/de.json",
    "content": "{\n  \"m_title\":\"Technaxx TX-67\",\n  \"m_descr\":\"Unterstützt die Technaxx TX-67 Outdoor Kamera\",\n  \"l_cam_url\": \"Kamera IP URL\",\n  \"l_user\": \"Benutzername für HTTP Authentifizierung\",\n  \"h_http_auth\": \"Lassen Sie das Feld frei, wenn die Kamera nicht mit einem Passwort geschütztt ist.\",\n  \"l_pw\":\"Passwort für HTTP Authentifiziereung.\",\n  \"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/TechnaxxTX67/lang/en.json",
    "content": "{\n\t\"m_title\":\"Technaxx TX-67\",\n\t\"m_descr\":\"Support the Technaxx TX-67 Outdoor Camera.\",\n\t\"l_cam_url\":\"Camera IP URL\",\n  \t\"l_user\": \"Username for HTTP authentication\",\n  \t\"l_pw\": \"Password for HTTP authentication\",\n  \t\"h_http_auth\": \"Leave empty if camera is not protected by a password\",\n  \t\"l_door_dev\": \"Door device\"\n}"
  },
  {
    "path": "modules/TechnaxxTX67/module.json",
    "content": "{\n    \"singleton\": false,\n    \"dependencies\": [],\n    \"category\": \"surveillance\",\n    \"author\": \"Z-Wave.Me\",\n    \"homepage\": \"http://razberry.z-wave.me\",\n    \"icon\": \"icon.png\",\n    \"moduleName\":\"TechnaxxTX67\",\n    \"version\": \"1.0.1\",\n    \"maturity\": \"stable\",\n    \"repository\": {\n        \"type\": \"git\",\n        \"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n    },\n    \"defaults\": {\n        \"title\": \"__m_title__\",\n        \"description\": \"__m_descr__\",\n        \"ip\": \"\",\n        \"streamUrl\": \"/cgi-bin/mjpg/video.cgi?channel=0&subtype=1\",\n        \"screenUrl\": \"/cgi-bin/snapshot.cgi?channel=0\",\n        \"leftUrl\": \"/cgi-bin/ptz.cgi?action=start&channel=0&code=Left&arg1=0&arg2=3&arg3=0\",\n        \"rightUrl\": \"/cgi-bin/ptz.cgi?action=start&channel=0&code=Right&arg1=0&arg2=3&arg3=0\",\n        \"upUrl\": \"/cgi-bin/ptz.cgi?action=start&channel=0&code=Up&arg1=0&arg2=3&arg3=0\",\n        \"downUrl\": \"/cgi-bin/ptz.cgi?action=start&channel=0&code=Down&arg1=0&arg2=3&arg3=0\",\n        \"stopUrl\": \"/cgi-bin/ptz.cgi?action=stop&channel=0&code=Left&arg1=0&arg2=1&arg3=0\",\n        \"user\": \"\",\n        \"password\": \"\",\n        \"doorDevices\": []\n    },\n    \"schema\": {\n        \"type\": \"object\",\n        \"properties\": {\n            \"ip\": {\n                \"format\": \"uri\",\n                \"required\": true\n            },\n            \"user\": {\n                \"required\": false\n            },\n            \"password\": {\n                \"format\": \"password\",\n                \"required\": false\n            },\n            \"doorDevices\": {\n                \"type\": \"array\",\n                \"items\": {\n                    \"field\": \"enum\",\n                    \"datasource\": \"namespaces\",\n                    \"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId,namespaces:devices_switchMultilevel:deviceId\",\n                    \"required\": false\n                }\n            }\n        },\n        \"required\": false\n    },\n    \"options\": {\n        \"fields\": {\n            \"ip\": {\n                \"label\": \"__l_cam_url__\",\n                \"type\": \"url\",\n                \"allowIntranet\": true,\n                \"required\": true\n            },\n            \"screenUrl\": {\n                \"label\": \"__l_screen_url__\",\n                \"type\": \"url\",\n                \"required\": false\n            },\n            \"user\": {\n                \"label\": \"__l_user__\",\n                \"helper\": \"__h_http_auth__\",\n                \"required\": false\n            },\n            \"password\": {\n                \"label\": \"__l_pw__\",\n                \"helper\": \"__h_http_auth__\",\n                \"required\": false\n            },\n            \"doorDevices\": {\n                \"label\": \"__l_door_dev__\",\n                \"fields\": {\n                    \"item\": {\n                        \"type\": \"select\",\n                        \"datasource\": \"namespaces\",\n                        \"field\": \"optionLabels\",\n                        \"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName,namespaces:devices_switchMultilevel:deviceName\"\n                    }\n                }\n            }\n        }\n    }\n}"
  },
  {
    "path": "modules/TechnaxxTX67/patchnotes.txt",
    "content": "#v1.0.1\n- update control urls (left, right, up, down, stop)\n#v1.0.0\n- update of the module for the newest firmware ot Technaxx TX-67 (irmVersion 2.460.0000.15.R, Build Date: 2018-07-12 WEB Version 3.2.1.490211)\n"
  },
  {
    "path": "modules/ThermostatDevice/index.js",
    "content": "/*** ThermostatDevice Z-Way HA module *******************************************\n\nVersion: 1.1.1\n(c) Z-Wave.Me, 2019\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tImplements thermostat device based on temperature sensor and switch\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction ThermostatDevice (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tThermostatDevice.super_.call(this, id, controller);\n}\n\ninherits(ThermostatDevice, AutomationModule);\n\n_module = ThermostatDevice;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nThermostatDevice.prototype.init = function (config) {\n\tThermostatDevice.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.vDev = this.controller.devices.create({\n\t\tdeviceId: \"ThermostatDevice_\" + this.id,\n\t\tdefaults: {\n\t\t\tdeviceType: \"thermostat\",\n\t\t\tprobeType: \"thermostat_set_point\",\n\t\t\tmetrics: {\n\t\t\t\tscaleTitle:  this.config.scale === 'C' ? '°C' : '°F',\n\t\t\t\tlevel: this.config.scale === 'C' ? 18 : 65,\n\t\t\t\tmin: this.config.scale === 'C' ? 5 : 41,\n\t\t\t\tmax: this.config.scale === 'C' ? 40 : 104,\n\t\t\t\ticon: \"thermostat\",\n\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t}\n\t\t},\n\t\toverlay: {},\n\t\thandler: function (command, args) {\n\t\t\tthis.set(\"metrics:level\", parseFloat(args.level));\n\t\t\tself.checkTemp();\n\t\t},\n\t\tmoduleId: this.id\n\t});\n\t\n\tthis.controller.devices.on(this.config.sensor, 'change:metrics:level', function() {\n\t\tself.checkTemp();\n\t});\n};\n\nThermostatDevice.prototype.stop = function () {\n\tvar self = this;\n\n\tthis.controller.devices.off(this.config.sensor, 'change:metrics:level', function() {\n\t\tself.checkTemp();\n\t});\n\n\tif (this.vDev) {\n\t\tthis.controller.devices.remove(this.vDev.id);\n\t\tthis.vDev = null;\n\t}\n\n\tThermostatDevice.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\nThermostatDevice.prototype.checkTemp = function () {\n\tvar vDevSwitch = this.controller.devices.get(this.config.switch),\n\t\tvDevSensor = this.controller.devices.get(this.config.sensor),\n\t\tvDev = this.vDev;\n\t\n\tif (vDevSwitch && vDevSensor && vDev) {\n\t\tif ((vDevSensor.get('metrics:level') + this.config.hysteresis < vDev.get('metrics:level')) && (vDevSwitch.get('metrics:level') == \"off\" && this.config.heaton || vDevSwitch.get('metrics:level') == \"on\" && !this.config.heaton)) {\n\t\t\tvDevSwitch.performCommand(this.config.heaton ? \"on\" : \"off\");\n\t\t}\n\t\tif ((vDevSensor.get('metrics:level') - this.config.hysteresis > vDev.get('metrics:level')) && (vDevSwitch.get('metrics:level') == \"on\" && this.config.heaton || vDevSwitch.get('metrics:level') == \"off\" && !this.config.heaton)) {\n\t\t\tvDevSwitch.performCommand(this.config.heaton ? \"off\" : \"on\");\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/ThermostatDevice/lang/de.json",
    "content": "{\n\t\"m_title\":\"Virtueller Thermostat\",\n\t\"m_descr\":\"Diese App kombiniert einen Aktor und einen Temperatursensor zu einem Thermostat. Die Schaltung des Aktors erfolgt in Abhängigkeit von gemessener Temperatur und dem durch die App definierten Sollwert.<br><br>Einstellungen:<br><ul><li>Wählen Sie ein Auslösergerät. Das kann jeder An-/Ausschalter im Netzwerk sein.</li><li>Wählen Sie den Temperatursensor.</li></ul><br>Anwendung: Die App erstellt eine App, die die Einstellung eines gezielten Temperatursollwertes ermöglicht.Bitte beachten Sie, dass der gewählte Temperatursensor eventuell nur eine neue Temperaturangabe während eines vorgegebenen Zeitintervalls meldet. Dies kann zum Überschreiten der geregelten Temperatur führen, da ganz einfach der aktualisierte Temperaturwert des Sensors verzögert erfolgt. Infolgedessen achten Sie auf netzbetriebene Geräte mit Temperatursensoren. Denn diese können ihre Messungen häufiger aktualisieren.\",\n\t\"l_switch\":\"Schalter\",\n\t\"l_sensor\":\"Temperatursensor\",\n\t\"l_heaton\":\"Modus\",\n\t\"heat\":\"Heizen\",\n\t\"cool\":\"Kühlen\",\n\t\"l_hysteresis\":\"Hysteresis\",\n\t\"h_hysteresis\":\"Maximaler Bereich zwischen Ist- und Solltemperatur, nachdem sich das Thermostat an/ausschalten soll.\",\n\t\"l_scale\": \"Scale\",\n\t\"scale_C\": \"°C\",\n\t\"scale_F\": \"°F\"\n}"
  },
  {
    "path": "modules/ThermostatDevice/lang/en.json",
    "content": "{\n\t\"m_title\":\"Virtual Thermostat\",\n\t\"m_descr\":\"This app combines an actor and a temperature sensor to form a thermostat. The actor will be turned on off depending on the temperature measured and a set-point defined by the element that is created by this app.<br><br>Settings:<br><ul><li>Pick the actuator device. This can be any on/off switch in the network</li><li>Pick the temperature sensory</li></lu><br><br>Usage: The app will create an app that allows setting the target set-point temperature. Please note that the temperature sensor you pick may only report a new temperature within a given time interval, this may cause an overshooting of the controlled temperature simply because the updated temperature value from the sensor comes very late. Hence, prefer temperature sensor devices that are mains powered and can therefore update their value more frequently.\",\n\t\"l_switch\":\"Switch\",\n\t\"l_sensor\":\"Temperature sensor\",\n\t\"l_heaton\":\"Mode\",\n\t\"heat\":\"Heat\",\n\t\"cool\":\"Cool\",\n\t\"l_hysteresis\":\"Hysteresis\",\n\t\"h_hysteresis\":\"Maximal delta between current and target temperature after which thermostat should turn on/off\",\n\t\"l_scale\": \"Scale\",\n\t\"scale_C\": \"°C\",\n\t\"scale_F\": \"°F\"\n}"
  },
  {
    "path": "modules/ThermostatDevice/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Виртуальный термостат\",\n\t\"m_descr\":\"Виртуальный термостат состоит из датчика и реле\",\n\t\"l_switch\":\"Выключатель (реле)\",\n\t\"l_sensor\":\"Датчик\",\n\t\"l_heaton\":\"Режим\",\n\t\"heat\":\"Обогрев\",\n\t\"cool\":\"Охлаждение\",\n\t\"l_hysteresis\":\"Гистерезис\",\n\t\"h_hysteresis\":\"Максимальная температура коридора между текущем значением температуры и температурой после которой реле должно включиться/выключиться\",\n\t\"l_scale\": \"Шкала\",\n\t\"scale_C\": \"°C\",\n\t\"scale_F\": \"°F\"\n}\n"
  },
  {
    "path": "modules/ThermostatDevice/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"device_enhancements\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"ThermostatDevice\",\n\t\"version\": \"1.1.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"switch\": \"\",\n\t\t\"sensor\": \"\",\n\t\t\"heaton\": true,\n\t\t\"scale\": \"C\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"switch\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"sensor\": {\n\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"enum\": \"namespaces:devices_sensorMultilevel:deviceId\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"heaton\": {\n\t\t\t\t\"enum\": [true, false],\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"hysteresis\": {\n\t\t\t\t\"minimum\": 0,\n\t\t\t\t\"maximum\": 5,\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"scale\": {\n\t\t\t\t\"enum\": [\"C\", \"F\"],\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"switch\": {\n\t\t\t\t\"label\": \"__l_switch__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_switchBinary:deviceName\"\n\t\t\t},\n\t\t\t\"sensor\": {\n\t\t\t\t\"label\": \"__l_sensor__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\"optionLabels\": \"namespaces:devices_sensorMultilevel:deviceName\"\n\t\t\t},\n\t\t\t\"heaton\": {\n\t\t\t\t\"label\": \"__l_heaton__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [\"__heat__\", \"__cool__\"]\n\t\t\t},\n\t\t\t\"hysteresis\": {\n\t\t\t\t\"label\": \"__l_hysteresis__\",\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"helper\": \"__h_hysteresis__\"\n\t\t\t},\n\t\t\t\"scale\": {\n\t\t\t\t\"label\": \"__l_scale__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [\"__scale_C__\", \"__scale_F__\"]\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/VistaCam/TVPIP320PIV1/index.js",
    "content": ""
  },
  {
    "path": "modules/VistaCam/TVPIP320PIV1/lang/de.json",
    "content": ""
  },
  {
    "path": "modules/VistaCam/TVPIP320PIV1/lang/en.json",
    "content": ""
  },
  {
    "path": "modules/VistaCam/TVPIP320PIV1/module.json",
    "content": ""
  },
  {
    "path": "modules/VistaCam/index.js",
    "content": "/*** VistaCam Z-Way HA module *******************************************\n\nVersion: 1.1.0\n(c) Z-Wave.Me, 2017\n-----------------------------------------------------------------------------\nAuthor: Stanislav Morozov <r3b@seoarmy.ru>\nDescription:\n\tThis module stores params of VistaCam\n\n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\nVistaCam\nfunction VistaCam (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tVistaCam.super_.call(this, id, controller);\n}\n\ninherits(VistaCam, AutomationModule);\n\n_module = VistaCam;\n\n// ----------------------------------------------------------------------------\n// --- Module insVistaCam9828tance initialized\n// ----------------------------------------------------------------------------\n\n_.extend(VistaCam.prototype, {\n\tinit: function (config) {\n\t\tVistaCam.super_.prototype.init.call(this, config);\n\t\tvar self=this;\n\t\tvar that = this,\n\t\t\tvDevId = \"CameraDevice_\" + this.id;\n\t\t\n\t\tthis.proxy_url \t= \"/\" + vDevId + \"/stream\";\n\t\tthis.cgi \t\t= \"/cgi-bin/CGIProxy.fcgi?cmd=\";\n\t\t\n\t\t\n\t\tvar opener = function(command) {\n\t\t\tconfig.doorDevices.forEach(function(el) {\n\t\t\t\tvar vDev = that.controller.devices.get(el);\n\t\t\t\t\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvar type = vDev.get(\"deviceType\");\n\t\t\t\t\tif (type === \"switchBinary\") {\n\t\t\t\t\t\tvDev.performCommand(command == \"open\" ? \"on\" : \"off\");\n\t\t\t\t\t} else if (type === \"doorlock\") {\n\t\t\t\t\t\t\tvDev.performCommand(command);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t};\t \n\t\tthis.url\t= config.url + \"/img/video.mjpeg \"; \n\t\tconsole.log(this.url);\t  \n\t\tws.proxify(this.proxy_url, this.url, \"\", \"\");\n\n\t\tthis.vDev = this.controller.devices.create({\n\t\t\tdeviceId: vDevId,\n\t\t\tdefaults: {\n\t\t\t\tdeviceType: \"camera\",\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: \"camera\",\n\t\t\t\t\ttitle: self.getInstanceTitle()\n\t\t\t\t}\n\t\t\t},\n\t\t\toverlay: {\n\t\t\t\tmetrics: {\n\t\t\t\t\turl: this.proxy_url,\n\t\t\t\t}\n\t\t\t},\n\t\t\thandler: function(command) {\n\t\t\t\tvar url = null;\n\n\t\t\t\tif (url) {\n\t\t\t\t\thttp.request({\n\t\t\t\t\t\turl: url,\n\t\t\t\t\t\tasync: true,\n\t\t\t\t\t\tauth: {\n\t\t\t\t\t\t\tlogin: config.user,\n\t\t\t\t\t\t\tpassword: config.password\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tmoduleId: this.id\n\t\t});\n\t},\n\tstop: function () {\n\t\tVistaCam.super_.prototype.stop.call(this);\n\n\t\tws.proxify(this.proxy_url, null);\n\t\t\n\t\tif (this.vDev) {\n\t\t\tthis.controller.devices.remove(this.vDev.id);\n\t\t\tthis.vDev = null;\n\t\t}\n\t}\n});\n"
  },
  {
    "path": "modules/VistaCam/lang/de.json",
    "content": "{\n\t\"m_descr\":\"Ünterstützung der MIOS VistaCam\",\n\t\"l_ip\":\"Kamera IP-Adresse\",\n\t\"h_ip\":\"Beispielformat: 'http://IPADDRESS:PORT'\",\n\t\"l_door_dev\":\"Türsensor\"\n}"
  },
  {
    "path": "modules/VistaCam/lang/en.json",
    "content": "{\n\t\"m_descr\":\"Support the MIOS VistaCam\",\n\t\"l_ip\":\"Camera IP URL\",\n\t\"h_ip\":\"in the format 'http://IPADDRESS:PORT'\",\n\t\"l_door_dev\":\"Door device\"\n}"
  },
  {
    "path": "modules/VistaCam/lang/ru.json",
    "content": "{\n\t\"m_descr\":\"Поддержка Камеры MIOS VistaCam.\",\n\t\"l_ip\":\"URL Камеры\",\n\t\"h_ip\":\"В формате 'http://IPADDRESS:PORT'\",\n\t\"l_door_dev\":\"Устройство управления доступом двери\"\n}"
  },
  {
    "path": "modules/VistaCam/module.json",
    "content": "{\n\t\"singleton\": false,\n\t\"dependencies\": [],\n\t\"category\": \"surveillance\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.foscam.com/\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"VistaCam\",\n\t\"version\": \"1.1.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"VisaCam\",\n\t\t\"description\": \"__m_descr__\",\n\t\"url\": \"\",\n\t\"doorDevices\": []\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"url\": {\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"type\": \"array\",\n\t\t\t\t\"items\": {\n\t\t\t\t\t\"field\": \"enum\",\n\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\"enum\": \"namespaces:devices_doorlock:deviceId,namespaces:devices_switchBinary:deviceId\",\n\t\t\t\t\t\"required\": false\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"url\": {\n\t\t\t\t\"label\": \"__l_ip__\",\n\t\t\t\t\"helper\": \"__h_ip__\",\t\t\t\t\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"doorDevices\": {\n\t\t\t\t\"label\": \"__l_door_dev__\",\n\t\t\t\t\"fields\": {\n\t\t\t\t\t\"item\": {\n\t\t\t\"type\": \"select\",\n\t\t\t\t\t\t\"datasource\": \"namespaces\",\n\t\t\t\t\t\t\"field\": \"optionLabels\",\n\t\t\t\t\t\t\"optionLabels\": \"namespaces:devices_doorlock:deviceName,namespaces:devices_switchBinary:deviceName\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}"
  },
  {
    "path": "modules/ZMEOpenWRT/index.js",
    "content": "/*** ZMEOpenWRT Z-Way HA module *******************************************\n\nVersion: 1.0.0\n(c) Z-Wave.Me, 2016\n-----------------------------------------------------------------------------\nAuthor: Poltorak Serguei <ps@z-wave.me>\nDescription:\n\tSupport for some Z-Wave.Me specific OpenWRT features:\n\t - TimeZone selection (list of TZ was taken from https://wiki.openwrt.org/doc/uci/system#time_zones)\n\t - Open access to all ports from WAN\n\t \n******************************************************************************/\n\n// ----------------------------------------------------------------------------\n// --- Class definition, inheritance and setup\n// ----------------------------------------------------------------------------\n\nfunction ZMEOpenWRT (id, controller) {\n\t// Call superconstructor first (AutomationModule)\n\tZMEOpenWRT.super_.call(this, id, controller);\n}\n\ninherits(ZMEOpenWRT, AutomationModule);\n\n_module = ZMEOpenWRT;\n\n// ----------------------------------------------------------------------------\n// --- Module instance initialized\n// ----------------------------------------------------------------------------\n\nZMEOpenWRT.prototype.init = function (config) {\n\tZMEOpenWRT.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tsaveObject(\"timezone\", this.config.timezone, true);\n\tsaveObject(\"wan_port_access\", this.config.wan_port_access, true);\n}\n\nZMEOpenWRT.prototype.stop = function () {\n\t// unsign event handlers\n\n\t// detach handlers\n\n\tZMEOpenWRT.super_.prototype.stop.call(this);\n};\n\n// ----------------------------------------------------------------------------\n// --- Module methods\n// ----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "modules/ZMEOpenWRT/lang/de.json",
    "content": "{\n\t\"m_title\":\"Zeitzone und Ethernet-Zugang\",\n\t\"m_descr\":\"Konfiguration der Zeitzone und des Ethernet-Zugangs \",\n\t\"l_timezone\": \"Zeitzone\",\n\t\"h_timezone\": \"Wählen Sie eine Zeitzone aus der Liste. Nach dem Speichern ist ein Neustart notwendig, um die Änderung der Zeitzone zu übernehmen.\",\n\t\"l_wan_port_access\": \"Erlaubt den Zugriff auf das Gateway über das Netzwerkkabel.\",\n\t\"rl_wan_port_access\": \"Zugang über Netzwerkkabel aktivieren\",\n\t\"h_wan_port_access\": \"Konfiguriert den Ethernet-Zugang. Dieser ist werkseitig deaktiviert. Wenn Sie das Gerät mit ihrem eigenem lokalen Netzwerk verbinden, ist die Gateway-Sicherheit von ihrem eigenen Netzwerk abhängig.\"\n}"
  },
  {
    "path": "modules/ZMEOpenWRT/lang/en.json",
    "content": "{\n\t\"m_title\":\"Time zone and access from home network\",\n\t\"m_descr\":\"Configuration of time zone and definition of local access by Ethernet.\",\n\t\"l_timezone\": \"Time zone\",\n\t\"h_timezone\": \"Select your time zone from the list. You will need to REBOOT your box after saving this data for time to change.\",\n\t\"l_wan_port_access\": \"Allow access from home network by Ethernet\",\n\t\"rl_wan_port_access\": \"enable Ethernet access\",\n\t\"h_wan_port_access\": \"Access by Ethernet is turned off by factory default. If activated the security of your gateway depends on the security of your cable based home network.\"\n}"
  },
  {
    "path": "modules/ZMEOpenWRT/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Часовой пояс и доступ из WAN\",\n\t\"m_descr\":\"Z-Wave.Me специфичные настройки OpenWRT\",\n\t\"l_timezone\": \"Часовой пояс\",\n\t\"h_timezone\": \"Выберите ваш часовой пояс. Требуется ПЕРЕЗАГРУЗКА для применения нового значения.\",\n\t\"l_wan_port_access\": \"Открыть доступ к интерфейсу контроллера через порт WAN\",\n\t\"rl_wan_port_access\": \"включить доступ из WAN\",\n\t\"h_wan_port_access\": \"Открыть доступ с порта, который обычно смотрит в Интернет. Используйте только если вы подключили контроллер к локальной сети и уверены в её безопасности\"\n}"
  },
  {
    "path": "modules/ZMEOpenWRT/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": true,\n\t\"category\": \"basic_gateway_modules\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://www.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\t\"moduleName\":\"ZMEOpenWRT\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"timezone\": \"UTC\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"timezone\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"enum\": [\"UTC\", \"GMT0\", \"GMT0\", \"EAT-3\", \"CET-1\", \"EAT-3\", \"GMT0\", \"WAT-1\", \"GMT0\", \"GMT0\", \"CAT-2\", \"WAT-1\", \"CAT-2\", \"WET0\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"GMT0\", \"GMT0\", \"EAT-3\", \"EAT-3\", \"WAT-1\", \"WET0\", \"GMT0\", \"CAT-2\", \"CAT-2\", \"SAST-2\", \"EAT-3\", \"EAT-3\", \"CAT-2\", \"WAT-1\", \"WAT-1\", \"WAT-1\", \"GMT0\", \"WAT-1\", \"CAT-2\", \"CAT-2\", \"WAT-1\", \"CAT-2\", \"SAST-2\", \"SAST-2\", \"EAT-3\", \"GMT0\", \"EAT-3\", \"WAT-1\", \"WAT-1\", \"GMT0\", \"GMT0\", \"WAT-1\", \"GMT0\", \"EET-2\", \"CET-1\", \"WAT-1WAST,M9.1.0,M4.1.0\", \"HAST10HADT,M3.2.0,M11.1.0\", \"AKST9AKDT,M3.2.0,M11.1.0\", \"AST4\", \"AST4\", \"BRT3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"ART3\", \"AST4\", \"PYT4PYST,M10.1.0/0,M4.2.0/0\", \"EST5\", \"BRT3\", \"AST4\", \"BRT3\", \"CST6\", \"AST4\", \"AMT4\", \"COT5\", \"MST7MDT,M3.2.0,M11.1.0\", \"MST7MDT,M3.2.0,M11.1.0\", \"AMT4AMST,M10.3.0/0,M2.3.0/0\", \"CST6CDT,M4.1.0,M10.5.0\", \"VET4:30\", \"GFT3\", \"EST5\", \"CST6CDT,M3.2.0,M11.1.0\", \"MST7MDT,M4.1.0,M10.5.0\", \"CST6\", \"AMT4AMST,M10.3.0/0,M2.3.0/0\", \"AST4\", \"GMT0\", \"PST8PDT,M3.2.0,M11.1.0\", \"MST7\", \"MST7MDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"AST4\", \"MST7MDT,M3.2.0,M11.1.0\", \"AMT4\", \"CST6\", \"BRT3\", \"AST4ADT,M3.2.0,M11.1.0\", \"AST4ADT,M3.2.0/0:01,M11.1.0/0:01\", \"EST5EDT,M3.2.0,M11.1.0\", \"AST4\", \"AST4\", \"CST6\", \"ECT5\", \"GYT4\", \"AST4ADT,M3.2.0,M11.1.0\", \"CST5CDT,M3.2.0/0,M10.5.0/1\", \"MST7\", \"EST5EDT,M3.2.0,M11.1.0\", \"CST6CDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"CST6CDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"MST7MDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5\", \"AKST9AKDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"BOT4\", \"PET5\", \"PST8PDT,M3.2.0,M11.1.0\", \"BRT3\", \"CST6\", \"AMT4\", \"AST4\", \"AST4\", \"CST6CDT,M3.2.0,M11.1.0\", \"MST7MDT,M4.1.0,M10.5.0\", \"CST6CDT,M3.2.0,M11.1.0\", \"CST6CDT,M4.1.0,M10.5.0\", \"CST6CDT,M4.1.0,M10.5.0\", \"PMST3PMDT,M3.2.0,M11.1.0\", \"AST4ADT,M3.2.0,M11.1.0\", \"CST6CDT,M4.1.0,M10.5.0\", \"UYT3UYST,M10.1.0,M3.2.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"AST4\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"AKST9AKDT,M3.2.0,M11.1.0\", \"FNT2\", \"CST6CDT,M3.2.0,M11.1.0\", \"CST6CDT,M3.2.0,M11.1.0\", \"MST7MDT,M3.2.0,M11.1.0\", \"EST5\", \"EST5EDT,M3.2.0,M11.1.0\", \"SRT3\", \"MST7\", \"AST4\", \"EST5\", \"AMT4\", \"AST4\", \"CST6CDT,M3.2.0,M11.1.0\", \"CST6CDT,M3.2.0,M11.1.0\", \"BRT3\", \"CST6\", \"AMT4\", \"PST8PDT,M4.1.0,M10.5.0\", \"BRT3\", \"AST4\", \"BRT3BRST,M10.3.0/0,M2.3.0/0\", \"EGT1EGST,M3.5.0/0,M10.5.0/1\", \"MST7MDT,M3.2.0,M11.1.0\", \"AST4\", \"NST3:30NDT,M3.2.0/0:01,M11.1.0/0:01\", \"AST4\", \"AST4\", \"AST4\", \"AST4\", \"CST6\", \"CST6\", \"AST4ADT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"PST8PDT,M3.2.0,M11.1.0\", \"EST5EDT,M3.2.0,M11.1.0\", \"AST4\", \"PST8PDT,M3.2.0,M11.1.0\", \"PST8PDT,M3.2.0,M11.1.0\", \"CST6CDT,M3.2.0,M11.1.0\", \"AKST9AKDT,M3.2.0,M11.1.0\", \"MST7MDT,M3.2.0,M11.1.0\", \"WST-8\", \"DAVT-7\", \"DDUT-10\", \"MIST-11\", \"MAWT-5\", \"NZST-12NZDT,M9.5.0,M4.1.0/3\", \"ROTT3\", \"NZST-12NZDT,M9.5.0,M4.1.0/3\", \"SYOT-3\", \"VOST-6\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"AST-3\", \"ALMT-6\", \"ANAT-11ANAST,M3.5.0,M10.5.0/3\", \"AQTT-5\", \"AQTT-5\", \"TMT-5\", \"AST-3\", \"AST-3\", \"AZT-4AZST,M3.5.0/4,M10.5.0/5\", \"ICT-7\", \"EET-2EEST,M3.5.0/0,M10.5.0/0\", \"KGT-6\", \"BNT-8\", \"CHOT-8\", \"CST-8\", \"IST-5:30\", \"EET-2EEST,M4.1.5/0,M10.5.5/0\", \"BDT-6\", \"TLT-9\", \"GST-4\", \"TJT-5\", \"EET-2EEST,M3.5.6/0:01,M9.1.5\", \"CST-8\", \"ICT-7\", \"HKT-8\", \"HOVT-7\", \"IRKT-8IRKST,M3.5.0,M10.5.0/3\", \"WIT-7\", \"EIT-9\", \"AFT-4:30\", \"PETT-11PETST,M3.5.0,M10.5.0/3\", \"PKT-5\", \"CST-8\", \"NPT-5:45\", \"IST-5:30\", \"KRAT-7KRAST,M3.5.0,M10.5.0/3\", \"MYT-8\", \"MYT-8\", \"AST-3\", \"CST-8\", \"MAGT-11MAGST,M3.5.0,M10.5.0/3\", \"CIT-8\", \"PHT-8\", \"GST-4\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"NOVT-6NOVST,M3.5.0,M10.5.0/3\", \"NOVT-6NOVST,M3.5.0,M10.5.0/3\", \"OMST-7\", \"ORAT-5\", \"ICT-7\", \"WIT-7\", \"KST-9\", \"AST-3\", \"QYZT-6\", \"MMT-6:30\", \"AST-3\", \"SAKT-10SAKST,M3.5.0,M10.5.0/3\", \"UZT-5\", \"KST-9\", \"CST-8\", \"SGT-8\", \"CST-8\", \"UZT-5\", \"GET-4\", \"IRST-3:30IRDT,80/0,264/0\", \"BTT-6\", \"JST-9\", \"ULAT-8\", \"CST-8\", \"ICT-7\", \"VLAT-10VLAST,M3.5.0,M10.5.0/3\", \"YAKT-9YAKST,M3.5.0,M10.5.0/3\", \"YEKT-5YEKST,M3.5.0,M10.5.0/3\", \"AMT-4AMST,M3.5.0,M10.5.0/3\", \"AZOT1AZOST,M3.5.0/0,M10.5.0/1\", \"AST4ADT,M3.2.0,M11.1.0\", \"WET0WEST,M3.5.0/1,M10.5.0\", \"CVT1\", \"WET0WEST,M3.5.0/1,M10.5.0\", \"WET0WEST,M3.5.0/1,M10.5.0\", \"GMT0\", \"GST2\", \"GMT0\", \"FKT4FKST,M9.1.0,M4.3.0\", \"CST-9:30CST,M10.1.0,M4.1.0/3\", \"EST-10\", \"CST-9:30CST,M10.1.0,M4.1.0/3\", \"EST-10EST,M10.1.0,M4.1.0/3\", \"CST-9:30\", \"CWST-8:45\", \"EST-10EST,M10.1.0,M4.1.0/3\", \"EST-10\", \"LHST-10:30LHST-11,M10.1.0,M4.1.0\", \"EST-10EST,M10.1.0,M4.1.0/3\", \"WST-8\", \"EST-10EST,M10.1.0,M4.1.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"GMT0IST,M3.5.0/1,M10.5.0\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"GMT0BST,M3.5.0/1,M10.5.0\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"GMT0BST,M3.5.0/1,M10.5.0\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"GMT0BST,M3.5.0/1,M10.5.0\", \"EET-2EEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"WET0WEST,M3.5.0/1,M10.5.0\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"GMT0BST,M3.5.0/1,M10.5.0\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"EET-2EEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"MSK-3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"SAMT-3SAMST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"VOLT-3VOLST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EET-2EEST,M3.5.0/3,M10.5.0/4\", \"CET-1CEST,M3.5.0,M10.5.0/3\", \"EAT-3\", \"IOT-6\", \"CXT-7\", \"CCT-6:30\", \"EAT-3\", \"TFT-5\", \"SCT-4\", \"MVT-5\", \"MUT-4\", \"EAT-3\", \"RET-4\", \"WST11\", \"NZST-12NZDT,M9.5.0,M4.1.0/3\", \"CHAST-12:45CHADT,M9.5.0/2:45,M4.1.0/3:45\", \"VUT-11\", \"PHOT-13\", \"TKT10\", \"FJT-12\", \"TVT-12\", \"GALT6\", \"GAMT9\", \"SBT-11\", \"ChST-10\", \"HST10\", \"HST10\", \"LINT-14\", \"KOST-11\", \"MHT-12\", \"MHT-12\", \"MART9:30\", \"SST11\", \"NRT-12\", \"NUT11\", \"NFT-11:30\", \"NCT-11\", \"SST11\", \"PWT-9\", \"PST8\", \"PONT-11\", \"PGT-10\", \"CKT10\", \"ChST-10\", \"TAHT10\", \"GILT-12\", \"TOT-13\", \"TRUT-10\", \"WAKT-12\", \"WFT-12\"],\n\t\t\t\t\"required\" : true\n\t\t\t},\n\t\t\t\"wan_port_access\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": false\n\t\t\t}\n\t\t}\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"timezone\": {\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [\"UTC\", \"Africa/Abidjan\", \"Africa/Accra\", \"Africa/Addis Ababa\", \"Africa/Algiers\", \"Africa/Asmara\", \"Africa/Bamako\", \"Africa/Bangui\", \"Africa/Banjul\", \"Africa/Bissau\", \"Africa/Blantyre\", \"Africa/Brazzaville\", \"Africa/Bujumbura\", \"Africa/Casablanca\", \"Africa/Ceuta\", \"Africa/Conakry\", \"Africa/Dakar\", \"Africa/Dar es Salaam\", \"Africa/Djibouti\", \"Africa/Douala\", \"Africa/El Aaiun\", \"Africa/Freetown\", \"Africa/Gaborone\", \"Africa/Harare\", \"Africa/Johannesburg\", \"Africa/Kampala\", \"Africa/Khartoum\", \"Africa/Kigali\", \"Africa/Kinshasa\", \"Africa/Lagos\", \"Africa/Libreville\", \"Africa/Lome\", \"Africa/Luanda\", \"Africa/Lubumbashi\", \"Africa/Lusaka\", \"Africa/Malabo\", \"Africa/Maputo\", \"Africa/Maseru\", \"Africa/Mbabane\", \"Africa/Mogadishu\", \"Africa/Monrovia\", \"Africa/Nairobi\", \"Africa/Ndjamena\", \"Africa/Niamey\", \"Africa/Nouakchott\", \"Africa/Ouagadougou\", \"Africa/Porto-Novo\", \"Africa/Sao Tome\", \"Africa/Tripoli\", \"Africa/Tunis\", \"Africa/Windhoek\", \"America/Adak\", \"America/Anchorage\", \"America/Anguilla\", \"America/Antigua\", \"America/Araguaina\", \"America/Argentina/Buenos Aires\", \"America/Argentina/Catamarca\", \"America/Argentina/Cordoba\", \"America/Argentina/Jujuy\", \"America/Argentina/La Rioja\", \"America/Argentina/Mendoza\", \"America/Argentina/Rio Gallegos\", \"America/Argentina/Salta\", \"America/Argentina/San Juan\", \"America/Argentina/Tucuman\", \"America/Argentina/Ushuaia\", \"America/Aruba\", \"America/Asuncion\", \"America/Atikokan\", \"America/Bahia\", \"America/Barbados\", \"America/Belem\", \"America/Belize\", \"America/Blanc-Sablon\", \"America/Boa Vista\", \"America/Bogota\", \"America/Boise\", \"America/Cambridge Bay\", \"America/Campo Grande\", \"America/Cancun\", \"America/Caracas\", \"America/Cayenne\", \"America/Cayman\", \"America/Chicago\", \"America/Chihuahua\", \"America/Costa Rica\", \"America/Cuiaba\", \"America/Curacao\", \"America/Danmarkshavn\", \"America/Dawson\", \"America/Dawson Creek\", \"America/Denver\", \"America/Detroit\", \"America/Dominica\", \"America/Edmonton\", \"America/Eirunepe\", \"America/El Salvador\", \"America/Fortaleza\", \"America/Glace Bay\", \"America/Goose Bay\", \"America/Grand Turk\", \"America/Grenada\", \"America/Guadeloupe\", \"America/Guatemala\", \"America/Guayaquil\", \"America/Guyana\", \"America/Halifax\", \"America/Havana\", \"America/Hermosillo\", \"America/Indiana/Indianapolis\", \"America/Indiana/Knox\", \"America/Indiana/Marengo\", \"America/Indiana/Petersburg\", \"America/Indiana/Tell City\", \"America/Indiana/Vevay\", \"America/Indiana/Vincennes\", \"America/Indiana/Winamac\", \"America/Inuvik\", \"America/Iqaluit\", \"America/Jamaica\", \"America/Juneau\", \"America/Kentucky/Louisville\", \"America/Kentucky/Monticello\", \"America/La Paz\", \"America/Lima\", \"America/Los Angeles\", \"America/Maceio\", \"America/Managua\", \"America/Manaus\", \"America/Marigot\", \"America/Martinique\", \"America/Matamoros\", \"America/Mazatlan\", \"America/Menominee\", \"America/Merida\", \"America/Mexico City\", \"America/Miquelon\", \"America/Moncton\", \"America/Monterrey\", \"America/Montevideo\", \"America/Montreal\", \"America/Montserrat\", \"America/Nassau\", \"America/New York\", \"America/Nipigon\", \"America/Nome\", \"America/Noronha\", \"America/North Dakota/Center\", \"America/North Dakota/New Salem\", \"America/Ojinaga\", \"America/Panama\", \"America/Pangnirtung\", \"America/Paramaribo\", \"America/Phoenix\", \"America/Port of Spain\", \"America/Port-au-Prince\", \"America/Porto Velho\", \"America/Puerto Rico\", \"America/Rainy River\", \"America/Rankin Inlet\", \"America/Recife\", \"America/Regina\", \"America/Rio Branco\", \"America/Santa Isabel\", \"America/Santarem\", \"America/Santo Domingo\", \"America/Sao Paulo\", \"America/Scoresbysund\", \"America/Shiprock\", \"America/St Barthelemy\", \"America/St Johns\", \"America/St Kitts\", \"America/St Lucia\", \"America/St Thomas\", \"America/St Vincent\", \"America/Swift Current\", \"America/Tegucigalpa\", \"America/Thule\", \"America/Thunder Bay\", \"America/Tijuana\", \"America/Toronto\", \"America/Tortola\", \"America/Vancouver\", \"America/Whitehorse\", \"America/Winnipeg\", \"America/Yakutat\", \"America/Yellowknife\", \"Antarctica/Casey\", \"Antarctica/Davis\", \"Antarctica/DumontDUrville\", \"Antarctica/Macquarie\", \"Antarctica/Mawson\", \"Antarctica/McMurdo\", \"Antarctica/Rothera\", \"Antarctica/South Pole\", \"Antarctica/Syowa\", \"Antarctica/Vostok\", \"Arctic/Longyearbyen\", \"Asia/Aden\", \"Asia/Almaty\", \"Asia/Anadyr\", \"Asia/Aqtau\", \"Asia/Aqtobe\", \"Asia/Ashgabat\", \"Asia/Baghdad\", \"Asia/Bahrain\", \"Asia/Baku\", \"Asia/Bangkok\", \"Asia/Beirut\", \"Asia/Bishkek\", \"Asia/Brunei\", \"Asia/Choibalsan\", \"Asia/Chongqing\", \"Asia/Colombo\", \"Asia/Damascus\", \"Asia/Dhaka\", \"Asia/Dili\", \"Asia/Dubai\", \"Asia/Dushanbe\", \"Asia/Gaza\", \"Asia/Harbin\", \"Asia/Ho Chi Minh\", \"Asia/Hong Kong\", \"Asia/Hovd\", \"Asia/Irkutsk\", \"Asia/Jakarta\", \"Asia/Jayapura\", \"Asia/Kabul\", \"Asia/Kamchatka\", \"Asia/Karachi\", \"Asia/Kashgar\", \"Asia/Kathmandu\", \"Asia/Kolkata\", \"Asia/Krasnoyarsk\", \"Asia/Kuala Lumpur\", \"Asia/Kuching\", \"Asia/Kuwait\", \"Asia/Macau\", \"Asia/Magadan\", \"Asia/Makassar\", \"Asia/Manila\", \"Asia/Muscat\", \"Asia/Nicosia\", \"Asia/Novokuznetsk\", \"Asia/Novosibirsk\", \"Asia/Omsk\", \"Asia/Oral\", \"Asia/Phnom Penh\", \"Asia/Pontianak\", \"Asia/Pyongyang\", \"Asia/Qatar\", \"Asia/Qyzylorda\", \"Asia/Rangoon\", \"Asia/Riyadh\", \"Asia/Sakhalin\", \"Asia/Samarkand\", \"Asia/Seoul\", \"Asia/Shanghai\", \"Asia/Singapore\", \"Asia/Taipei\", \"Asia/Tashkent\", \"Asia/Tbilisi\", \"Asia/Tehran\", \"Asia/Thimphu\", \"Asia/Tokyo\", \"Asia/Ulaanbaatar\", \"Asia/Urumqi\", \"Asia/Vientiane\", \"Asia/Vladivostok\", \"Asia/Yakutsk\", \"Asia/Yekaterinburg\", \"Asia/Yerevan\", \"Atlantic/Azores\", \"Atlantic/Bermuda\", \"Atlantic/Canary\", \"Atlantic/Cape Verde\", \"Atlantic/Faroe\", \"Atlantic/Madeira\", \"Atlantic/Reykjavik\", \"Atlantic/South Georgia\", \"Atlantic/St Helena\", \"Atlantic/Stanley\", \"Australia/Adelaide\", \"Australia/Brisbane\", \"Australia/Broken Hill\", \"Australia/Currie\", \"Australia/Darwin\", \"Australia/Eucla\", \"Australia/Hobart\", \"Australia/Lindeman\", \"Australia/Lord Howe\", \"Australia/Melbourne\", \"Australia/Perth\", \"Australia/Sydney\", \"Europe/Amsterdam\", \"Europe/Andorra\", \"Europe/Athens\", \"Europe/Belgrade\", \"Europe/Berlin\", \"Europe/Bratislava\", \"Europe/Brussels\", \"Europe/Bucharest\", \"Europe/Budapest\", \"Europe/Chisinau\", \"Europe/Copenhagen\", \"Europe/Dublin\", \"Europe/Gibraltar\", \"Europe/Guernsey\", \"Europe/Helsinki\", \"Europe/Isle of Man\", \"Europe/Istanbul\", \"Europe/Jersey\", \"Europe/Kaliningrad\", \"Europe/Kiev\", \"Europe/Lisbon\", \"Europe/Ljubljana\", \"Europe/London\", \"Europe/Luxembourg\", \"Europe/Madrid\", \"Europe/Malta\", \"Europe/Mariehamn\", \"Europe/Minsk\", \"Europe/Monaco\", \"Europe/Moscow\", \"Europe/Oslo\", \"Europe/Paris\", \"Europe/Podgorica\", \"Europe/Prague\", \"Europe/Riga\", \"Europe/Rome\", \"Europe/Samara\", \"Europe/San Marino\", \"Europe/Sarajevo\", \"Europe/Simferopol\", \"Europe/Skopje\", \"Europe/Sofia\", \"Europe/Stockholm\", \"Europe/Tallinn\", \"Europe/Tirane\", \"Europe/Uzhgorod\", \"Europe/Vaduz\", \"Europe/Vatican\", \"Europe/Vienna\", \"Europe/Vilnius\", \"Europe/Volgograd\", \"Europe/Warsaw\", \"Europe/Zagreb\", \"Europe/Zaporozhye\", \"Europe/Zurich\", \"Indian/Antananarivo\", \"Indian/Chagos\", \"Indian/Christmas\", \"Indian/Cocos\", \"Indian/Comoro\", \"Indian/Kerguelen\", \"Indian/Mahe\", \"Indian/Maldives\", \"Indian/Mauritius\", \"Indian/Mayotte\", \"Indian/Reunion\", \"Pacific/Apia\", \"Pacific/Auckland\", \"Pacific/Chatham\", \"Pacific/Efate\", \"Pacific/Enderbury\", \"Pacific/Fakaofo\", \"Pacific/Fiji\", \"Pacific/Funafuti\", \"Pacific/Galapagos\", \"Pacific/Gambier\", \"Pacific/Guadalcanal\", \"Pacific/Guam\", \"Pacific/Honolulu\", \"Pacific/Johnston\", \"Pacific/Kiritimati\", \"Pacific/Kosrae\", \"Pacific/Kwajalein\", \"Pacific/Majuro\", \"Pacific/Marquesas\", \"Pacific/Midway\", \"Pacific/Nauru\", \"Pacific/Niue\", \"Pacific/Norfolk\", \"Pacific/Noumea\", \"Pacific/Pago Pago\", \"Pacific/Palau\", \"Pacific/Pitcairn\", \"Pacific/Ponape\", \"Pacific/Port Moresby\", \"Pacific/Rarotonga\", \"Pacific/Saipan\", \"Pacific/Tahiti\", \"Pacific/Tarawa\", \"Pacific/Tongatapu\", \"Pacific/Truk\", \"Pacific/Wake\", \"Pacific/Wallis\"],\n\t\t\t\t\"label\": \"__l_timezone__\",\n\t\t\t\t\"helper\": \"__h_timezone__\"\n\t\t\t},\n\t\t\t\"wan_port_access\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"label\": \"__l_wan_port_access__\",\n\t\t\t\t\"rightLabel\": \"__rl_wan_port_access__\",\n\t\t\t\t\"helper\": \"__h_wan_port_access__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/ZMatter/index.js",
    "content": "/*** ZMatter Binding module ********************************************************\n\nVersion: 1.0.0\n-------------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>\nCopyright: (c) Z-Wave.Me, 2024\n\n******************************************************************************/\n\nif (!String.prototype.padStart) {\n\tString.prototype.padStart = function padStart(targetLength,padString) {\n\t\ttargetLength = targetLength>>0; //floor if number or convert non-number to 0;\n\t\tpadString = String(padString || ' ');\n\t\tif (this.length > targetLength) {\n\t\t\treturn String(this);\n\t\t}\n\t\telse {\n\t\t\ttargetLength = targetLength-this.length;\n\t\t\tif (targetLength > padString.length) {\n\t\t\t\tpadString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed\n\t\t\t}\n\t\t\treturn padString.slice(0,targetLength) + String(this);\n\t\t}\n\t};\n}\n\n\nfunction ZMatter(id, controller) {\n\n\t// if called without \"new\", return list of loaded Z-Matter instances\n\tif (!(this instanceof ZMatter))\n\t\treturn ZMatter.list();\n\n\tZMatter.super_.call(this, id, controller);\n\n\tthis.ZWAY_DEVICE_CHANGE_TYPES = {\n\t\t\"DeviceAdded\": 0x01,\n\t\t\"DeviceRemoved\": 0x02,\n\t\t\"EndPointAdded\": 0x04,\n\t\t\"EndPointRemoved\": 0x08,\n\t\t\"ClusterAdded\": 0x10,\n\t\t\"ClusterRemoved\": 0x20,\n\t\t\"ZDDXSaved\": 0x100,\n\t\t\"EnumerateExisting\": 0x200\n\t};\n\n\tthis.ZWAY_DATA_CHANGE_TYPE = {\n\t\t\"Updated\": 0x01, // Value updated or child created\n\t\t\"Invalidated\": 0x02, // Value invalidated\n\t\t\"Deleted\": 0x03, // Data holder deleted - callback is called last time before being deleted\n\t\t\"ChildCreated\": 0x04, // New direct child node created\n\n\t\t// ORed flags\n\t\t\"PhantomUpdate\": 0x40, // Data holder updated with same value (only updateTime changed)\n\t\t\"ChildEvent\": 0x80 // Event from child node\n\t};\n\n\tthis.CC = {\n\t\t\"OnOff\": 0x0006,\n\t\t\"LevelControl\": 0x0008,\n\t\t\"DoorLock\": 0x0101,\n\t\t\"WindowCovering\": 0x0102,\n\t\t\"ColorControl\": 0x0300,\n\t\t\"TemperatureMeasurement\": 0x0402,\n\t\t\"PressureMeasurement\": 0x0403,\n\t\t\"RelativeHumidityMeasurement\": 0x0405,\n\t\t\"OccupancySensing\": 0x0406,\n\t\t\"IasZone\": 0x0500,\n\t};\n}\n\n// Module inheritance and setup\n\ninherits(ZMatter, AutomationModule);\n\n_module = ZMatter;\n\nObject.defineProperty(ZMatter, \"list\", {\n\tvalue: function(__, req) {\n\t\t// show in the list if called directly (not via web) or role is admin or API is public\n\t\treturn Object.keys(ZMatter).filter(function(name) {\n\t\t\treturn !req || req.role == controller.auth.ROLE.ADMIN || ZMatter[name].publicAPI;\n\t\t});\n\t},\n\tenumerable: false,\n\twritable: false,\n\tconfigurable: false\n});\n\nws.allowExternalAccess(\"ZMatter.list\", controller.auth.ROLE.ANONYMOUS); // we handle role inside the handler\n\nZMatter.prototype.updateList = function() {\n\tthis.controller.setNamespace(\"zmatters\", this.controller.namespaces, ZMatter.list().map(function(name) {\n\t\treturn {\n\t\t\tzmatterName: name\n\t\t};\n\t}));\n};\n\nZMatter.prototype.loadObject = function(name) {\n\ttry {\n\t\treturn loadObject(this.config.name + \"_\" + name);\n\t} catch (e) {\n\t\tthis.addNotification('warning','Error in storage file: '+ name + ' detected. Unable to load data - ERROR: '+ e.toString() + ' File will be rewritten if possible.','z-wave');\n\t\treturn null;\n\t}\n};\n\nZMatter.prototype.saveObject = function(name, obj, immediate) {\n\treturn saveObject(this.config.name + \"_\" + name, obj, immediate);\n};\n\nZMatter.prototype.init = function(config) {\n\tZMatter.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.restartBindingCounter = 0;\n\n\tthis.startBinding();\n\tif (!this.zmatter) {\n\t\treturn;\n\t}\n\n\tthis._dataBind = function(dataBindings, zmatterName, nodeId, endpointId, clusterId, path, func, type) {\n\t\tif (zmatterName === self.config.name && self.zmatter) {\n\t\t\tself.dataBind(dataBindings, self.zmatter, nodeId, endpointId, clusterId, path, func, type);\n\t\t}\n\t};\n\tthis._dataUnbind = function(dataBindings) {\n\t\tself.dataUnbind(dataBindings);\n\t};\n\n\tthis.controller.on(\"ZMatter.dataBind\", this._dataBind);\n\tthis.controller.on(\"ZMatter.dataUnbind\", this._dataUnbind);\n\n\tthis.controller.emit(\"ZMatter.register\", this.config.name);\n};\n\nZMatter.prototype.startBinding = function() {\n\tvar self = this;\n\n\ttry {\n\t\tthis.zmatter = new ZMatterBinding(this.config.name, this.config.port, this.config.speed || 115200, this.config.bleOverDHorWS, {\n\t\t\tconfigFolder: this.config.config || 'config',\n\t\t\tpaaFolder: this.config.paaFolder || 'config/paa-root-certs',\n\t\t\tcdFolder: this.config.cdFolder || null,\n\t\t\tterminationCallback: function() {\n\t\t\t\tself.terminating.call(self);\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\tthis.zmatter.discover();\n\t\t} catch (e1) {\n\t\t\tthis.zmatter.stop();\n\t\t\tconsole.log(e1.toString());\n\t\t\treturn;\n\t\t}\n\t} catch (e) {\n\t\tthis.zmatter = null;\n\t\tconsole.log(e.toString());\n\t\tthis.tryRestartLater(e);\n\t\treturn;\n\t}\n\n\t// started\n\tthis.restartBindingCounter = 0;\n\n\tthis.fastAccess = false;\n\tif (!global.zmatter) {\n\t\t// this is the first zmatter - make fast shortcut\n\t\tthis.fastAccess = true;\n\t}\n\n\tglobal.ZMatter[this.config.name] = {\n\t\t\"zmatter\": this.zmatter,\n\t\t\"port\": this.config.port,\n\t\t\"publicAPI\": this.config.publicAPI,\n\t\t\"fastAccess\": this.fastAccess\n\t};\n\tthis.updateList();\n\n\tif (this.config.wifiEssid && this.config.wifiPassword)\n\t{\n\t\tthis.zmatter.controller.SetWiFiConfig(this.config.wifiEssid, this.config.wifiPassword);\n\t}\n\n\tif (this.config.threadCredential)\n\t{\n\t\tthis.zmatter.controller.SetThreadConfig(this.config.threadCredential);\n\t}\n\t\n\tthis.stopped = false;\n\n\tif (this.config.enableAPI !== false) {\n\t\tthis.defineHandlers();\n\t}\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIAllow();\n\t\t}\n\t\tglobal[\"zmatter\"] = this.zmatter; // global variable\n\t\tglobal[\"ZMatterAPI\"] = this.ZMatterAPI;\n\t}\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIAllow(this.config.name);\n\t}\n\t_.extend(global[\"ZMatter\"][this.config.name], this.ZMatterAPI);\n\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStart();\n\t}\n\n\tthis.timeUpdaterStart();\n\n\t// save data every hour for hot start\n\tthis.saveDataXMLTimer = setInterval(function() {\n\t\tself.zmatter.devices.SaveData();\n\t}, 3600 * 1000);\n};\n\nZMatter.prototype.stop = function() {\n\tconsole.log(\"--- ZMatter.stop()\");\n\tZMatter.super_.prototype.stop.call(this);\n\n\tthis.stopBinding();\n\n\tif (this._dataBind) {\n\t\tthis.controller.off(\"ZMatter.dataBind\", this._dataBind);\n\t}\n\tif (this._dataUnbind) {\n\t\tthis.controller.off(\"ZMatter.dataUnbind\", this._dataUnbind);\n\t}\n};\n\nZMatter.prototype.stopBinding = function() {\n\tthis.controller.emit(\"ZMatter.unregister\", this.config.name);\n\n\tthis.networkReorganization = null;\n\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStop();\n\t}\n\n\tthis.timeUpdaterStop();\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIRevoke();\n\t\t}\n\t\tif (global.zmatter) {\n\t\t\tdelete global[\"zmatter\"];\n\t\t\tdelete global[\"ZMatterAPI\"];\n\t\t}\n\t}\n\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIRevoke(this.config.name);\n\t}\n\n\tif (global.ZMatter) {\n\t\tdelete global.ZMatter[this.config.name];\n\t\tthis.updateList();\n\t}\n\n\tif (this.saveDataXMLTimer) {\n\t\tclearInterval(this.saveDataXMLTimer);\n\t\tthis.saveDataXMLTimer = undefined;\n\t}\n\n\tthis.stopped = true;\n\tif (this.zmatter) {\n\t\ttry {\n\t\t\tthis.zmatter.stop();\n\t\t} catch (e) {\n\t\t\t// Z-Matter has already gone\n\t\t}\n\t\tthis.zmatter = null;\n\t}\n};\n\nZMatter.prototype.tryRestartLater = function(e) {\n\tvar delay = 10;\n\n\tif (this.restartBindingCounter < 5) {\n\t\tvar self = this;\n\n\t\tconsole.log(\"Trying to restart ZMatter binding (\" + this.config.name + \") in \" + delay + \" seconds\");\n\t\tthis.restartBindingCounter++;\n\n\t\tsetTimeout(function() {\n\t\t\t// retry open after N seconds\n\t\t\tconsole.log(\"Restarting ZMatter binding (\" + self.config.name + \")\");\n\t\t\tself.startBinding();\n\t\t}, delay * 1000);\n\n\t} else {\n\t\tvar langFile = this.loadModuleLang();\n\n\t\tconsole.log(\"Tried \" + this.restartBindingCounter + \" times without success. Stopping tries.\");\n\t\tthis.addNotification(\"critical\", langFile.err_binding_start + e.toString(), \"z-wave\");\n\t}\n};\n\nZMatter.prototype.terminating = function() {\n\tif (!this.stopped) {\n\t\tconsole.log(\"Terminating ZMatter binding\");\n\t\tthis.stopBinding();\n\t\tthis.tryRestartLater();\n\t}\n};\n\n\n// --------------- Public HTTP API -------------------\n\n\nZMatter.prototype.externalAPIAllow = function(name) {\n\tvar _name = !!name ? (\"ZMatter.\" + name) : \"ZMatterAPI\";\n\n\tws.allowExternalAccess(_name, this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Run\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Data\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".InspectQueue\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\t/*\n\tws.allowExternalAccess(_name + \".Backup\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Restore\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".FirmwareUpdate\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMELicense\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMEFirmwareUpgrade\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMEBootloaderUpgrade\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".EncryptionKeys\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\t*/\n\t// -- see below -- // ws.allowExternalAccess(_name + \".JSONtoXML\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n};\n\nZMatter.prototype.externalAPIRevoke = function(name) {\n\tvar _name = !!name ? (\"ZMatter.\" + name) : \"ZMatterAPI\";\n\n\tws.revokeExternalAccess(_name);\n\tws.revokeExternalAccess(_name + \".Run\");\n\tws.revokeExternalAccess(_name + \".Data\");\n\tws.revokeExternalAccess(_name + \".InspectQueue\");\n\t/*\n\tws.revokeExternalAccess(_name + \".Backup\");\n\tws.revokeExternalAccess(_name + \".Restore\");\n\tws.revokeExternalAccess(_name + \".FirmwareUpdate\");\n\tws.revokeExternalAccess(_name + \".ZMELicense\");\n\tws.revokeExternalAccess(_name + \".ZMEFirmwareUpgrade\");\n\tws.revokeExternalAccess(_name + \".ZMEBootloaderUpgrade\");\n\tws.revokeExternalAccess(_name + \".EncryptionKeys\");\n\t*/\n\t// -- see below -- // ws.revokeExternalAccess(_name + \".JSONtoXML\");\n};\n\nZMatter.prototype.defineHandlers = function() {\n\tvar zmatter = this.zmatter; // for with() statement in Run and other APIs\n\tvar self = this;\n\n\tthis.ZMatterAPI = function() {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Bad ZMatterAPI request \"\n\t\t};\n\t};\n\n\tthis.ZMatterAPI.list = function() {\n\t\ttry {\n\t\t\treturn ZMatter.list() || [];\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.Run = function(url) {\n\t\turl = \"with(zmatter) { \" + url.substring(1) + \" }\";\n\t\ttry {\n\t\t\tvar r = eval(url);\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: r\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.Data = function(url) {\n\t\tvar timestamp = parseInt(url.substring(1), 10) || 0;\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zmatter.data(timestamp)\n\t\t};\n\t};\n\n\tthis.ZMatterAPI.InspectQueue = function(url) {\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zmatter.InspectQueue()\n\t\t};\n\t};\n\n\t/*\n\tthis.ZMatterAPI.Backup = function(url, request) {\n\t\tvar now = new Date();\n\n\t\t// create a timestamp in format yyyy-MM-dd-HH-mm\n\t\tvar ts = getHRDateformat(now);\n\n\t\ttry {\n\n\t\t\t// do backup\n\t\t\tvar data = zmatter.controller.Backup();\n\t\t\tvar filename = \"z-way-backup-\" + ts + \".zbk\"\n\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/x-download\",\n\t\t\t\t\t\"Content-Disposition\": \"attachment; filename=\" + filename\n\t\t\t\t},\n\t\t\t\tbody: data\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.Restore = function(url, request) {\n\t\tif (request.method === \"POST\" && request.data && request.data && request.data.config_backup) {\n\t\t\tvar full = false;\n\t\t\tif (request.query && request.query.hasOwnProperty(\"restore_chip_info\")) {\n\t\t\t\tvar rci = request.query[\"restore_chip_info\"];\n\t\t\t\tfull = (rci === \"yes\" || rci === \"true\" || rci === \"1\");\n\t\t\t}\n\n\t\t\tvar file = request.data.config_backup;\n\t\t\tif (file endpointof Array) {\n\t\t\t\tfile = file[0];\n\t\t\t}\n\t\t\tif (file.name && file.content && file.length > 0) {\n\t\t\t\t// valid file object detected\n\t\t\t\ttry {\n\t\t\t\t\tzmatter.controller.Restore(file.content, full);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: null\n\t\t\t\t\t};\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tbody: e.toString()\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid request\"\n\t\t};\n\t};\n\n\tthis.ZMatterAPI.FirmwareUpdate = function(url, request) {\n\t\ttry {\n\t\t\tvar deviceId = parseInt(url.substring(1), 10);\n\t\t\tif (!deviceId) {\n\t\t\t\tthrow \"Invalid device id\";\n\t\t\t}\n\n\t\t\tvar fwUpdate = zmatter.devices[deviceId].FirmwareUpdate;\n\t\t\tif (!fwUpdate) {\n\t\t\t\tthrow \"Device doesn't support FW Update\";\n\t\t\t}\n\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar manufacturerId = fwUpdate.data.manufacturerId.value;\n\t\t\tvar targetId = parseInt(data.targetId);\n\t\t\tvar firmwareId = targetId == 0 ? fwUpdate.data.firmwareId.value : fwUpdate.data[\"firmware\" + targetId].value;\n\t\t\t\n\t\t\tif (!manufacturerId && manufacturerId !== 0 || !firmwareId && firmwareId !== 0) {\n\t\t\t\tthrow \"Either manufacturer or firmware id is not present\";\n\t\t\t}\n\n\t\t\tif (targetId === 0 && !fwUpdate.data.upgradeable.value) {\n\t\t\t\tthrow \"Firmware is not upgradeable\";\n\t\t\t}\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\t// update firmware from file\n\t\t\t\tvar fw;\n\t\t\t\tif (data.file.content.substr(0, 1) === \":\") {\n\t\t\t\t\t// this is a .hex file\n\t\t\t\t\tfw = IntelHex2bin(data.file.content);\n\t\t\t\t} else {\n\t\t\t\t\tfw = data.file.content;\n\t\t\t\t}\n\t\t\t\tfwUpdate.Perform(manufacturerId, firmwareId, targetId, fw);\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: \"Initiating update\"\n\t\t\t\t};\n\t\t\t} else if (data.url) {\n\t\t\t\tvar result = {\n\t\t\t\t\tstatus: 'in progress'\n\t\t\t\t};\n\t\t\t\tvar d = Date.now() + 300000; // wait no more than 5 min\n\t\t\t\t// update firmware from url\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tcontentType: \"application/octet-stream\", // enforce binary response,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tsuccess: function(res) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar data = new Uint8Array(res.data);\n\t\t\t\t\t\t\tvar data_str = \"\";\n\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\tdata_str += String.fromCharCode(data[i]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar fw;\n\t\t\t\t\t\t\tif (data_str.substr(0, 1) === \":\") {\n\t\t\t\t\t\t\t\t// this is a .hex file\n\t\t\t\t\t\t\t\tfw = IntelHex2bin(data_str);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfw = data_str;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfwUpdate.Perform(manufacturerId, firmwareId, targetId, fw);\n\n\t\t\t\t\t\t\tresult.status = 'done';\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tresult.error = 'Firmware download successful. Parsing has failed: ' + e.toString();\n\t\t\t\t\t\t\tresult.status = 'fail';\n\t\t\t\t\t\t\tthrow ('Firmware download successful. Parsing has failed: ' + e.toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tresult.error = 'Failed to download firmware: ' + res.statusText;\n\t\t\t\t\t\tresult.status = 'fail';\n\t\t\t\t\t\tthrow ('Failed to download firmware: ' + res.statusText);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\twhile (Date.now() < d && result.status === \"in progress\") {\n\t\t\t\t\tprocessPendingCallbacks();\n\t\t\t\t}\n\n\t\t\t\tresult.status = result.status === 'in progress' ? 'fail' : result.status;\n\n\t\t\t\tif (result.status === 'fail') {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tbody: result.error\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: \"Initiating update\"\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.ZMELicense = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data || !data.license) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\t\t\t\n\t\t\tvar func, lic;\n\t\t\tif (parseFloat(zmatter.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\tfunc = zmatter.ZMELicenseSet;\n\t\t\t\tlic = data.license.match(/.{2}/g).map(function(i, v) { return parseInt(i, 16); });\n\t\t\t} else {\n\t\t\t\tfunc = zmatter.ZMECapabilities;\n\t\t\t\tlic = data.license.split(\",\").map(function(i) { return parseInt(i, 10); });\n\t\t\t}\n\t\t\t\n\t\t\tfunc.call(zmatter, lic, function() {\n\t\t\t\tresult = \"done\";\n\t\t\t}, function() {\n\t\t\t\tresult = \"failed\";\n\t\t\t});\n\n\t\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.ZMEFirmwareUpgrade = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tif (zmatter.controller.data.SDK.value === null) {\n\t\t\t\tconsole.log(\"Unknown SDK version - update Z-Way\");\n\t\t\t\tthrow \"Unknown SDK version - update Z-Way\";\n\t\t\t}\n\n\t\t\tvar L = 32,\n\t\t\t\taddr,\n\t\t\t\tskip1800;\n\n\t\t\tif (parseFloat(zmatter.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t// ZGM130S/ZG14\n\t\t\t\tskip1800 = false;\n\t\t\t\taddr = 0x3A000;\n\t\t\t} else {\n\t\t\t\t// ZM5101/SD3503/ZM5202\n\t\t\t\tif (zmatter.controller.data.manufacturerId.value === 0) { // Z-Wave.Me Hub\n\t\t\t\t\tskip1800 = true;\n\t\t\t\t\taddr =  0x7800; // M25PE10\n\t\t\t\t} else {\n\t\t\t\t\tskip1800 =\n\t\t\t\t\t\tzmatter.controller.data.bootloader.crc.value !== 0x8aaa // bootloader for RaZberry 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzmatter.controller.data.bootloader.crc.value !== 0x7278 // bootloader for UZB 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzmatter.controller.data.bootloader.crc.value !== 0x9d04 // bootloader for UZB 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzmatter.controller.data.bootloader.crc.value !== 0x8b4b // bootloader for Z-Box 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tparseFloat(zmatter.controller.data.SDK.value.substr(0, 4)) < 6.71; // bootloader for 6.71 SDK\n\t\t\t\t\taddr = skip1800 ? 0x7800: 0x20000; // M25PE40 on old and new SDKs\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\tconsole.log(\"Fetching firmware from file \" + data.file.name);\n\n\t\t\t\tvar buf = new ArrayBuffer(data.file.content.length);\n\t\t\t\tvar bufView = new Uint8Array(buf);\n\t\t\t\tfor (var i = 0; i < data.file.content.length; i++) {\n\t\t\t\t\tbufView[i] = data.file.content.charCodeAt(i);\n\t\t\t\t}\n\n\t\t\t\tvar data = skip1800 ? buf.slice(0x1800) : buf;\n\n\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t}\n\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t}\n\n\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr - 2, [0, 1], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tzmatter.SerialAPISoftReset(function() {\n\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\tzmatter.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t} else if (data.url) {\n\t\t\t\tconsole.log(\"Fetching firmware from \" + data.url);\n\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcontentType: \"application/octet-stream\",\n\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\tvar data = skip1800 ? response.data.slice(0x1800) : response.data;\n\n\t\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr - 2, [0, 1], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\tzmatter.SerialAPISoftReset(function() {\n\t\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\t\tzmatter.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tconsole.error(\"Failed to download firmware: \" + res.statusText);\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Wrong request. Failed to apply firmware.\");\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 300 * 1000; // wait not more than 5 minutes\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.ZMEBootloaderUpgrade = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\tconsole.log(\"Fetching bootloader from file \" + data.file.name);\n\t\t\t\t\n\t\t\t\tvar buf = new ArrayBuffer(data.file.content.length);\n\t\t\t\tvar bufView = new Uint8Array(buf);\n\t\t\t\tfor (var i = 0; i < data.file.content.length; i++) {\n\t\t\t\t\tbufView[i] = data.file.content.charCodeAt(i);\n\t\t\t\t}\n\t\t\t\tvar data = buf;\n\n\t\t\t\tif (parseFloat(zmatter.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t\tvar arr = (new Uint8Array(data.slice(0, 30)));\n\t\t\t\t\tzmatter.ZMEBootloaderLoadFlash(data.slice(0, 5), function() {\n\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\tzmatter.stop(); // to force re-start Z-Way\n\t\t\t\t\t}, function() {\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar L = 32,\n\t\t\t\t\t\tseg = 6, // Функция бутлодера принимает номер сегмента\n\t\t\t\t\t\taddr = seg * 0x800; // ==12k\n\n\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t}\n\t\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t}\n\n\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr - 2, [0, 0], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t//Вызываем перезапись bootloder\n\t\t\t\t\t\t\tzmatter.ZMEBootloaderFlash(seg, function() {\n\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\tzmatter.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (data.url) {\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcontentType: \"application/octet-stream\",\n\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\tif (parseFloat(zmatter.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t\t\t\tzmatter.ZMEBootloaderLoadFlash(data, function() {\n\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\tzmatter.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar L = 32,\n\t\t\t\t\t\t\t\tseg = 6, // Функция бутлодера принимает номер сегмента\n\t\t\t\t\t\t\t\taddr = seg * 0x800, // ==12k\n\t\t\t\t\t\t\t\tdata = response.data;\n\n\t\t\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tzmatter.NVMExtWriteLongBuffer(addr - 2, [0, 0], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t//Вызываем перезапись bootloder\n\t\t\t\t\t\t\t\t\tzmatter.ZMEBootloaderFlash(seg, function() {\n\t\t\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\t\t\tzmatter.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tconsole.error(\"Failed to download bootloader: \" + res.statusText);\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Wrong request. Failed to apply bootloader.\");\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 60 * 1000; // wait not more than 60 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZMatterAPI.EncryptionKeys = function () {\n\t\tvar filename = ('00000000' + (zmatter.controller.data.homeId.value + (zmatter.controller.data.homeId.value < 0 ? 0x100000000 : 0)).toString(16)).slice(-8)\n\t\tvar reply = {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/plain\", // application/x-download octet-stream\n\t\t\t\t\"Content-Disposition\": \"attachment; filename=\" + filename.toUpperCase() + \".txt\",\n\t\t\t},\n\t\t\tbody: null,\n\t\t\terror: null,\n\t\t\tmessage: null\n\t\t};\n\t\tvar networkKeys = [zmatter.devices[zmatter.controller.data.nodeId.value].data.networkKey.value];\n\t\tvar keys = zmatter.devices[zmatter.controller.data.nodeId.value].data.networkKeys;\n\t\tif (keys) {\n\t\t\tnetworkKeys.push(keys.S2Unauthenticated.value, keys.S2Authenticated.value, keys.S2Access.value);\n\t\t}\n\t\tif (keys.S2AuthenticatedLR) {\n\t\t\tnetworkKeys.push(keys.S2AuthenticatedLR.value, keys.S2AccessLR.value)\n\t\t}\n\n\t\treply.body = networkKeys.map(function (key, index) {\n\t\t\treturn (index ? '9F' : '98') + ';' + (key ? key : new Array(16).fill(0))\n\t\t\t\t.map(function (e) {return (+e).toString(16).padStart(2, '0').toUpperCase()}).join('') + ';1';\n\t\t}).join('\\r\\n');\n\n\t\treturn reply;\n\t}\n\t*/\n};\n\n\n// ------------- Data Binding --------------\n\nZMatter.prototype._dataBind = function(dataBindings, zmatterName, nodeId, endpointId, clusterId, path, func, type) {\n\tif (zmatterName === this.config.name) {\n\t\tthis.dataBind(dataBindings, this.zmatter, nodeId, endpointId, clusterId, path, func, type);\n\t}\n}\nZMatter.prototype.dataBind = function(dataBindings, zmatter, nodeId, endpointId, clusterId, path, func, type) {\n\t// three prototypes:\n\t//  (dataBindings, zmatter, nodeId, endpointId, clusterId, path, func, type)\n\t//  (dataBindings, zmatter, nodeId,                             path, func)\n\t//  (dataBindings, zmatter,                                     path, func) // bind to controller data\n\n\tvar pathArr = [],\n\t\tdata = null,\n\t\tctrlBind = is_function(endpointId),\n\t\tdevBind = is_function(clusterId);\n\n\tif (ctrlBind) {\n\t\tpath = nodeId;\n\t\tfunc = endpointId;\n\t\tnodeId = undefined;\n\t\tendpointId = undefined;\n\t\tclusterId = undefined;\n\t\tdata = zmatter.controller.data;\n\t} else if (devBind) {\n\t\tpath = endpointId;\n\t\tfunc = clusterId;\n\t\tendpointId = undefined;\n\t\tclusterId = undefined;\n\t\tdata = zmatter.devices[nodeId].data;\n\t} else {\n\t\tdata = zmatter.devices[nodeId].endpoints[endpointId].clusters[clusterId].data;\n\t}\n\n\tif (path) {\n\t\tpathArr = path.split(\".\");\n\t}\n\n\tif (!func) {\n\t\tconsole.log(\"Function passed to dataBind is undefined\");\n\t\treturn;\n\t}\n\n\twhile (pathArr.length) {\n\t\tdata = data[pathArr.shift()];\n\t\tif (!data) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (data) {\n\t\tif (ctrlBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zmatter\": zmatter,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, false)\n\t\t\t});\n\t\t} else if (devBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zmatter\": zmatter,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, nodeId, false)\n\t\t\t});\n\t\t} else {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zmatter\": zmatter,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"endpointId\": endpointId,\n\t\t\t\t\"clusterId\": clusterId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, null, type === \"child\")\n\t\t\t});\n\t\t\tif (type === \"value\") {\n\t\t\t\tfunc.call(data, this.ZWAY_DATA_CHANGE_TYPE.Updated);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconsole.log(\"Can not find data path:\", nodeId, endpointId, clusterId, path);\n\t}\n};\n\nZMatter.prototype.dataUnbind = function(dataBindings) {\n\tdataBindings.forEach(function(item) {\n\t\tvar ctrlBind = !(\"nodeId\" in item),\n\t\t\tdevBind = !(\"endpointId\" in item);\n\n\t\tif (item.zmatter && item.zmatter.isRunning() && (ctrlBind || (item.zmatter.devices[item.nodeId] && (devBind || (item.zmatter.devices[item.nodeId].endpoints[item.endpointId] && item.zmatter.devices[item.nodeId].endpoints[item.endpointId].clusters[item.clusterId]))))) {\n\t\t\tvar data = ctrlBind ? item.zmatter.controller.data : (devBind ? item.zmatter.devices[item.nodeId].data : item.zmatter.devices[item.nodeId].endpoints[item.endpointId].clusters[item.clusterId].data),\n\t\t\t\tpathArr = item.path ? item.path.split(\".\") : [];\n\n\t\t\twhile (pathArr.length) {\n\t\t\t\tdata = data[pathArr.shift()];\n\t\t\t\tif (!data) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data) {\n\t\t\t\tdata.unbind(item.func);\n\t\t\t} else {\n\t\t\t\tconsole.log(\"Can not find data path:\", item.nodeId, item.endpointId, item.clusterId, item.path);\n\t\t\t}\n\t\t}\n\t});\n\tdataBindings = null;\n};\n\n// ------------- Update time every day -----\n\nZMatter.prototype.timeUpdaterStart = function() {\n\tvar self = this;\n\t\n\tthis.controller.emit(\"cron.addTask\", \"ZMatterTimeUpdater.poll\", {\n\t\tminute: 0,\n\t\thour: 3,\n\t\tweekDay: null,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\t// add event listener\n\tthis.timeUpdater = function() {\n\t\tvar devices = Object.keys(self.zmatter.devices);\n\t\tdevices.forEach(function(nodeId) {\n\t\t\tif (nodeId == self.zmatter.controller.data.nodeId.value) return; // not a strict === since nodeId is a string index, but number in DH\n\t\t\t\n\t\t\tif (self.zmatter.devices[nodeId].TimeParameters)\n\t\t\t\tself.zmatter.devices[nodeId].TimeParameters.Set();\n\t\t\tif (self.zmatter.devices[nodeId].Clock)\n\t\t\t\tself.zmatter.devices[nodeId].Clock.Set();\n\t\t});\n\t};\n\n\tthis.controller.on(\"ZMatterTimeUpdater.poll\", this.timeUpdater);\n};\n\nZMatter.prototype.timeUpdaterStop = function() {\n\tthis.controller.emit(\"cron.removeTask\", \"ZMatterTimeUpdater.poll\");\n\n\tif (this.timeUpdater)\n\t\tthis.controller.off(\"ZMatterTimeUpdater.poll\", this.timeUpdater);\n}\n\n// ----------------- Devices Creator ---------------\n\n\nZMatter.prototype.gateDevicesStart = function() {\n\n\tvar self = this,\n\t\tfixesDone = [];\n\n\tthis.gateDataBinding = [];\n\n\t// Bind to all future ClusterClasses changes\n\tthis.gateBinding = this.zmatter.bind(function(type, nodeId, endpointId, clusterId) {\n\t\tif (type === self.ZWAY_DEVICE_CHANGE_TYPES[\"ClusterAdded\"]) {\n\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"interviewDone\", function(type) {\n\t\t\t\tif (this.value === true && type !== self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\n\t\t\t\t\tvar create = true,\n\t\t\t\t\t\tchangeVDev = {},\n\t\t\t\t\t\tdeviceData = self.zmatter.devices[nodeId].data,\n\t\t\t\t\t\tdeviceEndPoints = self.zmatter.devices[nodeId].endpoints,\n\t\t\t\t\t\tdeviceCC = deviceEndPoints[endpointId].clusters[clusterId],\n\t\t\t\t\t\tc = self.zmatter.controller,\n\t\t\t\t\t\tmC = deviceData.manufacturerCode.value ? deviceData.manufacturerCode.value : null,\n\t\t\t\t\t\t//appMajor = deviceData.applicationMajor.value ? deviceData.applicationMajor.value : null,\n\t\t\t\t\t\t//appMinor = deviceData.applicationMinor.value ? deviceData.applicationMinor.value : null,\n\t\t\t\t\t\tgivenName = null,\n\t\t\t\t\t\tdevId,\n\t\t\t\t\t\t//appMajorId,\n\t\t\t\t\t\t//appMajorMinorId,\n\t\t\t\t\t\tpostFix;\n\t\t\t\t\t\t//fixes = self.postfix.fixes ? self.postfix.fixes : self.postfix;\n\n\t\t\t\t\t// try to get fix by manufacturerProductId and application Version\n\t\t\t\t\t/* TODO - commented since mC and appMajor are to be implemented in the future\n\t\t\t\t\tif (!!mId && !!mPT && !!mPId && !!self.postfix) {\n\n\t\t\t\t\t\tdevId = mId + '.' + mPT + '.' + mPId;\n\t\t\t\t\t\tappMajorId = devId + '.' + appMajor;\n\t\t\t\t\t\tappMajorMinorId = devId + '.' + appMajor + '.' + appMinor;\n\t\t\t\t\t\tpostFix = fixes.filter(function(fix) {\n\t\t\t\t\t\t\treturn \tfix.p_id === mId.toString() || //search by manufacturerId\n\t\t\t\t\t\t\t\tfix.p_id === devId || //search by manufacturerProductId\n\t\t\t\t\t\t\t\tfix.p_id === appMajorId || //search by applicationMajor\n\t\t\t\t\t\t\t\tfix.p_id === appMajorMinorId; //search by applicationMajor and applicationMinor\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t*/\n\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\t\t\t\t\t// --- postfix functions\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\n\t\t\t\t\t// add SwitchController support by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... endpoint ID\n\t\t\t\t\t// cluster ... Cluster Class ID\n\t\t\t\t\t// minBtnNr ... starting button number\n\t\t\t\t\t// maxBtnNr ... maximum button number\n\t\t\t\t\t// type ... 'S' for 'scene' and 'B' for 'button' or 'switchControl'\n\t\t\t\t\tfunction scenesSupport(instId, cluster, minBtnNr, maxBtnNr, type) {\n\t\t\t\t\t\tvar trapArray = [],\n\t\t\t\t\t\t\tcluster = cluster || null;\n\n\t\t\t\t\t\ttrapArray = self.controller.endpoints.filter(function(endpoint) {\n\t\t\t\t\t\t\treturn endpoint.moduleId === 'SwitchControlGenerator';\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (instId === endpointId && clusterId === cluster && deviceCC && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\tmaxBtnNr = (deviceCC.data.maxScenes && deviceCC.data.maxScenes.value && deviceCC.data.maxScenes.value <= maxBtnNr ? deviceCC.data.maxScenes.value : maxBtnNr) || 0\n\n\t\t\t\t\t\t\tif (trapArray[0].params.generated.indexOf('ZMatterVDev_zmatter_Remote_' + nodeId + '-' + endpointId + '-0-1') === -1) {\n\t\t\t\t\t\t\t\tfor (i = minBtnNr; i <= maxBtnNr; i++) {\n\t\t\t\t\t\t\t\t\tthis.controller.emit('SwitchControlGenerator.register', 'ZMatter', self.config.name, nodeId, endpointId, '0', i, type);\n\t\t\t\t\t\t\t\t\tconsole.logJS(i, minBtnNr, maxBtnNr);\n\n\t\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\t\tconsole.log('#######################', 'ADD SWITCHCONTROLGENERATOR SUPPORT TO #' + nodeId, '###############################');\n\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Add support for endpoint ' + instId + ':');\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'CC:', cluster);\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Set maximum number of buttons / secnes to :', maxBtnNr);\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Add virtual devices as type button (B) or scene (S):', type);\n\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\tconsole.log('############################################################################################################');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// set device config by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... endpoint ID\n\t\t\t\t\t// parameter ... id of the parameter that should be changed. Can be 0 ... 0xff\n\t\t\t\t\t// value ... new value. Can be 0 ... 0xffffffff\n\t\t\t\t\t// size ... 0 for auto or 1, 2, 4 (Byte)\n\t\t\t\t\tfunction setConfig(instId, parameter, value, size) {\n\t\t\t\t\t\tvar parameter = Number.isInteger(parseInt(parameter)) ? parseInt(parameter) : null,\n\t\t\t\t\t\t\tvalue = Number.isInteger(parseInt(value)) ? parseInt(value) : null,\n\t\t\t\t\t\t\tsize = parseInt(size) || null;\n\n\t\t\t\t\t\tif (instId === endpointId && parameter !== null && !!value !== null && size !== null) {\n\t\t\t\t\t\t\t// set config after inclusion only and if it doesn't exist or isn't equal\n\t\t\t\t\t\t\tif (clusterId === 112 && deviceCC && c.data.lastIncludedDevice.value === nodeId && (!deviceCC.data[parameter] || (deviceCC.data[parameter] && deviceCC.data[parameter].val.value !== value))) {\n\t\t\t\t\t\t\t\tdeviceCC.Set(parameter, value, size);\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'CHANGE CONFIGURATION OF #' + nodeId, '###############################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change configuration of endpoint ' + instId + ':');\n\t\t\t\t\t\t\t\tconsole.log('###', 'parameter:', parameter);\n\t\t\t\t\t\t\t\tconsole.log('###', 'value:', value);\n\t\t\t\t\t\t\t\tconsole.log('###', 'size:', size);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change CC entries by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... endpoint ID\n\t\t\t\t\t// cluster ... Cluster Class ID\n\t\t\t\t\t// dataType ... data type object that should be changed -e.g. security, version, interviewDone\n\t\t\t\t\t// key ... of this data type object\n\t\t\t\t\t// value ... new value\n\t\t\t\t\tfunction setCCData(instId, cluster, dataType, key, value) {\n\t\t\t\t\t\tvar cluster = parseInt(cluster, 10);\n\n\t\t\t\t\t\tif (clusterId === cluster &&\n\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster] &&\n\t\t\t\t\t\t\tc.data.lastIncludedDevice.value === nodeId) {\n\n\t\t\t\t\t\t\t// set value\n\t\t\t\t\t\t\tif (typeof value !== 'undefined' &&\n\t\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster].data[dataType] &&\n\t\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster].data[dataType][key] !== value) {\n\n\t\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster].data[dataType][key] = value;\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'SET COMMANDCLASS DATA OF:', devId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change CC entry of endpoint ' + instId + ':');\n\t\t\t\t\t\t\t\tconsole.log('###', 'CC:', cluster);\n\t\t\t\t\t\t\t\tconsole.log('###', 'data type object that has changed:', dataType);\n\t\t\t\t\t\t\t\tconsole.log('###', 'new value for ' + key + ':', value);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('##############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change device entries by entering (runs once after inclusion):\n\t\t\t\t\t// dataType ... data type object that should be changed -e.g. security, version, interviewDone\n\t\t\t\t\t// key ... of this data type object\n\t\t\t\t\t// value ... new value\n\t\t\t\t\tfunction setDeviceData(dataType, key, value) {\n\t\t\t\t\t\tif (c.data.lastIncludedDevice.value === nodeId) {\n\n\t\t\t\t\t\t\t// set value\n\t\t\t\t\t\t\tif (typeof value !== 'undefined' &&\n\t\t\t\t\t\t\t\tdeviceData[dataType] &&\n\t\t\t\t\t\t\t\tdeviceData[dataType][key] !== value) {\n\n\t\t\t\t\t\t\t\tdeviceData[dataType][key] = value;\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'SET DEVICE DATA OF:', devId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change Device entry:');\n\t\t\t\t\t\t\t\tconsole.log('###', 'data type object that has changed:', dataType);\n\t\t\t\t\t\t\t\tconsole.log('###', 'new value for ' + key + ':', value);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('##############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change the node name (runs once after inclusion):\n\t\t\t\t\tfunction renameNode(nodeName) {\n\n\t\t\t\t\t\tif (nodeName !== deviceData.givenName.value) {\n\n\t\t\t\t\t\t\t// do something\n\t\t\t\t\t\t\tdeviceData.givenName.value = nodeName && nodeName !== '' && !!nodeName ? nodeName : deviceData.givenName.value;\n\n\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\tconsole.log('#######################', 'Apply postfix #' + nodeId, '################################');\n\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\tconsole.log('###', 'Change node name to: ', nodeName);\n\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\tconsole.log('######################################################################################');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\t\t\t\t\t// --- END\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\n\t\t\t\t\tif (postFix) {\n\t\t\t\t\t\tif (postFix.length > 0) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// works of course only during inclusion - after restart hidden elements are visible again\n\t\t\t\t\t\t\t\tif (!!nodeId && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\tvar intDone = deviceCC.data.interviewDone.value;\n\t\t\t\t\t\t\t\t\tintDelay = Date.now() + 5 * 1000; // wait not more than 5 seconds for single interview\n\n\t\t\t\t\t\t\t\t\t// wait till interview is done\n\t\t\t\t\t\t\t\t\twhile (Date.now() < intDelay && intDone === false) {\n\t\t\t\t\t\t\t\t\t\tintDone = deviceCC.data.interviewDone.value;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (intDone === false) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t// call preInteview functions from postfix.json\n\t\t\t\t\t\t\t\t\t\t\tpostFix.forEach(function(fix) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!!fix.preInterview && fix.preInterview && fix.preInterview.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tfix.preInterview.forEach(function(func) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teval(func);\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('##############', 'INTERVIEW-HAS-FAILED-----PREFIX-HAS-FAILED:', '#' + nodeId, '#######################');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###', 'ERROR:', e.toString());\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('######################################################################################################');\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// call postInterview functions from postfix.json\n\t\t\t\t\t\t\t\tpostFix.forEach(function(fix) {\n\t\t\t\t\t\t\t\t\tif (!!fix.postInterview && fix.postInterview && fix.postInterview.length > 0) {\n\t\t\t\t\t\t\t\t\t\tfix.postInterview.forEach(function(entry) {\n\t\t\t\t\t\t\t\t\t\t\tvar splittedEntry = entry.split(','),\n\t\t\t\t\t\t\t\t\t\t\t\tdevICC = endpointId + '-' + clusterId;\n\n\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tswitch (splittedEntry[0]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'rename':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'hide':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'deactivate':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'icon':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'probeType':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1 && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) / postFix type / value - fallback true for hide / deactivate\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId][splittedEntry[0]] = splittedEntry[2] ? splittedEntry[2] : true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'discreteState':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1 && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]['discreteState']) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['discreteState'] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) / postFix type / scene + keyAttribute / value - fallback undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['discreteState'][splittedEntry[2]] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcnt: splittedEntry[3] ? splittedEntry[3] : undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taction: splittedEntry[4] ? splittedEntry[4] : undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: splittedEntry[5] ? splittedEntry[5] : undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'noVDev':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) without creation\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].noVDev = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'renameNode':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trenameNode(splittedEntry[1]);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'emulateOff':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[2]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].emulateOff = splittedEntry[2];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'configVDev':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// configVDev, i, cfg#, type, func1, func2, title\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[2] && splittedEntry[3] && splittedEntry[4] && splittedEntry[5]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1] + '-112';\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]['configVDev']) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['configVDev'] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['configVDev'][splittedEntry[2]] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: splittedEntry[3],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tp2v: splittedEntry[4],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tv2p: splittedEntry[5],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: splittedEntry[6] || ('Config #' + splittedEntry[2])\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'tilt':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].tilt = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'notificationStatus':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].notificationStatus = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teval(entry);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'PRE-OR-POSTFIX-ERROR:', '#' + nodeId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'ERROR:', e.toString());\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('#################################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar ccId = nodeId + '-' + endpointId + '-' + clusterId;\n\n\t\t\t\t\tif (!changeVDev[ccId] || (changeVDev[ccId] && !changeVDev[ccId].noVDev)) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, false, changeVDev);\n\t\t\t\t\t} else if (changeVDev[ccId] && changeVDev[ccId].noVDev) {\n\t\t\t\t\t\tvar devId = \"ZMatterVDev_\" + self.config.name + \"_\" + nodeId + '-' + ccId;\n\t\t\t\t\t\t// console output\n\t\t\t\t\t\tconsole.log('#######################', 'Apply postfix for:', devId, '################################');\n\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\tconsole.log('###', 'not created');\n\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\tconsole.log('########################################################################################');\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!deviceData.givenName.value || deviceData.givenName.value == '') {\n\t\t\t\t\t\t// set givenName\n\t\t\t\t\t\tdeviceData.givenName.value = givenName? givenName : self.nodeNameByType(nodeId, deviceData);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tself.parseDelClusterClass(nodeId, endpointId, clusterId);\n\t\t\t\t}\n\t\t\t}, \"value\");\n\t\t} else {\n\t\t\tself.parseDelClusterClass(nodeId, endpointId, clusterId);\n\t\t}\n\t}, this.ZWAY_DEVICE_CHANGE_TYPES[\"ClusterAdded\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"ClusterRemoved\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"EnumerateExisting\"]);\n\n\tself.dataBind(self.gateDataBinding, self.zmatter, \"lastExcludedDevice\", function(type) {\n\t\tvar _id = this.value,\n\t\t\t_toRemove = self.controller.devices.filter(function(el) {\n\t\t\t\treturn el.id.indexOf(\"ZMatterVDev_\" + self.config.name + \"_\" + _id + '-') === 0;\n\t\t\t}).map(function(el) {\n\t\t\t\treturn el.id;\n\t\t\t}).concat(\n\t\t\t\tObject.keys(self.controller.vdevInfo).filter(function(__id) {\n\t\t\t\t\treturn __id.indexOf(\"ZMatterVDev_\" + self.config.name + \"_\" + _id + '-') === 0;\n\t\t\t\t})\n\t\t\t);\n\n\t\t_toRemove.forEach(function(name) {\n\t\t\tself.controller.devices.remove(name);\n\t\t\tself.controller.devices.cleanup(name);\n\t\t});\n\t}, \"\");\n};\n\nZMatter.prototype.gateDevicesStop = function() {\n\tvar self = this;\n\n\t// delete devices\n\tthis.controller.devices.map(function(el) {\n\t\treturn el.id;\n\t}).filter(function(el) {\n\t\treturn el.indexOf(\"ZMatterVDev_\" + self.config.name + \"_\") === 0;\n\t}).forEach(function(el) {\n\t\ttry {\n\t\t\tself.controller.devices.remove(el);\n\t\t} catch (e) {\n\t\t\t// do nothing - this is to prevent Stop abort to make sure we release zmatter context in C\n\t\t}\n\t});\n\n\t// releasing bindings\n\ttry {\n\t\tif (this.gateDataBinding) {\n\t\t\tthis.dataUnbind(this.gateDataBinding);\n\t\t}\n\t\tif (this.zmatter) {\n\t\t\tthis.zmatter.unbind(this.gateBinding);\n\t\t}\n\t} catch (e) {\n\t\t// Z-Matter already gone, skip deallocation\n\t\t//this.zmatter = null;\n\t}\n};\n\nZMatter.prototype.addVDevInfo = function(info, nodeId) {\n\tvar manufacturerName = \"\", modelIdentifier = \"\", swBuildId = \"\";\n\tif (this.zmatter.devices[nodeId].endpoints[1] && this.zmatter.devices[nodeId].endpoints[1].Basic) {\n\t\tvar basicData = this.zmatter.devices[nodeId].endpoints[1].Basic.data;\n\t\tmanufacturerName = basicData.manufacturerName ? basicData.manufacturerName.value : \"\";\n\t\tmodelIdentifier = basicData.modelIdentifier ? basicData.modelIdentifier.value : \"\";\n\t\tswBuildId = basicData.swBuildId ? basicData.swBuildId.value : \"\";\n\t}\n\t_.extend(info, {\n\t\ttechnology: \"ZMatter\",\n\t\tbindingName: this.config.name,\n\t\tnodeId: nodeId,\n\t\tmanufacturer: manufacturerName,\n\t\tproduct: modelIdentifier,\n\t\tfirmware: swBuildId,\n\t\tlocation: 0,\n\t});\n}\n\nZMatter.prototype.compileTitle = function(nodeId, endpointId, title, type, addVendor) { // accepts more arguments, see code\n\tvar sortArgs = [];\n\n\t// add vendor name\n\tif (addVendor === undefined || addVendor === true) {\n\t\tif (this.zmatter.devices[nodeId].endpoints[1] && this.zmatter.devices[nodeId].endpoints[1].Basic) {\n\t\t\tvar vendorName = this.zmatter.devices[nodeId].endpoints[1].Basic.data.manufacturerName ? this.zmatter.devices[nodeId].endpoints[1].Basic.data.manufacturerName.value : \"\";\n\t\t\tif (vendorName) {\n\t\t\t\tsortArgs.push(vendorName);\n\t\t\t}\n\t\t}\n\t}\n\n\tsortArgs.push(title);\n\n\t// add probeType\n\tif (type) {\n\t\tsortArgs.push(type);\n\t}\n\n\t// add id\n\tsortArgs.push(\"(\" + nodeId + (endpointId ? \".\" + endpointId : \"\") + \")\");\n\n\treturn sortArgs.join(' ');\n};\n\nZMatter.prototype.applyPostfix = function(defaultObj, changeObj, nodeId, endpointId, title, type, addVendor) {\n\tthis.addVDevInfo(defaultObj, nodeId);\n\t\n\tdefaultObj.metrics.title = this.compileTitle(nodeId, endpointId, title, type, addVendor);\n\t\n\tif (changeObj) {\n\t\tif (changeObj.noVDev) return false;\n\t\t\n\t\tif (changeObj.probeType)\n\t\t\tdefaultObj.probeType = changeObj.probeType;\n\t\tif (changeObj.icon)\n\t\t\tdefaultObj.metrics.icon = changeObj.icon;\n\t\tif (changeObj.rename)\n\t\t\tdefaultObj.metrics.title = this.compileTitle(nodeId, endpointId, changeObj.rename, undefined, false);\n\t\tdefaultObj.visibility = changeObj.hide ? false : true;\n\t\tdefaultObj.permanently_hidden = changeObj.deactivate ? true : false;\n\t\n\t\tif (changeObj.discreteState && !_.isEmpty(changeObj.discreteState) && defaultObj.metrics.discreteStates) {\n\t\t\tdefaultObj.metrics.discreteStates = changeObj.discreteState;\n\t\t}\n\t}\n\treturn true;\n};\n\nZMatter.prototype.parseAddClusterClass = function(nodeId, endpointId, clusterId, scaleAdded, changeVDev) {\n\tnodeId = parseInt(nodeId, 10);\n\tendpointId = parseInt(endpointId, 10);\n\tclusterId = parseInt(clusterId, 10);\n\n\t// avoid errors during binding stop and device exclusion\n\tif (!this.zmatter || !this.zmatter.devices[nodeId]) {\n\t\treturn;\n\t}\n\n\tvar self = this,\n\t\tendpoint = this.zmatter.devices[nodeId].endpoints[endpointId],\n\t\tendpointClusterClasses = Object.keys(endpoint.clusters).map(function(x) {\n\t\t\treturn parseInt(x);\n\t\t}),\n\t\tcc = endpoint.clusters[clusterId],\n\t\tsepar = \"-\",\n\t\tvDevIdPrefix = \"ZMatterVDev_\" + this.config.name + \"_\",\n\t\tvDevIdNI = nodeId + separ + endpointId,\n\t\tvDevIdC = clusterId,\n\t\tvDevId = vDevIdPrefix + vDevIdNI + separ + vDevIdC,\n\t\tchangeDevId = vDevIdNI + separ + vDevIdC,\n\t\tdefaults;\n\t// vDev is not in this scope, but in {} scope for each type of device to allow reuse it without closures\n\n\ttry {\n\t\tif (!cc) {\n\t\t\treturn; // do not handle destroyed Cluster Classes\n\t\t}\n\n\t\tif (!cc.data.inDirection.value) {\n\t\t\treturn; // do not handle unsupported Cluster Classes\n\t\t}\n\n\t\tif (this.CC[\"OnOff\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar icon = \"switch\";\n\t\t\tvar probeType = \"switch\";\n\n\t\t\t//TODO How to guess the icon type?\n\t\t\t/*\n\t\t\tswitch (this.zmatter.devices[nodeId].data.specificType.value) {\n\t\t\t\tcase 0x01:\n\t\t\t\t\tprobeType = \"power_switch_binary\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x03:\n\t\t\t\t\tprobeType = \"scene_switch_binary\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x04:\n\t\t\t\t\tprobeType = \"power_strip\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x05:\n\t\t\t\t\ticon = \"siren\";\n\t\t\t\t\tprobeType = \"siren\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x06:\n\t\t\t\t\ticon = \"valve\";\n\t\t\t\t\tprobeType = \"valve\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tprobeType = \"switch\";\n\t\t\t\t\tbreak;\n\t\t\t};\n\t\t\t*/\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Switch')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\tcc.Set(true);\n\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\tcc.Set(false);\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', this.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tthis.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"onOff\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"LevelControl\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar icon = 'multilevel';\n\t\t\tvar title = 'Dimmer';\n\t\t\tvar probeType = 'multilevel';\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, title)) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Blinds\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = Math.round(parseInt(args.level, 10) * 255 / 99, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal > 255) {\n\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tcc.StepOnOff(0, 10);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tcc.StepOnOff(1, 10);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"stop\" === command) { // Commands for Blinds\n\t\t\t\t\t\tcc.StopOnOff();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\tcc.MoveOnOff(0);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\tcc.MoveOnOff(1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.MoveToLevelOnOff(newVal, args.duration);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.MoveToLevelOnOff(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"currentLevel\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", Math.round(this.value * 99 / 255, 10));\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"ColorControl\"] === clusterId) {\n\t\t\tvar\n\t\t\t\t// TODO COLOR_SOFT_WHITE = 0,\n\t\t\t\t// TODO COLOR_COLD_WHITE = 1,\n\t\t\t\tCOLOR_RED = 2,\n\t\t\t\tCOLOR_GREEN = 3,\n\t\t\t\tCOLOR_BLUE = 4;\n\n\t\t\tvar ccLevelControl = endpoint.clusters[this.CC[\"LevelControl\"]];\n\t\t\tif (!ccLevelControl) return;\n\n\t\t\tif (!self.controller.devices.get(vDevId + separ + \"rgb\")) {\n\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: \"switchRGBW\",\n\t\t\t\t\tprobeType: 'switchColor_rgb',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\tcolor: HSVtoRGB(\n\t\t\t\t\t\t\tcc.data.currentHue.value,\n\t\t\t\t\t\t\tcc.data.currentSaturation.value,\n\t\t\t\t\t\t\tccLevelControl.data.currentLevel.value\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlevel: 'off',\n\t\t\t\t\t\toldColor: {},\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Color')) return;\n\n\t\t\t\tvar vDev_rgb = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId + separ + \"rgb\",\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\tvar color = {\n\t\t\t\t\t\t\t\tr: 0,\n\t\t\t\t\t\t\t\tg: 0,\n\t\t\t\t\t\t\t\tb: 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toldColor = vDev_rgb.get('metrics:oldColor');\n\t\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\t\tif (!_.isEmpty(oldColor)) {\n\t\t\t\t\t\t\t\tcolor = oldColor;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcolor.r = color.g = color.b = 255;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (command === \"off\") {\n\t\t\t\t\t\t\tcolor.r = color.g = color.b = 0;\n\t\t\t\t\t\t} else if (command === \"exact\") {\n\t\t\t\t\t\t\tcolor.r = parseInt(args.red, 10);\n\t\t\t\t\t\t\tcolor.g = parseInt(args.green, 10);\n\t\t\t\t\t\t\tcolor.b = parseInt(args.blue, 10);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:oldColor\", color);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar hsv = RGBtoHSV(color.r, color.g, color.b);\n\t\t\t\t\t\t\n\t\t\t\t\t\tconsole.logJS(hsv);\n\t\t\t\t\t\tcc.MoveToHueAndSaturation(hsv.h, hsv.s, 0);\n\t\t\t\t\t\tccLevelControl.MoveToLevel(hsv.v);\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: this.id\n\t\t\t\t});\n\n\t\t\t\tfunction HSVtoRGB(h, s, v) {\n\t\t\t\t\tvar r, g, b, i, f, p, q, t;\n\t\t\t\t\t\n\t\t\t\t\th = h / 255.0;\n\t\t\t\t\ts = s / 255.0;\n\t\t\t\t\tv = v / 255.0;\n\t\t\t\t\t\n\t\t\t\t\ti = Math.floor(h * 6);\n\t\t\t\t\tf = h * 6 - i;\n\t\t\t\t\tp = v * (1 - s);\n\t\t\t\t\tq = v * (1 - f * s);\n\t\t\t\t\tt = v * (1 - (1 - f) * s);\n\t\t\t\t\t\n\t\t\t\t\tswitch (i % 6) {\n\t\t\t\t\t\tcase 0: r = v, g = t, b = p; break;\n\t\t\t\t\t\tcase 1: r = q, g = v, b = p; break;\n\t\t\t\t\t\tcase 2: r = p, g = v, b = t; break;\n\t\t\t\t\t\tcase 3: r = p, g = q, b = v; break;\n\t\t\t\t\t\tcase 4: r = t, g = p, b = v; break;\n\t\t\t\t\t\tcase 5: r = v, g = p, b = q; break;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn {\n\t\t\t\t\t\tr: Math.round(r * 255),\n\t\t\t\t\t\tg: Math.round(g * 255),\n\t\t\t\t\t\tb: Math.round(b * 255)\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfunction RGBtoHSV(r, g, b) {\n\t\t\t\t\tvar max = Math.max(r, g, b), min = Math.min(r, g, b),\n\t\t\t\t\t\td = max - min,\n\t\t\t\t\t\th,\n\t\t\t\t\t\ts = (max === 0 ? 0 : d / max),\n\t\t\t\t\t\tv = max / 255;\n\t\t\t\t\t\n\t\t\t\t\tswitch (max) {\n\t\t\t\t\t\tcase min: h = 0; break;\n\t\t\t\t\t\tcase r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;\n\t\t\t\t\t\tcase g: h = (b - r) + d * 2; h /= 6 * d; break;\n\t\t\t\t\t\tcase b: h = (r - g) + d * 4; h /= 6 * d; break;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn {\n\t\t\t\t\t\th: Math.round(h * 255),\n\t\t\t\t\t\ts: Math.round(s * 255),\n\t\t\t\t\t\tv: Math.round(v * 255)\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfunction handleColor(type, arg) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar isOn = ccLevelControl.data.currentLevel.value > 0;\n\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + 'rgb');\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvar color = HSVtoRGB(\n\t\t\t\t\t\t\t\tcc.data.currentHue.value,\n\t\t\t\t\t\t\t\tcc.data.currentSaturation.value,\n\t\t\t\t\t\t\t\tccLevelControl.data.currentLevel.value\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:color\", color);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:level\", isOn ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.log(e.toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (vDev_rgb) {\n\t\t\t\t\tvDev_rgb.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"currentHue\", handleColor, \"value\");\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"currentSaturation\", handleColor, \"value\");\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, this.CC[\"LevelControl\"], \"currentLevel\", handleColor, \"value\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"WindowCovering\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\t\t\t// Lift\n\t\t\t\n\t\t\tvar icon = 'blinds';\n\t\t\tvar title = 'Blind';\n\t\t\tprobeType = 'motor';\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, title)) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Blinds\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"stop\" === command) { // Commands for Blinds\n\t\t\t\t\t\tcc.Stop();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\tcc.UpOpen();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\tcc.DownClose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.GoToLiftPercentage(newVal); // no exactSmooth for WindowCovering\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.GoToLiftPercentage(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"currentPositionLiftPercentage\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t\t\n\t\t\t// Tilt\n\t\t\t\n\t\t\tvar icon = 'blinds';\n\t\t\tvar title = 'Tilt';\n\t\t\tprobeType = 'motor';\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId + separ + \"tilt\"], nodeId, endpointId, title)) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId + separ + \"tilt\",\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Tilt\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"stop\" === command) { // Ignore Blind Commands for Tilt\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.GoToTiltPercentage(newVal); // no exactSmooth for WindowCovering\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.GoToTiltPercentage(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"currentPositionTiltPercentage\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} /* else if (this.CC[\"SoundSwitch\"] === clusterId) {\n\t\t\tif (cc.data) {\n\t\t\t\t// tones\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'scene',\n\t\t\t\t\t\tlevel: 'on',\n\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tfor(var toneId = 0; toneId <= cc.data.tonesNumber.value; toneId++) {\n\t\t\t\t\t(function(toneId) {\n\t\t\t\t\t\tif ((toneId == 0 || cc.data[toneId]) && !self.controller.devices.get(vDevId + separ + toneId)) {\n\t\t\t\t\t\t\tvar cVDId = changeDevId + separ + toneId;\n\n\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, toneId ? cc.data[toneId].toneName.value : 'Mute')) return;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\tdeviceId: vDevId + separ + toneId,\n\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\t\t\t\t\tcc.TonePlaySet(toneId);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, toneId + \".toneName\", function(type) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + toneId);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"tonesNumber\", function(type) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + \"0\");\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})(toneId);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.controller.devices.get(vDevId)) {\n\t\t\t\t\t// volume\n\t\t\t\t\tdefaults = {\n\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\tprobeType: 'volume',\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Volume')) return;\n\n\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t\t\t} else if (\"max\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (newVal > 99) {\n\t\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"exact\" === command) {\n\t\t\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t} else if (newVal === 255) {\n\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t} else if (newVal > 99) {\n\t\t\t\t\t\t\t\t\tif (newVal === 100) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewVal = null;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\t\t\tcc.ConfigurationGet();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\t\t\tcc.ConfigurationSet(0, newVal);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"defaultVolume\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"SensorBinary\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\ticon: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(vDevId + separ + sensorTypeId)) {\n\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[sensorTypeId].sensorTypeString.value;\n\t\t\t\t\t\t// aivs // Motion icon for Sensor Binary by default\n\t\t\t\t\t\tdefaults.metrics.icon = \"motion\";\n\t\t\t\t\t\tdefaults.probeType = \"general_purpose\";\n\n\t\t\t\t\t\tif (sensorTypeId === 2) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"smoke\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 3 || sensorTypeId === 4) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 6) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"flood\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 7) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"cooling\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 8) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"tamper\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 10) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"door\";\n\t\t\t\t\t\t\tdefaults.probeType = \"door-window\";\n\t\t\t\t\t\t} else if (sensorTypeId === 12) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"motion\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + sensorTypeId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tif (changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\tvDev.__emulateOff_timeout = parseInt(changeVDev[cVDId].emulateOff, 10);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, sensorTypeId + \".level\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\t\tif (vDev.__emulateOff_timeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (this.value) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (vDev.get(\"metrics:level\") !== \"on\" || !vDev.__emulateOff_timer) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer && clearTimeout(vDev.__emulateOff_timer);\n\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer = 0;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}, vDev.__emulateOff_timeout);\n\t\t\t\t\t\t\t\t\t\t\t\t} // off from the sensor is ignored\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\n\t\t\t\t\t\t\tif (changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\t// on start we need to kick the timer\n\t\t\t\t\t\t\t\tif (vDev.get(\"metrics:level\") === \"on\") {\n\t\t\t\t\t\t\t\t\tself.zmatter.devices[nodeId].endpoints[endpointId].clusters[clusterId].data[sensorTypeId].level.value = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"SensorMultilevel\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(vDevId + separ + sensorTypeId)) {\n\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[sensorTypeId].sensorTypeString.value;\n\t\t\t\t\t\tdefaults.metrics.scaleTitle = cc.data[sensorTypeId].scaleString.value;\n\n\t\t\t\t\t\tif (sensorTypeId === 1) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"temperature\";\n\t\t\t\t\t\t} else if (sensorTypeId === 3) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"luminosity\";\n\t\t\t\t\t\t} else if (sensorTypeId === 4 || sensorTypeId === 15 || sensorTypeId === 16) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"energy\";\n\t\t\t\t\t\t} else if (sensorTypeId === 5) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"humidity\";\n\t\t\t\t\t\t} else if (sensorTypeId === 9) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"barometer\";\n\t\t\t\t\t\t} else if (sensorTypeId === 12) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"rain\";\n\t\t\t\t\t\t} else if (sensorTypeId === 17) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co2\";\n\t\t\t\t\t\t} else if (sensorTypeId === 25) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"seismic\";\n\t\t\t\t\t\t} else if (sensorTypeId === 27) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"ultraviolet\";\n\t\t\t\t\t\t} else if (sensorTypeId === 40) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co\";\n\t\t\t\t\t\t} else if (sensorTypeId === 52) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_x\";\n\t\t\t\t\t\t} else if (sensorTypeId === 53) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_y\";\n\t\t\t\t\t\t} else if (sensorTypeId === 54) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_z\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + sensorTypeId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, sensorTypeId + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"Meter\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorMultilevel',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'meter',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(scaleId) {\n\n\t\t\t\t\tscaleId = parseInt(scaleId, 10);\n\t\t\t\t\tif (!isNaN(scaleId) && !self.controller.devices.get(vDevId + separ + scaleId)) {\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + scaleId;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[scaleId].sensorTypeString.value;\n\t\t\t\t\t\tdefaults.metrics.scaleTitle = cc.data[scaleId].scaleString.value;\n\n\t\t\t\t\t\t// Check sensor type, can be: Electric, Gas, Water\n\t\t\t\t\t\tswitch (cc.data[scaleId].sensorType.value) {\n\t\t\t\t\t\t\t// Electric meter\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tswitch (scaleId) {\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_kilowatt_hour';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_kilovolt_ampere_hour';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_watt';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_pulse_count';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_voltage';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_ampere';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_power_factor';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t// Gas meter\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tswitch (scaleId) {\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterGas_cubic_meters';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterGas_cubic_feet';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterGas_pulse_count';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t// Water meter\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tswitch (scaleId) {\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_cubic_meters';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_cubic_feet';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_us_gallons';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_pulse_count';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Meter', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + scaleId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(scaleId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, scaleId + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + scaleId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"MeterPulse\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorMultilevel',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'meterElectric_pulse_count',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'meter',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.controller.devices.get(vDevId)) {\n\t\t\t\tvar cVDId = changeDevId;\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Meter Pulse')) return;\n\n\t\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"val\", function(type) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}, \"value\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"Battery\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'battery',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'Battery',\n\t\t\t\t\tscaleTitle: '%',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'battery',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Battery')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"last\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? 0 : this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}*/ else if (this.CC[\"DoorLock\"] === clusterId) {\n\t\t\tdefaults_lock = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tdefaults_door = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\ttitle: 'Door State',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tvar lockType = cc.data.lockType.value;\n\n\t\t\tswitch (lockType) {\n\t\t\t\tcase 0x00:\n\t\t\t\t\ttitle = \"Dead bolt\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x01:\n\t\t\t\t\ttitle = \"Magnetic\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x02:\n\t\t\t\t\ttitle = \"Other\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x03:\n\t\t\t\t\ttitle = \"Mortise\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x04:\n\t\t\t\t\ttitle = \"Rim\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x05:\n\t\t\t\t\ttitle = \"Latch Bolt\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x06:\n\t\t\t\t\ttitle = \"Cylindrical Lock\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x07:\n\t\t\t\t\ttitle = \"Tubular Lock\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x08:\n\t\t\t\t\ttitle = \"Interconnected\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x09:\n\t\t\t\t\ttitle = \"Dead Latch\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x0A:\n\t\t\t\t\ttitle = \"Door Furniture\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\ttitle = \"Door Lock\"\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!this.applyPostfix(defaults_lock, changeVDev[changeDevId], nodeId, endpointId, 'Door Lock', title)) return;\n\t\t\tif (!this.applyPostfix(defaults_door, changeVDev[changeDevId], nodeId, endpointId, 'Door Lock')) return;\n\n\t\t\tif (cc.data.lockState) {\n\t\t\t\tvar vDev_lock = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId + separ + \"lock\",\n\t\t\t\t\tdefaults: defaults_lock,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\t\tcc.LockDoor(\"\");\n\t\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\t\tcc.UnlockDoor(\"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (cc.data.doorState) {\n\t\t\t\t\tvar vDev_door = this.controller.devices.create({\n\t\t\t\t\t\tdeviceId: vDevId + separ + \"door\",\n\t\t\t\t\t\tdefaults: defaults_door,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\t\t\tcc.LockDoor(\"\");\n\t\t\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\t\t\tcc.UnlockDoor(\"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (vDev_door && vDev_lock) {\n\t\t\t\t\t\tvDev_door.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"doorState\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tswitch (this.value) {\n\t\t\t\t\t\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\t\t\t\t\t\tvDev_door.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tvDev_door.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  ERROR JAMMED)\n\t\t\t\t\t\t\t\t\t\t\t//vDev.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x03:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  ERROR FORCED OPENED)\n\t\t\t\t\t\t\t\t\t\t\tvDev_door.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x04:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  ERROR UNSPECIFIED)\n\t\t\t\t\t\t\t\t\t\t\t//vDev.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  UNDEFINED)\n\t\t\t\t\t\t\t\t\t\t\t//vDev.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"lockState\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tswitch (this.value) {\n\t\t\t\t\t\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Not fully locked\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Undefined lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t// TODO self.addNotification(\"error\", \"Unknown lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif (vDev_lock) {\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"lockState\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tswitch (this.value) {\n\t\t\t\t\t\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Not fully locked\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Undefined lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t// TODO self.addNotification(\"error\", \"Unknown lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} /*else if (this.CC[\"BarrierOperator\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Garage Door')) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\tcc.Set(255);\n\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\tcc.Set(0);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"state\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? \"open\" : \"close\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"ThermostatMode\"] === clusterId || this.CC[\"ThermostatSetPoint\"] === clusterId) {\n\t\t\tvar\n\t\t\t\twithMode = in_array(endpointClusterClasses, this.CC[\"ThermostatMode\"]) && endpoint.ThermostatMode.data.supported.value,\n\t\t\t\twithTemp = in_array(endpointClusterClasses, this.CC[\"ThermostatSetPoint\"]) && endpoint.ThermostatSetPoint.data.supported.value,\n\t\t\t\tdeviceNamePrefix = \"ZMatterVDev_\" + this.config.name + \"_\" + nodeId + separ + endpointId + separ;\n\n\t\t\tif ((withMode && !endpoint.ThermostatMode.data.interviewDone.value) || (withTemp && !endpoint.ThermostatSetPoint.data.interviewDone.value)) {\n\t\t\t\treturn; // skip not finished interview\n\t\t\t}\n\n\t\t\tvar MODE_OFF = 0,\n\t\t\t\tMODE_HEAT = 1,\n\t\t\t\tMODE_COOL = 2;\n\n\t\t\t// Handle Mode with proper changeVDev\n\t\t\tif (withMode && !self.controller.devices.get(deviceNamePrefix + this.CC[\"ThermostatMode\"])) {\n\t\t\t\tvar withModeOff = !!endpoint.ThermostatMode.data[MODE_OFF],\n\t\t\t\t\twithModeHeat = !!endpoint.ThermostatMode.data[MODE_HEAT],\n\t\t\t\t\twithModeCool = !!endpoint.ThermostatMode.data[MODE_COOL];\n\n\t\t\t\tif (withModeOff && (withModeHeat || withModeCool)) {\n\n\t\t\t\t\tdefaults = {\n\t\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\t\tprobeType: 'thermostat_mode',\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Thermostat operation')) return;\n\n\t\t\t\t\tvar m_vDev = this.controller.devices.create({\n\t\t\t\t\t\tdeviceId: deviceNamePrefix + this.CC[\"ThermostatMode\"],\n\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\t\tvar lastMode = withModeHeat ? MODE_HEAT : MODE_COOL;\n\n\t\t\t\t\t\t\t\t// modes are not always same in ThermostatSetPoint and in ThermostatMode, but here they are same\n\t\t\t\t\t\t\t\tif (withModeHeat && withModeCool && endpoint.ThermostatSetPoint && endpoint.ThermostatSetPoint.data[MODE_HEAT] && endpoint.ThermostatSetPoint.data[MODE_COOL]) {\n\t\t\t\t\t\t\t\t\tlastMode = endpoint.ThermostatSetPoint.data[MODE_HEAT].setVal.updateTime > endpoint.ThermostatSetPoint.data[MODE_COOL].setVal.updateTime ? MODE_HEAT : MODE_COOL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tendpoint.ThermostatMode.Set(lastMode);\n\t\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\t\tendpoint.ThermostatMode.Set(MODE_OFF);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (m_vDev) {\n\t\t\t\t\t\tm_vDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, this.CC[\"ThermostatMode\"], \"mode\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tm_vDev.set(\"metrics:level\", this.value != MODE_OFF ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle Set Point with proper changeVDev\n\t\t\tif (withTemp) {\n\t\t\t\tvar withTempHeat = endpoint.ThermostatSetPoint.data[MODE_HEAT],\n\t\t\t\t\twithTempCool = endpoint.ThermostatSetPoint.data[MODE_COOL],\n\t\t\t\t\tmodes = [];\n\n\t\t\t\twithTempHeat && modes.push(MODE_HEAT);\n\t\t\t\twithTempCool && modes.push(MODE_COOL);\n\n\t\t\t\tvar t_vDev = [];\n\t\t\t\tmodes.forEach(function(mode) {\n\t\t\t\t\tvar cVDId = changeDevId + separ + mode;\n\t\t\t\t\t\n\t\t\t\t\tvar DH = endpoint.ThermostatSetPoint.data[mode],\n\t\t\t\t\t\t_vDevId = deviceNamePrefix + self.CC[\"ThermostatSetPoint\"] + \"-\" + mode;\n\n\t\t\t\t\tif (!self.controller.devices.get(_vDevId)) {\n\n\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\tdeviceType: \"thermostat\",\n\t\t\t\t\t\t\tprobeType: 'thermostat_set_point',\n\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\tscaleTitle: DH.scaleString.value,\n\t\t\t\t\t\t\t\tlevel: DH.val.value,\n\t\t\t\t\t\t\t\tmin: DH.min && DH.min.value ? DH.min.value : (DH.scale.value === 0 ? 5 : 41),\n\t\t\t\t\t\t\t\tmax: DH.max && DH.max.value ? DH.max.value : (DH.scale.value === 0 ? 40 : 104),\n\t\t\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, \"Thermostat \" + (mode === MODE_HEAT ? \"Heat\" : \"Cool\"))) return;\n\n\t\t\t\t\t\tt_vDev[mode] = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: _vDevId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t\t// first set the setpoint temperature and then apply the mode\n\t\t\t\t\t\t\t\tif (command === \"exact\") {\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatSetPoint.Set(mode, args.level);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (command === \"on\" || command === \"exact\") {\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatMode && endpoint.ThermostatMode.data.supported.value && endpoint.ThermostatMode.Set(mode == MODE_HEAT ? MODE_HEAT : MODE_COOL); // modes are not always same in ThermostatSetPoint and in ThermostatMode, but here they are same\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatSetPoint.Get(mode);\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatMode && endpoint.ThermostatMode.data.supported.value && endpoint.ThermostatMode.Get();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (t_vDev[mode]) {\n\t\t\t\t\t\t\tt_vDev[mode].set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, self.CC[\"ThermostatSetPoint\"], mode + \".setVal\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tdelete t_vDev[mode];\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(_vDevId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tt_vDev[mode].set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t*/\n\t\telse if (this.CC[\"TemperatureMeasurement\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: \"temperature\",\n\t\t\t\t\tscaleTitle: 'C',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: \"temperature\",\n\t\t\t\t\ttitle: 'Temperature',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!self.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"measuredValue\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value / 100);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t\t\n\t\t}\n\t\telse if (this.CC[\"PressureMeasurement\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: \"barometer\",\n\t\t\t\t\tscaleTitle: 'kPa',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: \"barometer\",\n\t\t\t\t\ttitle: 'Barometer',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!self.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"measuredValue\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value / 10);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\telse if (this.CC[\"RelativeHumidityMeasurement\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: \"humidity\",\n\t\t\t\t\tscaleTitle: '%',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: \"humidity\",\n\t\t\t\t\ttitle: 'Relative Humidity',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!self.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"measuredValue\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\",  this.value / 100);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\telse if (this.CC[\"OccupancySensing\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\n\t\t\tvar title = \"Occupancy\";\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Alarm', title)) return;\n\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\t//TODO isFailed a_vDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"occupancy\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\telse if (this.CC[\"IasZone\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tvar zoneType = cc.data.zoneType.value;\n\t\t\tvar zoneStatus = cc.data.zoneStatus.value;\n\t\t\tvar title = \"\";\n\t\t\t\n\t\t\tswitch (zoneType) {\n\t\t\t\tcase 0x0000:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\tdefaults.probeType = 'general_purpose';\n\t\t\t\t\ttitle = \"\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x000d:\n\t\t\t\t\tdefaults.metrics.icon = 'motion';\n\t\t\t\t\tdefaults.probeType = 'motion';\n\t\t\t\t\ttitle = \"Motion\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x0028:\n\t\t\t\t\tdefaults.metrics.icon = 'smoke';\n\t\t\t\t\tdefaults.probeType = 'smoke';\n\t\t\t\t\ttitle = \"Smoke\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002b:\n\t\t\t\t\tdefaults.metrics.icon = 'co';\n\t\t\t\t\tdefaults.probeType = 'co';\n\t\t\t\t\ttitle = \"CO\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002a:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm_flood';\n\t\t\t\t\tdefaults.probeType = 'flood';\n\t\t\t\t\ttitle = \"Flood\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x0015:\n\t\t\t\t\tdefaults.metrics.icon = 'door';\n\t\t\t\t\tdefaults.probeType = 'door';\n\t\t\t\t\ttitle = \"Door\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002d:\n\t\t\t\tcase 0x0226:\n\t\t\t\t\tdefaults.metrics.icon = 'burglar';\n\t\t\t\t\tdefaults.probeType = 'burglar';\n\t\t\t\t\ttitle = \"Burglar\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002c:\n\t\t\t\tcase 0x0225:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\tdefaults.probeType = 'emergency';\n\t\t\t\t\ttitle = \"Emergency\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\tdefaults.probeType = 'general_purpose';\n\t\t\t\t\ttitle = \"\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Alarm', title)) return;\n\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\t//TODO isFailed a_vDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, \"zoneStatus\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", (this.value & 0x01) ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\t/*\n\t\telse if (this.CC[\"Configuration\"] === clusterId) {\n\t\t\tif (changeVDev[changeDevId]) {\n\t\t\t\tObject.keys(changeVDev[changeDevId]['configVDev']).forEach(function(param) {\n\t\t\t\t\tvar vDevIdParam = vDevId + '-' + param,\n\t\t\t\t\tvDevConfig = changeVDev[changeDevId]['configVDev'][param];\n\t\t\t\t\t\n\t\t\t\t\tif (!self.controller.devices.get(vDevIdParam)) {\n\t\t\t\t\t\tvar icon, probeType;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (vDevConfig.type == \"switchBinary\") {\n\t\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\t\t\t\tprobeType: \"switch\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: vDevConfig.title,\n\t\t\t\t\t\t\t\t\ticon: \"switch\",\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (vDevConfig.type == \"switchMultilevel\") {\n\t\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\t\t\tprobeType: \"multilevel\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: vDevConfig.title,\n\t\t\t\t\t\t\t\t\ticon: \"multilevel\",\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.addNotification(\"error\", \"Unknown vDev type for config parameter \" + param, \"module\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\teval('vDevConfig.v2p_script = function(command, args, vdev) { \"use strict\";' + vDevConfig.v2p + '};');\n\t\t\t\t\t\teval('vDevConfig.p2v_script = function(value) { \"use strict\";' + vDevConfig.p2v + '};');\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!cc.data[param] || !cc.data[param].size.value) { // make sure the size of the parameter is known, so Set works\n\t\t\t\t\t\t\tcc.Get(param);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevIdParam,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t\tif (\"update\" === command || !cc.data[param] || !cc.data[param].size.value) { // make sure the size of the parameter is known, so Set works\n\t\t\t\t\t\t\t\t\tcc.Get(param);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvar val = vDevConfig.v2p_script(command, args, vDev);\n\t\t\t\t\t\t\t\t\tif (val !== null && val !== undefined) {\n\t\t\t\t\t\t\t\t\t\tcc.Set(param, val);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zmatter.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zmatter, nodeId, endpointId, clusterId, param + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevIdParam);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", vDevConfig.p2v_script(this.value));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t*/\n\t} catch (e) {\n\t\tvar langFile = this.loadModuleLang(),\n\t\t\tvalues = nodeId + \"-\" + endpointId + \"-\" + clusterId + \": \" + e.toString();\n\n\t\tthis.addNotification(\"error\", langFile.err_dev_create + values, \"core\");\n\t\tconsole.log(e.stack);\n\t}\n};\n\nZMatter.prototype.parseDelClusterClass = function(nodeId, endpointId, clusterId) {\n\tnodeId = parseInt(nodeId, 10);\n\tendpointId = parseInt(endpointId, 10);\n\tclusterId = parseInt(clusterId, 10);\n\n\tvar self = this,\n\t\tsepar = \"-\",\n\t\tvDevIdPrefix = \"ZMatterVDev_\" + this.config.name + \"_\",\n\t\tvDevIdNI = nodeId + separ + endpointId,\n\t\tvDevIdC = clusterId,\n\t\tvDevId = vDevIdPrefix + vDevIdNI + separ + vDevIdC;\n\n\tthis.controller.devices.remove(vDevId);\n};\n\nZMatter.prototype.nodeNameByType = function (nodeId, nodeData) {\n\n\tvar name = 'Device ' + nodeId,\n\t\ttype = '',\n\t\tnode = nodeData;\n\n\tif (node){\n\t\tvar isSleepy = false; // TODO wait for isSleepy to be moved on device // node.isSleepy.value;\n\n\t\tif (isSleepy) {\n\t\t\ttype = 'Battery';\n\t\t} else {\n\t\t\ttype = 'Mains';\n\t\t}\n\t\tname = type + name;\n\t}\n\n\treturn name;\n};\n"
  },
  {
    "path": "modules/ZMatter/lang/de.json",
    "content": "{\n\t\"m_title\":\"ZMatter Netzwerksteuerung\",\n\t\"m_descr\":\"Diese App bildet die Information zu Ihrem ZMatter Netzwerk in Ihrer UI ab. Infolgedessen muss dieses während der ganzen Zeit aktiviert sein, in welcher Sie mit dem ZMatter Geräte arbeiten wollen. In der Verwendung mit diesem Modul kann sehr viel falsch gemacht werden, daher lassen Sie es unberührt, solange es nicht wirklich benötigt wird.\",\n\t\"l_port\":\"Serieller Port der verwendet werden soll:\",\n\t\"h_port\":\"Example: SR:/dev/ttyUSB1 or SR:/dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012082E1-if01-port0\",\n\t\"l_name\":\"Interner Name\",\n\t\"h_name\":\"Dies sollte ein valider JS key String sein. Achtung! Nur ändern, wenn Sie wissen was Sie tun.\",\n\t\"l_wifiEssid\": \"Wi-Fi network name\",\n\t\"h_wifiEssid\": \"Used to commission Matter over Wi-Fi devices\",\n\t\"l_wifiPassword\": \"Wi-Fi password\",\n\t\"h_wifiPassword\": \"Used to commission Matter over Wi-Fi devices\",\n\t\"l_threadCredential\": \"Thread credentials (also known as Thread Operational Dataset)\",\n\t\"h_threadCredential\": \"Used to commission Matter over Thread devices. Find it in settings of your existing Thread Border Gateway. For example, 0e08000000000001000035060004001fffe00708fde2e24908729d7a0c0402a0f7f8051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f0410445f2b5ca6f2a93a55ce570a70efeecb000300000f0208111111112222222201021234 (without quotes and 0x prefix)\",\n\t\"rl_enableAPI\":\"Aktiviere ZMatter API\",\n\t\"h_enableAPI\":\"Erlaubt HTTP anfragen zu /ZMatterAPI/* and /ZMatter/&lt;internal zway name&gt;/*\",\n\t\"rl_publicAPI\":\"Aktiviere öffentlichen Zugang zur ZMatter API\",\n\t\"h_publicAPI\":\"Keine authentifiziereung zur ZMatter API notwendig.\",\n\t\"rl_createVDev\":\"Erzeuge virtuelle Geräte in der Home Automation Engine\",\n\t\"h_createVDev\":\"Wenn diese Einstellung nicht aktiv ist, sind ZMatter Geräte nur in der Expert UI und über die ZMatter API sicht- bzw. benutzbar.\",\n\t\"l_config\":\"Pfad zum Ordner /config\",\n\t\"l_paa_folder\":\"Pfad zum PAA\",\n\t\"l_cd_folder\":\"Pfad zur CD\",\n\t\"err_binding_start\":\"Fehler beim Starten der ZMatter Bindung: \",\n\t\"err_connct\":\"Verbindung verloren zur ZMatter Geräte-ID: \",\n\t\"err_reset\": \"Benutzer zurückgesetzt ZMatter-Gerät ID: \",\n\t\"dev_btl\":\"ZMatter Geräte-ID ist wieder verbunden: \",\n\t\"err_dev_create\":\"vDev konnte mit den folgenden Daten nicht erstellt werden: \",\n\t\"main\":\"strombetriebenen Geräte\",\n\t\"battery\":\"batteriebetriebenen Geräte\"\n}"
  },
  {
    "path": "modules/ZMatter/lang/en.json",
    "content": "{\n\t\"m_title\":\"ZMatter Network Access\",\n\t\"m_descr\":\"Z-Way controls one ZMatter network with up to 232 devices. This app will combine multiple Z-Way entities into one User Interface. Essentially the app is mapping the data of another Z-Way powered Gateway into your gateway. The elements are displayed and can be used like the local ones. Please note that the function of the second gateway remains untouched. This means that this second gateway will not see the elements for your first gateway but can control and access their own elements without and further restrictions: <br><br> Settings: <br><ul><li>You need to set the IP address of the Remote Box including the port number. </li><li>You need to define the polling interval. Once second in a quite good choice.</li> <li>You need to manage the remove device to be included into you UI.</li></ul>\",\n\t\"l_port\":\"Serial port to ZMatter dongle\",\n\t\"h_port\":\"Example: SR:/dev/ttyUSB1 or SR:/dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012082E1-if01-port0\",\n\t\"l_name\":\"Internal name\",\n\t\"h_name\":\"Should be a valid JS key string. Don't change unless you know what you are doing\",\n\t\"l_wifiEssid\": \"Wi-Fi network name\",\n\t\"h_wifiEssid\": \"Used to commission Matter over Wi-Fi devices\",\n\t\"l_wifiPassword\": \"Wi-Fi password\",\n\t\"h_wifiPassword\": \"Used to commission Matter over Wi-Fi devices\",\n\t\"l_threadCredential\": \"Thread credentials (also known as Thread Operational Dataset)\",\n\t\"h_threadCredential\": \"Used to commission Matter over Thread devices. Find it in settings of your existing Thread Border Gateway. For example, 0e08000000000001000035060004001fffe00708fde2e24908729d7a0c0402a0f7f8051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f0410445f2b5ca6f2a93a55ce570a70efeecb000300000f0208111111112222222201021234 (without quotes and 0x prefix)\",\n\t\"rl_enableAPI\":\"Enable ZMatter API\",\n\t\"h_enableAPI\":\"Handler HTTP requests to /ZMatterAPI/* and /ZMatter/&lt;internal zway name&gt;/*\",\n\t\"rl_publicAPI\":\"Allow public access to ZMatter API\",\n\t\"h_publicAPI\":\"Do not ask for authentication to access ZMatter API\",\n\t\"rl_createVDev\":\"Create virtual devices in Home Automation engine\",\n\t\"h_createVDev\":\"Without this ZMatter devices will be visible only in Expert UI and via ZMatter API\",\n\t\"l_config\":\"Path to config folder\",\n\t\"l_paa_folder\":\"Path to PAA folder\",\n\t\"l_cd_folder\":\"Path to CD folder\",\n\t\"err_binding_start\":\"Cannot start ZMatter binding: \",\n\t\"err_connct\":\"Connection lost to ZMatter device ID: \",\n\t\"err_reset\": \"User reset to factory defaults ZMatter device ID: \",\n\t\"dev_btl\":\"ZMatter device ID is back to life: \",\n\t\"err_dev_create\":\"Cannot create vDev based on: \",\n\t\"main\":\"main powered devices\",\n\t\"battery\":\"battery powered devices\"\n}"
  },
  {
    "path": "modules/ZMatter/lang/ru.json",
    "content": "{\n\t\"m_title\":\"ZMatter движок\",\n\t\"m_descr\":\"Активация ZMatter движка.\",\n\t\"l_port\":\"Порт для ZMatter платы/стика\",\n\t\"h_port\":\"Пример: SR:/dev/ttyUSB1 или SR:/dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012082E1-if01-port0\",\n\t\"l_name\":\"Внутреннее имя\",\n\t\"h_name\":\"Должно быть допустимой JS строкой. Не изменяйте, если не знаете, что делаете\",\n\t\"l_wifiEssid\": \"Имя Wi-Fi сети\",\n\t\"h_wifiEssid\": \"Используется для добавления устройств Matter по Wi-Fi\",\n\t\"l_wifiPassword\": \"Пароль Wi-Fi сети\",\n\t\"h_wifiPassword\": \"Используется для добавления устройств Matter по Wi-Fi\",\n\t\"l_threadCredential\": \"Ключ Thread (также известный как Thread Operational Dataset)\",\n\t\"h_threadCredential\": \"Используется для добавления устройств Matter по Thread. Найдите ключ в настройках вашего Thread Border Gateway. Например, 0e08000000000001000035060004001fffe00708fde2e24908729d7a0c0402a0f7f8051000112233445566778899aabbccddeeff030e4f70656e54687265616444656d6f0410445f2b5ca6f2a93a55ce570a70efeecb000300000f0208111111112222222201021234 (без кавычек и префикса 0x)\",\n\t\"rl_enableAPI\":\"Включить ZMatter API\",\n\t\"h_enableAPI\":\"Обрабатывать HTTP запросы /ZMatterAPI/* и /ZMatter/&lt;внутреннее имя zway&gt;/*\",\n\t\"rl_publicAPI\":\"Разрешить доступ к ZMatter API без аутентификации\",\n\t\"h_publicAPI\":\"Не требовать аутентификации при обработке запросов к ZMatter API\",\n\t\"rl_createVDev\":\"Создавать виртуальные устройства домашней автоматизации\",\n\t\"h_createVDev\":\"Если отключить, то ZMatter устройства будут видны только в Экспертном интерфейсе и через ZMatter API\",\n\t\"l_config\":\"Путь к папке с настройками config/\",\n\t\"l_paa_folder\":\"Путь к папке с PAA\",\n\t\"l_cd_folder\":\"Путь к папке с CD\",\n\t\"err_binding_start\":\"Невозможно запустить ZMatter движок: \",\n\t\"err_connct\":\"Соединение потеряно с ZMatter устройством ID: \",\n\t\"err_reset\": \"Пользователь сбросил к заводским настройкам устройство ID: \",\n\t\"dev_btl\":\"ZMatter устройство ID снова доступно: \",\n\t\"err_dev_create\":\"Не возможно создать vDev основанное на: \",\n\t\"main\":\"main powered devices\",\n\t\"battery\":\"battery powered devices\"\n}"
  },
  {
    "path": "modules/ZMatter/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"peripherals\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://z-wave.me\",\n\t\"icon\": \"icon.svg\",\n\t\"moduleName\":\"ZMatter\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"name\": \"zmatter\",\n\t\t\"port\": \"SR:/dev/ttyUSB1\",\n\t\t\"wifiEssid\": \"\",\n\t\t\"wifiPassword\": \"\",\n\t\t\"threadCredential\": \"\",\n\t\t\"enableAPI\": true,\n\t\t\"publicAPI\": false,\n\t\t\"createVDev\": true,\n\t\t\"config\": \"config\",\n\t\t\"bleOverDHorWS\": true,\n\t\t\"paaFolder\": \"config/paa-root-certs\",\n\t\t\"cdFolder\": null\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"port\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"wifiEssid\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"\"\n\t\t\t},\n\t\t\t\"wifiPassword\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"\"\n\t\t\t},\n\t\t\t\"threadCredential\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"default\": \"\"\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"bleOverDHorWS\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"paaFolder\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"cdFolder\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"port\": {\n\t\t\t\t\"label\": \"__l_port__\",\n\t\t\t\t\"helper\": \"__h_port__\"\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"label\": \"__l_name__\",\n\t\t\t\t\"helper\": \"__h_name__\"\n\t\t\t},\n\t\t\t\"wifiEssid\": {\n\t\t\t\t\"label\": \"__l_wifiEssid__\",\n\t\t\t\t\"helper\": \"__h_wifiEssid__\"\n\t\t\t},\n\t\t\t\"wifiPassword\": {\n\t\t\t\t\"label\": \"__l_wifiPassword__\",\n\t\t\t\t\"helper\": \"__h_wifiPassword__\"\n\t\t\t},\n\t\t\t\"threadCredential\": {\n\t\t\t\t\"label\": \"__l_threadCredential__\",\n\t\t\t\t\"helper\": \"__h_threadCredential__\"\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_enableAPI__\",\n\t\t\t\t\"helper\": \"__h_enableAPI__\"\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_publicAPI__\",\n\t\t\t\t\"helper\": \"__h_publicAPI__\"\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_createVDev__\",\n\t\t\t\t\"helper\": \"__h_createVDev__\"\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_config__\",\n\t\t\t\t\"helper\": \"__h_config__\"\n\t\t\t},\n\t\t\t\"bleOverDHorWS\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_bleOverDHorWS__\",\n\t\t\t\t\"helper\": \"__h_bleOverDHorWS__\"\n\t\t\t},\n\t\t\t\"paaFolder\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_paa_folder__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t},\n\t\t\t\"cdFolder\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_cd_folder__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/ZWave/cmd_classes.json",
    "content": "{\"zw_classes\":{\"bas_dev\":[{\"_read_only\":\"false\",\"_name\":\"BASIC_TYPE_CONTROLLER\",\"_key\":\"0x01\",\"_help\":\"Controller\",\"_comment\":\"Node is a portable controller \"},{\"_read_only\":\"false\",\"_name\":\"BASIC_TYPE_ROUTING_SLAVE\",\"_key\":\"0x04\",\"_help\":\"Routing Slave\",\"_comment\":\"Node is a slave with routing capabilities\"},{\"_read_only\":\"false\",\"_name\":\"BASIC_TYPE_SLAVE\",\"_key\":\"0x03\",\"_help\":\"Slave\",\"_comment\":\"Node is a slave\"},{\"_read_only\":\"false\",\"_name\":\"BASIC_TYPE_STATIC_CONTROLLER\",\"_key\":\"0x02\",\"_help\":\"Static Controller\",\"_comment\":\"Node is a static controller\"}],\"gen_dev\":[{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x12\",\"_name\":\"SPECIFIC_TYPE_DOORBELL\",\"_help\":\"Doorbell\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_SATELLITE_RECEIVER\",\"_help\":\"Satellite Receiver\",\"_comment\":\"Satellite Receiver\"},{\"_key\":\"0x11\",\"_name\":\"SPECIFIC_TYPE_SATELLITE_RECEIVER_V2\",\"_help\":\"Satellite Receiver V2\",\"_comment\":\"Satellite Receiver V2\"}],\"_key\":\"0x03\",\"_name\":\"GENERIC_TYPE_AV_CONTROL_POINT\",\"_help\":\"Av Control Point\",\"_read_only\":\"false\",\"_comment\":\"AV Control Point\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_SIMPLE_DISPLAY\",\"_help\":\"Simple Display\",\"_comment\":\"Display (simple) Device Type\"}],\"_key\":\"0x04\",\"_name\":\"GENERIC_TYPE_DISPLAY\",\"_help\":\"Display\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_DOOR_LOCK\",\"_help\":\"Door Lock\",\"_comment\":\"Door Lock\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_ADVANCED_DOOR_LOCK\",\"_help\":\"Advanced Door Lock\",\"_comment\":\"Advanced Door Lock\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK\",\"_help\":\"Secure Keypad Door Lock\",\"_comment\":\"Door Lock (keypad –lever) Device Type\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK_DEADBOLT\",\"_help\":\"Door Lock Keypad Deadbolt\",\"_comment\":\"Door Lock (keypad – deadbolt) Device Type\"},{\"_key\":\"0x05\",\"_name\":\"SPECIFIC_TYPE_SECURE_DOOR\",\"_help\":\"Secure Door\",\"_comment\":\"Barrier Operator Specific Device Class\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_SECURE_GATE\",\"_help\":\"Secure Gate\",\"_comment\":\"Barrier Operator Specific Device Class\"},{\"_key\":\"0x07\",\"_name\":\"SPECIFIC_TYPE_SECURE_BARRIER_ADDON\",\"_help\":\"Secure Barrier Addon\",\"_comment\":\"Barrier Operator Specific Device Class\"},{\"_key\":\"0x08\",\"_name\":\"SPECIFIC_TYPE_SECURE_BARRIER_OPEN_ONLY\",\"_help\":\"Secure Barrier Open Only\",\"_comment\":\"Barrier Operator Specific Device Class\"},{\"_key\":\"0x09\",\"_name\":\"SPECIFIC_TYPE_SECURE_BARRIER_CLOSE_ONLY\",\"_help\":\"Secure Barrier Close Only\",\"_comment\":\"Barrier Operator Specific Device Class\"},{\"_key\":\"0x0A\",\"_name\":\"SPECIFIC_TYPE_SECURE_LOCKBOX\",\"_help\":\"Secure Lockbox\",\"_comment\":\"SDS12724\"},{\"_key\":\"0x0B\",\"_name\":\"SPECIFIC_TYPE_SECURE_KEYPAD\",\"_help\":\"Secure Keypad\"}],\"_key\":\"0x40\",\"_name\":\"GENERIC_TYPE_ENTRY_CONTROL\",\"_help\":\"Entry Control\",\"_read_only\":\"false\",\"_comment\":\"Entry Control\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_PORTABLE_REMOTE_CONTROLLER\",\"_help\":\"Portable Remote Controller\",\"_comment\":\"Remote Control (Multi Purpose) Device Type\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_PORTABLE_SCENE_CONTROLLER\",\"_help\":\"Portable Scene Controller\",\"_comment\":\"Portable Scene Controller\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_PORTABLE_INSTALLER_TOOL\",\"_help\":\"Portable Installer Tool\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_REMOTE_CONTROL_AV\",\"_help\":\"Remote Control AV\",\"_comment\":\"Remote Control (AV) Device Type\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_REMOTE_CONTROL_SIMPLE\",\"_help\":\"Remote Control Simple\",\"_comment\":\"Remote Control (Simple) Device Type\"}],\"_key\":\"0x01\",\"_name\":\"GENERIC_TYPE_GENERIC_CONTROLLER\",\"_help\":\"Generic Controller\",\"_read_only\":\"false\",\"_comment\":\"Remote Controller\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_SIMPLE_METER\",\"_help\":\"Simple Meter\",\"_comment\":\"Sub Energy Meter Device Type\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_ADV_ENERGY_CONTROL\",\"_help\":\"Adv Energy Control\",\"_comment\":\"Whole Home Energy Meter (Advanced) Device Type\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_WHOLE_HOME_METER_SIMPLE\",\"_help\":\"Whole Home Meter Simple\",\"_comment\":\"Whole Home Meter (Simple) Device Type\"}],\"_key\":\"0x31\",\"_name\":\"GENERIC_TYPE_METER\",\"_help\":\"Meter\",\"_read_only\":\"false\",\"_comment\":\"Meter\"},{\"spec_dev\":{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},\"_key\":\"0x30\",\"_name\":\"GENERIC_TYPE_METER_PULSE\",\"_help\":\"Meter Pulse\",\"_read_only\":\"false\",\"_comment\":\"Pulse Meter\"},{\"spec_dev\":{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},\"_key\":\"0xFF\",\"_name\":\"GENERIC_TYPE_NON_INTEROPERABLE\",\"_help\":\"Non Interoperable\",\"_read_only\":\"false\",\"_comment\":\"Non interoperable\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_REPEATER_SLAVE\",\"_help\":\"Repeater Slave\",\"_comment\":\"Basic Repeater Slave\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_VIRTUAL_NODE\",\"_help\":\"Virtual Node\",\"_comment\":\"\"}],\"_key\":\"0x0F\",\"_name\":\"GENERIC_TYPE_REPEATER_SLAVE\",\"_help\":\"Repeater Slave\",\"_read_only\":\"false\",\"_comment\":\"Repeater Slave\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_ZONED_SECURITY_PANEL\",\"_help\":\"Zoned Security Panel\",\"_comment\":\"\"}],\"_key\":\"0x17\",\"_name\":\"GENERIC_TYPE_SECURITY_PANEL\",\"_help\":\"Security Panel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_ENERGY_PRODUCTION\",\"_help\":\"Energy Production\",\"_comment\":\"Energy Production\"}],\"_key\":\"0x50\",\"_name\":\"GENERIC_TYPE_SEMI_INTEROPERABLE\",\"_help\":\"Semi Interoperable\",\"_read_only\":\"false\",\"_comment\":\"Semi Interoperable\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x05\",\"_name\":\"SPECIFIC_TYPE_ADV_ZENSOR_NET_ALARM_SENSOR\",\"_help\":\"Adv Zensor Net Alarm Sensor\",\"_comment\":\"\"},{\"_key\":\"0x0A\",\"_name\":\"SPECIFIC_TYPE_ADV_ZENSOR_NET_SMOKE_SENSOR\",\"_help\":\"Adv Zensor Net Smoke Sensor\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_BASIC_ROUTING_ALARM_SENSOR\",\"_help\":\"Basic Routing Alarm Sensor\",\"_comment\":\"\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_BASIC_ROUTING_SMOKE_SENSOR\",\"_help\":\"Basic Routing Smoke Sensor\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_BASIC_ZENSOR_NET_ALARM_SENSOR\",\"_help\":\"Basic Zensor Net Alarm Sensor\",\"_comment\":\"\"},{\"_key\":\"0x08\",\"_name\":\"SPECIFIC_TYPE_BASIC_ZENSOR_NET_SMOKE_SENSOR\",\"_help\":\"Basic Zensor Net Smoke Sensor\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_ROUTING_ALARM_SENSOR\",\"_help\":\"Routing Alarm Sensor\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"SPECIFIC_TYPE_ROUTING_SMOKE_SENSOR\",\"_help\":\"Routing Smoke Sensor\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_ZENSOR_NET_ALARM_SENSOR\",\"_help\":\"Zensor Net Alarm Sensor\",\"_comment\":\"\"},{\"_key\":\"0x09\",\"_name\":\"SPECIFIC_TYPE_ZENSOR_NET_SMOKE_SENSOR\",\"_help\":\"Zensor Net Smoke Sensor\",\"_comment\":\"\"},{\"_key\":\"0x0B\",\"_name\":\"SPECIFIC_TYPE_ALARM_SENSOR\",\"_help\":\"Alarm Sensor\",\"_comment\":\"Sensor (Alarm) Device Type\"}],\"_key\":\"0xA1\",\"_name\":\"GENERIC_TYPE_SENSOR_ALARM\",\"_help\":\"Sensor Alarm\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_ROUTING_SENSOR_BINARY\",\"_help\":\"Routing Sensor Binary\",\"_comment\":\"Routing Binary Sensor\"}],\"_key\":\"0x20\",\"_name\":\"GENERIC_TYPE_SENSOR_BINARY\",\"_help\":\"Sensor Binary\",\"_read_only\":\"false\",\"_comment\":\"Binary Sensor\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_ROUTING_SENSOR_MULTILEVEL\",\"_help\":\"Routing Sensor Multilevel\",\"_comment\":\"Sensor (Multilevel) Device Type\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_CHIMNEY_FAN\",\"_help\":\"Chimney Fan\",\"_comment\":\"\"}],\"_key\":\"0x21\",\"_name\":\"GENERIC_TYPE_SENSOR_MULTILEVEL\",\"_help\":\"Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"Multilevel Sensor\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_PC_CONTROLLER\",\"_help\":\"Pc Controller\",\"_comment\":\"Central Controller Device Type\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_SCENE_CONTROLLER\",\"_help\":\"Scene Controller\",\"_comment\":\"Scene Controller\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_STATIC_INSTALLER_TOOL\",\"_help\":\"Static Installer Tool\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_SET_TOP_BOX\",\"_help\":\"Set Top Box\",\"_comment\":\"Set Top Box Device Type\"},{\"_key\":\"0x05\",\"_name\":\"SPECIFIC_TYPE_SUB_SYSTEM_CONTROLLER\",\"_help\":\"Sub System Controller\",\"_comment\":\"Sub System Controller Device Type\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_TV\",\"_help\":\"TV\",\"_comment\":\"TV Device Type\"},{\"_key\":\"0x07\",\"_name\":\"SPECIFIC_TYPE_GATEWAY\",\"_help\":\"Gateway\",\"_comment\":\"Gateway Device Type\"}],\"_key\":\"0x02\",\"_name\":\"GENERIC_TYPE_STATIC_CONTROLLER\",\"_help\":\"Static Controller\",\"_read_only\":\"false\",\"_comment\":\"Static Controller\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_POWER_SWITCH_BINARY\",\"_help\":\"Power Switch Binary\",\"_comment\":\"On/Off Power Switch Device Type\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_SCENE_SWITCH_BINARY\",\"_help\":\"Scene Switch Binary\",\"_comment\":\"Binary Scene Switch\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_POWER_STRIP\",\"_help\":\"Power Strip\",\"_comment\":\"Power Strip Device Type\"},{\"_key\":\"0x05\",\"_name\":\"SPECIFIC_TYPE_SIREN\",\"_help\":\"Siren\",\"_comment\":\"Siren Device Type\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_VALVE_OPEN_CLOSE\",\"_help\":\"Valve Open/Close\",\"_comment\":\"Valve (open/close) Device Type\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_COLOR_TUNABLE_BINARY\",\"_help\":\"Binary Tunable Color Light\"},{\"_key\":\"0x07\",\"_name\":\"SPECIFIC_TYPE_IRRIGATION_CONTROLLER\",\"_help\":\"Irrigation Controller\"}],\"_key\":\"0x10\",\"_name\":\"GENERIC_TYPE_SWITCH_BINARY\",\"_help\":\"Switch Binary\",\"_read_only\":\"false\",\"_comment\":\"Binary Switch\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x05\",\"_name\":\"SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL\",\"_help\":\"Class A Motor Control\",\"_comment\":\"Window Covering No Position/Endpoint Device Type\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL\",\"_help\":\"Class B Motor Control\",\"_comment\":\"Window Covering Endpoint Aware Device Type\"},{\"_key\":\"0x07\",\"_name\":\"SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL\",\"_help\":\"Class C Motor Control\",\"_comment\":\"Window Covering Position/Endpoint Aware Device Type\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_MOTOR_MULTIPOSITION\",\"_help\":\"Motor Multiposition\",\"_comment\":\"Multiposition Motor\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL\",\"_help\":\"Power Switch Multilevel\",\"_comment\":\"Light Dimmer Switch Device Type\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL\",\"_help\":\"Scene Switch Multilevel\",\"_comment\":\"Multilevel Scene Switch\"},{\"_key\":\"0x08\",\"_name\":\"SPECIFIC_TYPE_FAN_SWITCH\",\"_help\":\"Fan Switch\",\"_comment\":\"Fan Switch Device Type\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_COLOR_TUNABLE_MULTILEVEL\",\"_help\":\"Multilevel Tunable Color Light\",\"_comment\":\"\"}],\"_key\":\"0x11\",\"_name\":\"GENERIC_TYPE_SWITCH_MULTILEVEL\",\"_help\":\"Switch Multilevel\",\"_read_only\":\"false\",\"_comment\":\"Multilevel Switch\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_SWITCH_REMOTE_BINARY\",\"_help\":\"Switch Remote Binary\",\"_comment\":\"Binary Remote Switch\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_SWITCH_REMOTE_MULTILEVEL\",\"_help\":\"Switch Remote Multilevel\",\"_comment\":\"Multilevel Remote Switch\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_SWITCH_REMOTE_TOGGLE_BINARY\",\"_help\":\"Switch Remote Toggle Binary\",\"_comment\":\"Binary Toggle Remote Switch\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_SWITCH_REMOTE_TOGGLE_MULTILEVEL\",\"_help\":\"Switch Remote Toggle Multilevel\",\"_comment\":\"Multilevel Toggle Remote Switch\"}],\"_key\":\"0x12\",\"_name\":\"GENERIC_TYPE_SWITCH_REMOTE\",\"_help\":\"Switch Remote\",\"_read_only\":\"false\",\"_comment\":\"Remote Switch\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_SWITCH_TOGGLE_BINARY\",\"_help\":\"Switch Toggle Binary\",\"_comment\":\"Binary Toggle Switch\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_SWITCH_TOGGLE_MULTILEVEL\",\"_help\":\"Switch Toggle Multilevel\",\"_comment\":\"Multilevel Toggle Switch\"}],\"_key\":\"0x13\",\"_name\":\"GENERIC_TYPE_SWITCH_TOGGLE\",\"_help\":\"Switch Toggle\",\"_read_only\":\"false\",\"_comment\":\"Toggle Switch\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_SETBACK_SCHEDULE_THERMOSTAT\",\"_help\":\"Setback Schedule Thermostat\",\"_comment\":\"Setback Schedule Thermostat\"},{\"_key\":\"0x05\",\"_name\":\"SPECIFIC_TYPE_SETBACK_THERMOSTAT\",\"_help\":\"Setback Thermostat\",\"_comment\":\"Thermostat (Setback) Device Type\"},{\"_key\":\"0x04\",\"_name\":\"SPECIFIC_TYPE_SETPOINT_THERMOSTAT\",\"_help\":\"Setpoint Thermostat\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_THERMOSTAT_GENERAL\",\"_help\":\"Thermostat General\",\"_comment\":\"Thermostat General\"},{\"_key\":\"0x06\",\"_name\":\"SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2\",\"_help\":\"Thermostat General V2\",\"_comment\":\"Thermostat (HVAC) Device Type\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_THERMOSTAT_HEATING\",\"_help\":\"Thermostat Heating\",\"_comment\":\"Thermostat Heating\"}],\"_key\":\"0x08\",\"_name\":\"GENERIC_TYPE_THERMOSTAT\",\"_help\":\"Thermostat\",\"_read_only\":\"false\",\"_comment\":\"Thermostat\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_RESIDENTIAL_HRV\",\"_help\":\"Residential Hrv\",\"_comment\":\"\"}],\"_key\":\"0x16\",\"_name\":\"GENERIC_TYPE_VENTILATION\",\"_help\":\"Ventilation\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_SIMPLE_WINDOW_COVERING\",\"_help\":\"Simple Window Covering\",\"_comment\":\"Simple Window Covering Control\"}],\"_key\":\"0x09\",\"_name\":\"GENERIC_TYPE_WINDOW_COVERING\",\"_help\":\"Window Covering\",\"_read_only\":\"false\",\"_comment\":\"Window Covering\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_ZIP_ADV_NODE\",\"_help\":\"Zip Adv Node\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_ZIP_TUN_NODE\",\"_help\":\"Zip Tun Node\",\"_comment\":\"\"}],\"_key\":\"0x15\",\"_name\":\"GENERIC_TYPE_ZIP_NODE\",\"_help\":\"Zip Node\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_BASIC_WALL_CONTROLLER\",\"_help\":\"Basic Wall Controller\",\"_comment\":\"Wall Controller Device Type\"}],\"_key\":\"0x18\",\"_name\":\"GENERIC_TYPE_WALL_CONTROLLER\",\"_help\":\"Wall Controller\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_SECURE_EXTENDER\",\"_help\":\"Secure Extender\",\"_comment\":\"Specific Device Secure Extender\"}],\"_key\":\"0x05\",\"_name\":\"GENERIC_TYPE_NETWORK_EXTENDER\",\"_help\":\"Network Extender\",\"_read_only\":\"false\",\"_comment\":\"Network Extender Generic Device Class\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class Not Used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_GENERAL_APPLIANCE\",\"_help\":\"General Appliance\"},{\"_key\":\"0x02\",\"_name\":\"SPECIFIC_TYPE_KITCHEN_APPLIANCE\",\"_help\":\"Kitchen Appliance\"},{\"_key\":\"0x03\",\"_name\":\"SPECIFIC_TYPE_LAUNDRY_APPLIANCE\",\"_help\":\"Laundry Appliance\"}],\"_key\":\"0x06\",\"_name\":\"GENERIC_TYPE_APPLIANCE\",\"_help\":\"Appliance\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"spec_dev\":[{\"_key\":\"0x00\",\"_name\":\"SPECIFIC_TYPE_NOT_USED\",\"_help\":\"Not Used\",\"_comment\":\"Specific Device Class not used\"},{\"_key\":\"0x01\",\"_name\":\"SPECIFIC_TYPE_NOTIFICATION_SENSOR\",\"_help\":\"Notification Sensor\"}],\"_key\":\"0x07\",\"_name\":\"GENERIC_TYPE_SENSOR_NOTIFICATION\",\"_help\":\"Sensor Notification\",\"_read_only\":\"false\"}],\"cmd_class\":[{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"ALARM_GET\",\"_help\":\"Alarm Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"ALARM_REPORT\",\"_help\":\"Alarm Report\",\"_comment\":\"\"}],\"_key\":\"0x71\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ALARM\",\"_help\":\"Command Class Alarm\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"ZWave Alarm Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"ALARM_GET\",\"_help\":\"Alarm Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Zensor Net Source Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"ZWave Alarm Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"ZWave Alarm Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"ZWave Alarm Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Number of Event Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Event Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"ALARM_REPORT\",\"_help\":\"Alarm Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"ZWave Alarm Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"ZWave Alarm Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"ALARM_SET\",\"_help\":\"Alarm Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"ALARM_TYPE_SUPPORTED_GET\",\"_help\":\"Alarm Type Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"V1 Alarm\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"ALARM_TYPE_SUPPORTED_REPORT\",\"_help\":\"Alarm Type Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x71\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_ALARM\",\"_help\":\"Command Class Alarm\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NOTIFICATION_GET\",\"_help\":\"Notification Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"V1 Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Notification Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Event Parameters Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Sequence\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Event Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"NOTIFICATION_REPORT\",\"_help\":\"Notification Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"NOTIFICATION_SET\",\"_help\":\"Notification Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"NOTIFICATION_SUPPORTED_GET\",\"_help\":\"Notification Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"V1 Alarm\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"NOTIFICATION_SUPPORTED_REPORT\",\"_help\":\"Notification Supported Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"EVENT_SUPPORTED_GET\",\"_help\":\"Event Supported Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Burglar\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"1\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"EVENT_SUPPORTED_REPORT\",\"_help\":\"Event Supported Report\"}],\"_key\":\"0x71\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_NOTIFICATION\",\"_help\":\"Command Class Notification\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NOTIFICATION_GET\",\"_help\":\"Notification Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"V1 Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Event Parameters Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Sequence\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Event Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"NOTIFICATION_REPORT\",\"_help\":\"Notification Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"NOTIFICATION_SET\",\"_help\":\"Notification Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"NOTIFICATION_SUPPORTED_GET\",\"_help\":\"Notification Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"V1 Alarm\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"NOTIFICATION_SUPPORTED_REPORT\",\"_help\":\"Notification Supported Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"EVENT_SUPPORTED_GET\",\"_help\":\"Event Supported Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"1\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"EVENT_SUPPORTED_REPORT\",\"_help\":\"Event Supported Report\"}],\"_key\":\"0x71\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_NOTIFICATION\",\"_help\":\"Command Class Notification\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NOTIFICATION_GET\",\"_help\":\"Notification Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"V1 Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Event Parameters Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Sequence\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Event Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"NOTIFICATION_REPORT\",\"_help\":\"Notification Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"NOTIFICATION_SET\",\"_help\":\"Notification Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"NOTIFICATION_SUPPORTED_GET\",\"_help\":\"Notification Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"V1 Alarm\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"NOTIFICATION_SUPPORTED_REPORT\",\"_help\":\"Notification Supported Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"EVENT_SUPPORTED_GET\",\"_help\":\"Event Supported Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"1\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"EVENT_SUPPORTED_REPORT\",\"_help\":\"Event Supported Report\"}],\"_key\":\"0x71\",\"_version\":\"5\",\"_name\":\"COMMAND_CLASS_NOTIFICATION\",\"_help\":\"Command Class Notification\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NOTIFICATION_GET\",\"_help\":\"Notification Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"V1 Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Event Parameters Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Sequence\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Event Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"NOTIFICATION_REPORT\",\"_help\":\"Notification Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"NOTIFICATION_SET\",\"_help\":\"Notification Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"NOTIFICATION_SUPPORTED_GET\",\"_help\":\"Notification Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"V1 Alarm\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"NOTIFICATION_SUPPORTED_REPORT\",\"_help\":\"Notification Supported Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"EVENT_SUPPORTED_GET\",\"_help\":\"Event Supported Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"1\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"EVENT_SUPPORTED_REPORT\",\"_help\":\"Event Supported Report\"}],\"_key\":\"0x71\",\"_version\":\"6\",\"_name\":\"COMMAND_CLASS_NOTIFICATION\",\"_help\":\"Command Class Notification\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"Water Valve\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Weather Alarm\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Irrigation\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Gas Alarm\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NOTIFICATION_GET\",\"_help\":\"Notification Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"V1 Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"V1 Alarm Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"Water Valve\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Weather Alarm\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Irrigation\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Gas Alarm\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Event Parameters Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Sequence\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Event Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"NOTIFICATION_REPORT\",\"_help\":\"Notification Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"Water Valve\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Weather Alarm\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Irrigation\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Gas Alarm\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"No pending notifications\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"On\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Notification Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"NOTIFICATION_SET\",\"_help\":\"Notification Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"NOTIFICATION_SUPPORTED_GET\",\"_help\":\"Notification Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"V1 Alarm\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"Water Valve\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Weather Alarm\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Irrigation\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Gas Alarm\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"NOTIFICATION_SUPPORTED_REPORT\",\"_help\":\"Notification Supported Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"Water Valve\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Weather Alarm\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Irrigation\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Gas Alarm\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"EVENT_SUPPORTED_GET\",\"_help\":\"Event Supported Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"CO\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Water\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Access Control\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Home Security\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Power Management\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"System\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Emergency\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Clock\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Appliance\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Home Health\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Siren\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"Water Valve\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Weather Alarm\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Irrigation\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Gas Alarm\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Notification Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Bit Masks\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"1\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"EVENT_SUPPORTED_REPORT\",\"_help\":\"Event Supported Report\"}],\"_key\":\"0x71\",\"_version\":\"7\",\"_name\":\"COMMAND_CLASS_NOTIFICATION\",\"_help\":\"Command Class Notification\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Try again later\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Try again in Wait Time seconds\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Request queued, executed later\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"The status field\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Wait Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"APPLICATION_BUSY\",\"_help\":\"Application Busy\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"APPLICATION_REJECTED_REQUEST\",\"_help\":\"Application Rejected Request\",\"_comment\":\"\"}],\"_key\":\"0x22\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_APPLICATION_STATUS\",\"_help\":\"Command Class Application Status\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"COMMAND_CONFIGURATION_GET\",\"_help\":\"Command Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reports to follow\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"First\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Command length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Command Class identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Command identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x06\",\"_name\":\"Command byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"COMMAND_CONFIGURATION_REPORT\",\"_help\":\"Command Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Command length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Command Class identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Command identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Command byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"COMMAND_CONFIGURATION_SET\",\"_help\":\"Command Configuration Set\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"COMMAND_RECORDS_SUPPORTED_GET\",\"_help\":\"Command Records Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Conf. Cmd\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"V/C\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Max command length\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Free Command records\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Max Command records\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"COMMAND_RECORDS_SUPPORTED_REPORT\",\"_help\":\"Command Records Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x9B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION\",\"_help\":\"Command Class Association Command Configuration\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"ASSOCIATION_GET\",\"_help\":\"Association Get\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"ASSOCIATION_GROUPINGS_GET\",\"_help\":\"Association Groupings Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Groupings\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"ASSOCIATION_GROUPINGS_REPORT\",\"_help\":\"Association Groupings Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"ASSOCIATION_REMOVE\",\"_help\":\"Association Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Max Nodes Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"NodeID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x03\",\"_name\":\"ASSOCIATION_REPORT\",\"_help\":\"Association Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x01\",\"_name\":\"ASSOCIATION_SET\",\"_help\":\"Association Set\",\"_comment\":\"\"}],\"_key\":\"0x85\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ASSOCIATION\",\"_help\":\"Command Class Association\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"ASSOCIATION_GET\",\"_help\":\"Association Get\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"ASSOCIATION_GROUPINGS_GET\",\"_help\":\"Association Groupings Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Groupings\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"ASSOCIATION_GROUPINGS_REPORT\",\"_help\":\"Association Groupings Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"ASSOCIATION_REMOVE\",\"_help\":\"Association Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Max Nodes Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"NodeID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x03\",\"_name\":\"ASSOCIATION_REPORT\",\"_help\":\"Association Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x01\",\"_name\":\"ASSOCIATION_SET\",\"_help\":\"Association Set\",\"_comment\":\"\"},{\"_key\":\"0x0B\",\"_name\":\"ASSOCIATION_SPECIFIC_GROUP_GET\",\"_help\":\"Association Specific Group Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Group\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"ASSOCIATION_SPECIFIC_GROUP_REPORT\",\"_help\":\"Association Specific Group Report\",\"_comment\":\"\"}],\"_key\":\"0x85\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_ASSOCIATION\",\"_help\":\"Command Class Association\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x03\",\"_name\":\"AV_CONTENT_BROWSE_MD_BY_LETTER_GET\",\"_help\":\"Av Content Browse Md By Letter Get\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"AV_CONTENT_BROWSE_MD_BY_LETTER_REPORT\",\"_help\":\"Av Content Browse Md By Letter Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"AV_CONTENT_BROWSE_MD_CHILD_COUNT_GET\",\"_help\":\"Av Content Browse Md Child Count Get\",\"_comment\":\"\"},{\"_key\":\"0x06\",\"_name\":\"AV_CONTENT_BROWSE_MD_CHILD_COUNT_REPORT\",\"_help\":\"Av Content Browse Md Child Count Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"AV_CONTENT_BROWSE_MD_GET\",\"_help\":\"Av Content Browse Md Get\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"AV_CONTENT_BROWSE_MD_REPORT\",\"_help\":\"Av Content Browse Md Report\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"AV_MATCH_ITEM_TO_RENDERER_MD_GET\",\"_help\":\"Av Match Item To Renderer Md Get\",\"_comment\":\"\"},{\"_key\":\"0x08\",\"_name\":\"AV_MATCH_ITEM_TO_RENDERER_MD_REPORT\",\"_help\":\"Av Match Item To Renderer Md Report\",\"_comment\":\"\"}],\"_key\":\"0x95\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_AV_CONTENT_DIRECTORY_MD\",\"_help\":\"Command Class Av Content Directory Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"AV_CONTENT_SEARCH_MD_GET\",\"_help\":\"Av Content Search Md Get\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"AV_CONTENT_SEARCH_MD_REPORT\",\"_help\":\"Av Content Search Md Report\",\"_comment\":\"\"}],\"_key\":\"0x97\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_AV_CONTENT_SEARCH_MD\",\"_help\":\"Command Class Av Content Search Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"AV_RENDERER_STATUS_GET\",\"_help\":\"Av Renderer Status Get\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"AV_RENDERER_STATUS_REPORT\",\"_help\":\"Av Renderer Status Report\",\"_comment\":\"\"}],\"_key\":\"0x96\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_AV_RENDERER_STATUS\",\"_help\":\"Command Class Av Renderer Status\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"AV_TAGGING_MD_GET\",\"_help\":\"Av Tagging Md Get\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"AV_TAGGING_MD_REPORT\",\"_help\":\"Av Tagging Md Report\",\"_comment\":\"\"}],\"_key\":\"0x99\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_AV_TAGGING_MD\",\"_help\":\"Command Class Av Tagging Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"BASIC_TARIFF_INFO_GET\",\"_help\":\"Basic Tariff Info Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Total No. Import Rates\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Dual\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"E1 Current Rate in Use\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"E1 Rate Consumption Register\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"E1 Time for Next Rate Hours\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"E1 Time for Next Rate Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"E1 Time for Next Rate Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"E2 Current Rate in Use\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved3\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x06\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"E2 Rate Consumption Register\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"BASIC_TARIFF_INFO_REPORT\",\"_help\":\"Basic Tariff Info Report\",\"_comment\":\"\"}],\"_key\":\"0x36\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_BASIC_TARIFF_INFO\",\"_help\":\"Command Class Basic Tariff Info\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Open/ Close\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"BASIC_WINDOW_COVERING_START_LEVEL_CHANGE\",\"_help\":\"Basic Window Covering Start Level Change\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"BASIC_WINDOW_COVERING_STOP_LEVEL_CHANGE\",\"_help\":\"Basic Window Covering Stop Level Change\",\"_comment\":\"\"}],\"_key\":\"0x50\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_BASIC_WINDOW_COVERING\",\"_help\":\"Command Class Basic Window Covering\",\"_read_only\":\"false\",\"_comment\":\"Obsoleted\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"BASIC_GET\",\"_help\":\"Basic Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"BASIC_REPORT\",\"_help\":\"Basic Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"BASIC_SET\",\"_help\":\"Basic Set\",\"_comment\":\"\"}],\"_key\":\"0x20\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_BASIC\",\"_help\":\"Command Class Basic\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"BASIC_GET\",\"_help\":\"Basic Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Current Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Target Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"BASIC_REPORT\",\"_help\":\"Basic Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"BASIC_SET\",\"_help\":\"Basic Set\",\"_comment\":\"\"}],\"_key\":\"0x20\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_BASIC\",\"_help\":\"Command Class Basic\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"BATTERY_GET\",\"_help\":\"Battery Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"battery low warning\",\"_flagmask\":\"0xFF\"},\"_key\":\"0x00\",\"_name\":\"Battery Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"BATTERY_REPORT\",\"_help\":\"Battery Report\",\"_comment\":\"\"}],\"_key\":\"0x80\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_BATTERY\",\"_help\":\"Command Class Battery\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x20\",\"_name\":\"CHIMNEY_FAN_ALARM_LOG_GET\",\"_help\":\"Chimney Fan Alarm Log Get\",\"_comment\":\"\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved11\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm 1\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error 1\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded 1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm still active 1\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Reserved12\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Alarm Event 1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved21\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm 2\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error 2\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded 2\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm still active 2\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Reserved22\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"_key\":\"0x01\",\"_name\":\"Alarm Event 2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved31\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm 3\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error 3\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded 3\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm still active 3\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Reserved32\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"_key\":\"0x02\",\"_name\":\"Alarm Event 3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved41\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm 4\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error 4\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded 4\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm still active 4\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Reserved42\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"_key\":\"0x03\",\"_name\":\"Alarm Event 4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved51\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm 5\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error 5\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded 5\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm still active 5\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Reserved52\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"_key\":\"0x04\",\"_name\":\"Alarm Event 5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x21\",\"_name\":\"CHIMNEY_FAN_ALARM_LOG_REPORT\",\"_help\":\"Chimney Fan Alarm Log Report\",\"_comment\":\"\"},{\"param\":{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Reset log\",\"_flagmask\":\"0x08\"},\"_key\":\"0x00\",\"_name\":\"Message\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x1F\",\"_name\":\"CHIMNEY_FAN_ALARM_LOG_SET\",\"_help\":\"Chimney Fan Alarm Log Set\",\"_comment\":\"\"},{\"_key\":\"0x23\",\"_name\":\"CHIMNEY_FAN_ALARM_STATUS_GET\",\"_help\":\"Chimney Fan Alarm Status Get\",\"_comment\":\"\"},{\"param\":{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Service\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Speed change Enable\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x06\",\"_flagname\":\"Start Temperature Exceeded\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Not Used \",\"_fieldmask\":\"0x30\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Alarm Status\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x24\",\"_name\":\"CHIMNEY_FAN_ALARM_STATUS_REPORT\",\"_help\":\"Chimney Fan Alarm Status Report\",\"_comment\":\"\"},{\"param\":{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Not Used1\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Acknowledge External Alarm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Acknowledge Sensor Error\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Acknowledge Alarm Temperature Exceeded\",\"_flagmask\":\"0x08\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Not Used2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Message\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x22\",\"_name\":\"CHIMNEY_FAN_ALARM_STATUS_SET\",\"_help\":\"Chimney Fan Alarm Status Set\",\"_comment\":\"\"},{\"_key\":\"0x0E\",\"_name\":\"CHIMNEY_FAN_ALARM_TEMP_GET\",\"_help\":\"Chimney Fan Alarm Temp Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x0F\",\"_name\":\"CHIMNEY_FAN_ALARM_TEMP_REPORT\",\"_help\":\"Chimney Fan Alarm Temp Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x0D\",\"_name\":\"CHIMNEY_FAN_ALARM_TEMP_SET\",\"_help\":\"Chimney Fan Alarm Temp Set\",\"_comment\":\"\"},{\"_key\":\"0x11\",\"_name\":\"CHIMNEY_FAN_BOOST_TIME_GET\",\"_help\":\"Chimney Fan Boost Time Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x12\",\"_name\":\"CHIMNEY_FAN_BOOST_TIME_REPORT\",\"_help\":\"Chimney Fan Boost Time Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x10\",\"_name\":\"CHIMNEY_FAN_BOOST_TIME_SET\",\"_help\":\"Chimney Fan Boost Time Set\",\"_comment\":\"\"},{\"_key\":\"0x28\",\"_name\":\"CHIMNEY_FAN_DEFAULT_SET\",\"_help\":\"Chimney Fan Default Set\",\"_comment\":\"\"},{\"_key\":\"0x26\",\"_name\":\"CHIMNEY_FAN_MIN_SPEED_GET\",\"_help\":\"Chimney Fan Min Speed Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Min Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x27\",\"_name\":\"CHIMNEY_FAN_MIN_SPEED_REPORT\",\"_help\":\"Chimney Fan Min Speed Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Min Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x25\",\"_name\":\"CHIMNEY_FAN_MIN_SPEED_SET\",\"_help\":\"Chimney Fan Min Speed Set\",\"_comment\":\"\"},{\"_key\":\"0x17\",\"_name\":\"CHIMNEY_FAN_MODE_GET\",\"_help\":\"Chimney Fan Mode Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ON\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x18\",\"_name\":\"CHIMNEY_FAN_MODE_REPORT\",\"_help\":\"Chimney Fan Mode Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ON\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x16\",\"_name\":\"CHIMNEY_FAN_MODE_SET\",\"_help\":\"Chimney Fan Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x1A\",\"_name\":\"CHIMNEY_FAN_SETUP_GET\",\"_help\":\"Chimney Fan Setup Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ON\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Boost Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Stop Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Min. Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size 1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale 1\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision 1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Start Temperature\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size 2\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale 2\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision 2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Stop Temperature\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size 3\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale 3\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision 3\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x08\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"8\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x09\",\"_name\":\"Alarm Temperature Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x1B\",\"_name\":\"CHIMNEY_FAN_SETUP_REPORT\",\"_help\":\"Chimney Fan Setup Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ON\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Boost Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Stop Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Min. Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size 1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale 1\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision 1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Start Temperature\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size 2\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale 2\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision 2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Stop Temperature\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size 3\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale 3\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision 3\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x08\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"8\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x09\",\"_name\":\"Alarm Temperature Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x19\",\"_name\":\"CHIMNEY_FAN_SETUP_SET\",\"_help\":\"Chimney Fan Setup Set\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"CHIMNEY_FAN_SPEED_GET\",\"_help\":\"Chimney Fan Speed Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"CHIMNEY_FAN_SPEED_REPORT\",\"_help\":\"Chimney Fan Speed Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Speed down\",\"_flagmask\":\"0x65\"},{\"_key\":\"0x02\",\"_flagname\":\"Speed up\",\"_flagmask\":\"0xC8\"}],\"_key\":\"0x00\",\"_name\":\"Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"CHIMNEY_FAN_SPEED_SET\",\"_help\":\"Chimney Fan Speed Set\",\"_comment\":\"\"},{\"_key\":\"0x08\",\"_name\":\"CHIMNEY_FAN_START_TEMP_GET\",\"_help\":\"Chimney Fan Start Temp Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"CHIMNEY_FAN_START_TEMP_REPORT\",\"_help\":\"Chimney Fan Start Temp Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"CHIMNEY_FAN_START_TEMP_SET\",\"_help\":\"Chimney Fan Start Temp Set\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"CHIMNEY_FAN_STATE_GET\",\"_help\":\"Chimney Fan State Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Boost\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Exhaust\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Reload\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Venting\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Stop\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Venting_EX\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Service\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Sensor Failure  \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Chimney Fire\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"External alarm\",\"_flagmask\":\"0x0A\"}],\"_key\":\"0x00\",\"_name\":\"State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"CHIMNEY_FAN_STATE_REPORT\",\"_help\":\"Chimney Fan State Report\",\"_comment\":\"\"},{\"param\":{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Next State\",\"_flagmask\":\"0x01\"},\"_key\":\"0x00\",\"_name\":\"State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"CHIMNEY_FAN_STATE_SET\",\"_help\":\"Chimney Fan State Set\",\"_comment\":\"\"},{\"_key\":\"0x1D\",\"_name\":\"CHIMNEY_FAN_STATUS_GET\",\"_help\":\"Chimney Fan Status Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Boost\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Exhaust\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Reload\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Venting\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Stop\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Venting_EX\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Service\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Sensor Failure  \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Chimney Fire\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"External alarm\",\"_flagmask\":\"0x0A\"}],\"_key\":\"0x00\",\"_name\":\"State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Speed\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Service\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"External Alarm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Sensor Error\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Alarm Temperature Exceeded\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Speed change Enable\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x06\",\"_flagname\":\"Start Temperature Exceeded\",\"_flagmask\":\"0x80\"}],\"bitfield\":{\"_key\":\"0x04\",\"_fieldname\":\"Not Used \",\"_fieldmask\":\"0x30\",\"_shifter\":\"4\"},\"_key\":\"0x02\",\"_name\":\"Alarm Status\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x1E\",\"_name\":\"CHIMNEY_FAN_STATUS_REPORT\",\"_help\":\"Chimney Fan Status Report\",\"_comment\":\"\"},{\"_key\":\"0x0B\",\"_name\":\"CHIMNEY_FAN_STOP_TEMP_GET\",\"_help\":\"Chimney Fan Stop Temp Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x0C\",\"_name\":\"CHIMNEY_FAN_STOP_TEMP_REPORT\",\"_help\":\"Chimney Fan Stop Temp Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x0A\",\"_name\":\"CHIMNEY_FAN_STOP_TEMP_SET\",\"_help\":\"Chimney Fan Stop Temp Set\",\"_comment\":\"\"},{\"_key\":\"0x14\",\"_name\":\"CHIMNEY_FAN_STOP_TIME_GET\",\"_help\":\"Chimney Fan Stop Time Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x15\",\"_name\":\"CHIMNEY_FAN_STOP_TIME_REPORT\",\"_help\":\"Chimney Fan Stop Time Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x13\",\"_name\":\"CHIMNEY_FAN_STOP_TIME_SET\",\"_help\":\"Chimney Fan Stop Time Set\",\"_comment\":\"\"}],\"_key\":\"0x2A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CHIMNEY_FAN\",\"_help\":\"Command Class Chimney Fan\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"SCHEDULE_CHANGED_GET\",\"_help\":\"Schedule Changed Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"ChangeCounter\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"SCHEDULE_CHANGED_REPORT\",\"_help\":\"Schedule Changed Report\",\"_comment\":\"\"},{\"param\":{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Weekday\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_GET\",\"_help\":\"Schedule Get\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"SCHEDULE_OVERRIDE_GET\",\"_help\":\"Schedule Override Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Override Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"No override\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Temporary override\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Permanent override\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x01\",\"_name\":\"Override State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"SCHEDULE_OVERRIDE_REPORT\",\"_help\":\"Schedule Override Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Override Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"No override\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Temporary override\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Permanent override\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x01\",\"_name\":\"Override State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SCHEDULE_OVERRIDE_SET\",\"_help\":\"Schedule Override Set\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Weekday\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Switchpoint 0\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Switchpoint 1\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Switchpoint 2\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Switchpoint 3\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Switchpoint 4\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Switchpoint 5\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Switchpoint 6\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Switchpoint 7\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Switchpoint 8\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCHEDULE_REPORT\",\"_help\":\"Schedule Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Weekday\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Switchpoint 0\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Switchpoint 1\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Switchpoint 2\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Switchpoint 3\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Switchpoint 4\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Switchpoint 5\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Switchpoint 6\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Switchpoint 7\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Switchpoint 8\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCHEDULE_SET\",\"_help\":\"Schedule Set\",\"_comment\":\"\"}],\"_key\":\"0x46\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE\",\"_help\":\"Command Class Climate Control Schedule\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"CLOCK_GET\",\"_help\":\"Clock Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Weekday\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"CLOCK_REPORT\",\"_help\":\"Clock Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Weekday\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"CLOCK_SET\",\"_help\":\"Clock Set\",\"_comment\":\"\"}],\"_key\":\"0x81\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CLOCK\",\"_help\":\"Command Class Clock\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"CONFIGURATION_GET\",\"_help\":\"Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Configuration Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"CONFIGURATION_REPORT\",\"_help\":\"Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x78\",\"_shifter\":\"3\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Configuration Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"CONFIGURATION_SET\",\"_help\":\"Configuration Set\",\"_comment\":\"\"}],\"_key\":\"0x70\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CONFIGURATION\",\"_help\":\"Command Class Configuration\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Offset\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"CONFIGURATION_BULK_GET\",\"_help\":\"Configuration Bulk Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Offset\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Handshake\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"variant\":{\"_paramoffs\":\"131\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x01\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"CONFIGURATION_BULK_REPORT\",\"_help\":\"Configuration Bulk Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Offset\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Handshake\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"variant\":{\"_paramoffs\":\"130\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x01\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"CONFIGURATION_BULK_SET\",\"_help\":\"Configuration Bulk Set\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"CONFIGURATION_GET\",\"_help\":\"Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Configuration Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"CONFIGURATION_REPORT\",\"_help\":\"Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x78\",\"_shifter\":\"3\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Configuration Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"CONFIGURATION_SET\",\"_help\":\"Configuration Set\",\"_comment\":\"\"}],\"_key\":\"0x70\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_CONFIGURATION\",\"_help\":\"Command Class Configuration\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Offset\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"CONFIGURATION_BULK_GET\",\"_help\":\"Configuration Bulk Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Offset\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Handshake\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"variant\":{\"_paramoffs\":\"131\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x01\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"CONFIGURATION_BULK_REPORT\",\"_help\":\"Configuration Bulk Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Offset\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Handshake\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"variant\":{\"_paramoffs\":\"130\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x01\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"CONFIGURATION_BULK_SET\",\"_help\":\"Configuration Bulk Set\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"CONFIGURATION_GET\",\"_help\":\"Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Configuration Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"CONFIGURATION_REPORT\",\"_help\":\"Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x78\",\"_shifter\":\"3\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Configuration Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"CONFIGURATION_SET\",\"_help\":\"Configuration Set\",\"_comment\":\"\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x0A\",\"_name\":\"CONFIGURATION_NAME_GET\",\"_help\":\"Configuration Name Get\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"CONFIGURATION_NAME_REPORT\",\"_help\":\"Configuration Name Report\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x0C\",\"_name\":\"CONFIGURATION_INFO_GET\",\"_help\":\"Configuration Info Get\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Info\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0D\",\"_name\":\"CONFIGURATION_INFO_REPORT\",\"_help\":\"Configuration Info Report\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x0E\",\"_name\":\"CONFIGURATION_PROPERTIES_GET\",\"_help\":\"Configuration Properties Get\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Signed Integer\"},{\"_value\":\"Unsigned Integer\"},{\"_value\":\"Enumerated\"},{\"_value\":\"Bit field\"}],\"_key\":\"0x01\",\"_fieldname\":\"Format\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Min Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Max Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Default Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Next Parameter Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x0F\",\"_name\":\"CONFIGURATION_PROPERTIES_REPORT\",\"_help\":\"Configuration Properties Report\"}],\"_key\":\"0x70\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_CONFIGURATION\",\"_help\":\"Command Class Configuration\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Group ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x31\",\"_name\":\"CTRL_REPLICATION_TRANSFER_GROUP\",\"_help\":\"Ctrl Replication Transfer Group\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Group ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Group Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x32\",\"_name\":\"CTRL_REPLICATION_TRANSFER_GROUP_NAME\",\"_help\":\"Ctrl Replication Transfer Group Name\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x33\",\"_name\":\"CTRL_REPLICATION_TRANSFER_SCENE\",\"_help\":\"Ctrl Replication Transfer Scene\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Scene Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x34\",\"_name\":\"CTRL_REPLICATION_TRANSFER_SCENE_NAME\",\"_help\":\"Ctrl Replication Transfer Scene Name\",\"_comment\":\"\"}],\"_key\":\"0x21\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CONTROLLER_REPLICATION\",\"_help\":\"Command Class Controller Replication\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"CRC_16_ENCAP\",\"_help\":\"CRC16 Encap\",\"_comment\":\"\"},\"_key\":\"0x56\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CRC_16_ENCAP\",\"_help\":\"Command Class CRC16 Encap\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DCP_LIST_REMOVE\",\"_help\":\"Dcp List Remove\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"DCP Rate ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of DC\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x07\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0D\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0E\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0F\",\"_name\":\"Duration Hour Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x10\",\"_name\":\"Duration Minute Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x11\",\"_name\":\"Duration Second Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x12\",\"_name\":\"Event Priority\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x13\",\"_name\":\"Load shedding\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x14\",\"_name\":\"Start Association Group\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x15\",\"_name\":\"Stop Association Group\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x16\",\"_name\":\"Randomization interval\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x07\",\"_sizemask\":\"0x03\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"DCP_LIST_SET\",\"_help\":\"Dcp List Set\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"DCP_LIST_SUPPORTED_GET\",\"_help\":\"Dcp List Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"DCP List Size\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Free DCP List entries\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"DCP_LIST_SUPPORTED_REPORT\",\"_help\":\"Dcp List Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x3A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_DCP_CONFIG\",\"_help\":\"Command Class Dcp Config\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"DCP_EVENT_STATUS_GET\",\"_help\":\"Dcp Event Status Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Event Started\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Event Completed\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"Event Rejected\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"Event not Applicable\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x06\",\"_name\":\"Event status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DCP_EVENT_STATUS_REPORT\",\"_help\":\"Dcp Event Status Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"DCP_LIST_GET\",\"_help\":\"Dcp List Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"DCP ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of DC\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x08\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0D\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0E\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0F\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x10\",\"_name\":\"Duration Hour Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x11\",\"_name\":\"Duration Minute Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x12\",\"_name\":\"Duration Second Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x13\",\"_name\":\"Event Priority\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x14\",\"_name\":\"Load shedding\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x15\",\"_name\":\"Start Association Group\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x16\",\"_name\":\"Stop Association Group\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x17\",\"_name\":\"Randomization interval\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"DCP_LIST_REPORT\",\"_help\":\"Dcp List Report\",\"_comment\":\"\"}],\"_key\":\"0x3B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_DCP_MONITOR\",\"_help\":\"Command Class Dcp Monitor\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"DOOR_LOCK_LOGGING_RECORDS_SUPPORTED_GET\",\"_help\":\"Door Lock Logging Records Supported Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Max records stored\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"DOOR_LOCK_LOGGING_RECORDS_SUPPORTED_REPORT\",\"_help\":\"Door Lock Logging Records Supported Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Record number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"RECORD_GET\",\"_help\":\"Record Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Record number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Hour Local Time\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Record status\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Event Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"User Code Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"USER_CODE\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"RECORD_REPORT\",\"_help\":\"Record Report\",\"_comment\":\"\"}],\"_key\":\"0x4C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_DOOR_LOCK_LOGGING\",\"_help\":\"Command Class Door Lock Logging\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"DOOR_LOCK_CONFIGURATION_GET\",\"_help\":\"Door Lock Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Constant operation\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Timed operation\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Operation Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles State\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"DOOR_LOCK_CONFIGURATION_REPORT\",\"_help\":\"Door Lock Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Constant operation\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Timed operation\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Operation Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles State\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DOOR_LOCK_CONFIGURATION_SET\",\"_help\":\"Door Lock Configuration Set\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"DOOR_LOCK_OPERATION_GET\",\"_help\":\"Door Lock Operation Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles Mode\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Door Condition\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"DOOR_LOCK_OPERATION_REPORT\",\"_help\":\"Door Lock Operation Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"DOOR_LOCK_OPERATION_SET\",\"_help\":\"Door Lock Operation Set\",\"_comment\":\"\"}],\"_key\":\"0x62\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_DOOR_LOCK\",\"_help\":\"Command Class Door Lock\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"DOOR_LOCK_CONFIGURATION_GET\",\"_help\":\"Door Lock Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Constant operation\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Timed operation\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Operation Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles State\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"DOOR_LOCK_CONFIGURATION_REPORT\",\"_help\":\"Door Lock Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Constant operation\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Timed operation\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Operation Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles State\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DOOR_LOCK_CONFIGURATION_SET\",\"_help\":\"Door Lock Configuration Set\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"DOOR_LOCK_OPERATION_GET\",\"_help\":\"Door Lock Operation Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door/Lock State Unknown\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x07\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles Mode\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Door Condition\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"DOOR_LOCK_OPERATION_REPORT\",\"_help\":\"Door Lock Operation Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door/Lock State Unknown\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x07\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"DOOR_LOCK_OPERATION_SET\",\"_help\":\"Door Lock Operation Set\",\"_comment\":\"\"}],\"_key\":\"0x62\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_DOOR_LOCK\",\"_help\":\"Command Class Door Lock\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"DOOR_LOCK_CONFIGURATION_GET\",\"_help\":\"Door Lock Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Constant operation\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Timed operation\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Operation Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles State\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"DOOR_LOCK_CONFIGURATION_REPORT\",\"_help\":\"Door Lock Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Constant operation\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Timed operation\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Operation Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles State\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DOOR_LOCK_CONFIGURATION_SET\",\"_help\":\"Door Lock Configuration Set\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"DOOR_LOCK_OPERATION_GET\",\"_help\":\"Door Lock Operation Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door/Lock State Unknown\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x07\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Current Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Inside Door Handles Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Outside Door Handles Mode\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Door Condition\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Lock Timeout Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Lock Timeout Seconds\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door/Lock State Unknown\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x07\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x05\",\"_name\":\"Target Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Already at the Target Value\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Unknown duration\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x06\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x03\",\"_name\":\"DOOR_LOCK_OPERATION_REPORT\",\"_help\":\"Door Lock Operation Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Door Unsecured\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Door Unsecured with timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Door Unsecured for inside Door Handles\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x03\",\"_flagname\":\"Door Unsecured for inside Door Handles with timeout\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x04\",\"_flagname\":\"Door Unsecured for outside Door Handles\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Door Unsecured for outside Door Handles with timeout\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x06\",\"_flagname\":\"Door/Lock State Unknown\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x07\",\"_flagname\":\"Door Secured\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Door Lock Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"DOOR_LOCK_OPERATION_SET\",\"_help\":\"Door Lock Operation Set\",\"_comment\":\"\"}],\"_key\":\"0x62\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_DOOR_LOCK\",\"_help\":\"Command Class Door Lock\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Instant energy production\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Total energy production\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Energy production today\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Total production time\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"ENERGY_PRODUCTION_GET\",\"_help\":\"Energy Production Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Instant energy production\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Total energy production\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Energy production today\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Total production time\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x00\",\"_name\":\"Parameter Number\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"ENERGY_PRODUCTION_REPORT\",\"_help\":\"Energy Production Report\",\"_comment\":\"\"}],\"_key\":\"0x90\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ENERGY_PRODUCTION\",\"_help\":\"Command Class Energy Production\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"FIRMWARE_MD_GET\",\"_help\":\"Firmware Md Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"FIRMWARE_MD_REPORT\",\"_help\":\"Firmware Md Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"zero\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"FIRMWARE_UPDATE_MD_GET\",\"_help\":\"Firmware Update Md Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Last\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"FIRMWARE_UPDATE_MD_REPORT\",\"_help\":\"Firmware Update Md Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_GET\",\"_help\":\"Firmware Update Md Request Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Invalid combination\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Requires authentication\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Valid combination\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_REPORT\",\"_help\":\"Firmware Update Md Request Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"unable to receive without checksum error\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"unable to receive\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"successfully\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"FIRMWARE_UPDATE_MD_STATUS_REPORT\",\"_help\":\"Firmware Update Md Status Report\",\"_comment\":\"\"}],\"_key\":\"0x7A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_FIRMWARE_UPDATE_MD\",\"_help\":\"Command Class Firmware Update Md\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"FIRMWARE_MD_GET\",\"_help\":\"Firmware Md Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"FIRMWARE_MD_REPORT\",\"_help\":\"Firmware Md Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"zero\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"FIRMWARE_UPDATE_MD_GET\",\"_help\":\"Firmware Update Md Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Last\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"FIRMWARE_UPDATE_MD_REPORT\",\"_help\":\"Firmware Update Md Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_GET\",\"_help\":\"Firmware Update Md Request Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Invalid combination\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Requires authentication\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Valid combination\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_REPORT\",\"_help\":\"Firmware Update Md Request Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"unable to receive without checksum error\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"unable to receive\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"successfully\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"FIRMWARE_UPDATE_MD_STATUS_REPORT\",\"_help\":\"Firmware Update Md Status Report\",\"_comment\":\"\"}],\"_key\":\"0x7A\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_FIRMWARE_UPDATE_MD\",\"_help\":\"Command Class Firmware Update Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"FIRMWARE_MD_GET\",\"_help\":\"Firmware Md Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware 0 ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Firmware 0 Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware Upgradable\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Number of Firmware Targets\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Max Fragment Size \",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"variant_group\":{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x06\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x04\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"FIRMWARE_MD_REPORT\",\"_help\":\"Firmware Md Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"zero\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"FIRMWARE_UPDATE_MD_GET\",\"_help\":\"Firmware Update Md Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Last\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"FIRMWARE_UPDATE_MD_REPORT\",\"_help\":\"Firmware Update Md Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware Target\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Fragment Size\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x03\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_GET\",\"_help\":\"Firmware Update Md Request Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Invalid combination\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Requires authentication\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Invalid Fragment Size\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Not upgradable\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Valid combination\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_REPORT\",\"_help\":\"Firmware Update Md Request Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"unable to receive without checksum error\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"unable to receive\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"successfully stored\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x03\",\"_flagname\":\"successfully\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"WaitTime\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x07\",\"_name\":\"FIRMWARE_UPDATE_MD_STATUS_REPORT\",\"_help\":\"Firmware Update Md Status Report\",\"_comment\":\"\"}],\"_key\":\"0x7A\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_FIRMWARE_UPDATE_MD\",\"_help\":\"Command Class Firmware Update Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"FIRMWARE_MD_GET\",\"_help\":\"Firmware Md Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware 0 ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Firmware 0 Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware Upgradable\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Number of Firmware Targets\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Max Fragment Size \",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"variant_group\":{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x06\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x04\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"FIRMWARE_MD_REPORT\",\"_help\":\"Firmware Md Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"zero\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"FIRMWARE_UPDATE_MD_GET\",\"_help\":\"Firmware Update Md Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Report number 1\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Last\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Report number 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"FIRMWARE_UPDATE_MD_REPORT\",\"_help\":\"Firmware Update Md Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware Target\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Fragment Size\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Activation\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x05\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_GET\",\"_help\":\"Firmware Update Md Request Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Invalid combination\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Requires authentication\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Invalid Fragment Size\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Not upgradable\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Valid combination\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"FIRMWARE_UPDATE_MD_REQUEST_REPORT\",\"_help\":\"Firmware Update Md Request Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"unable to receive without checksum error\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"unable to receive\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"does not match the Manufacturer ID\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"does not match the Firmware ID\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"does not match the Firmware Target\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Invalid file header information\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Invalid file header format\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Insufficient memory\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"successfully, waiting for activation\",\"_flagmask\":\"0xFD\"},{\"_key\":\"0x09\",\"_flagname\":\"successfully stored\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x0A\",\"_flagname\":\"successfully\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"WaitTime\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x07\",\"_name\":\"FIRMWARE_UPDATE_MD_STATUS_REPORT\",\"_help\":\"Firmware Update Md Status Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware Target\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x08\",\"_name\":\"FIRMWARE_UPDATE_ACTIVATION_SET\",\"_help\":\"Firmware Update Activation Set Command\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware Target\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Invalid combination\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Error activating the firmware\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Firmware update completed successfully\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x04\",\"_name\":\"Firmware Update Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x09\",\"_name\":\"FIRMWARE_UPDATE_ACTIVATION_STATUS_REPORT\",\"_help\":\"Firmware Update Activation Status Report\"}],\"_key\":\"0x7A\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_FIRMWARE_UPDATE_MD\",\"_help\":\"Command Class Firmware Update Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"GEOGRAPHIC_LOCATION_GET\",\"_help\":\"Geographic Location Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Longitude Degrees\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Longitude Minutes\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Long. Sign\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Latitude Degrees\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Latitude Minutes\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Lat. Sign\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"GEOGRAPHIC_LOCATION_REPORT\",\"_help\":\"Geographic Location Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Longitude Degrees\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Longitude Minutes\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Long. Sign\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Latitude Degrees\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Latitude Minutes\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Lat. Sign\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"GEOGRAPHIC_LOCATION_SET\",\"_help\":\"Geographic Location Set\",\"_comment\":\"\"}],\"_key\":\"0x8C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_GEOGRAPHIC_LOCATION\",\"_help\":\"Command Class Geographic Location\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"GROUPING_NAME_GET\",\"_help\":\"Grouping Name Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Grouping Name\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"GROUPING_NAME_REPORT\",\"_help\":\"Grouping Name Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Grouping Name\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"GROUPING_NAME_SET\",\"_help\":\"Grouping Name Set\",\"_comment\":\"\"}],\"_key\":\"0x7B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_GROUPING_NAME\",\"_help\":\"Command Class Grouping Name\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":{\"_key\":\"0x01\",\"_name\":\"HAIL\",\"_help\":\"Hail\",\"_comment\":\"\"},\"_key\":\"0x82\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_HAIL\",\"_help\":\"Command Class Hail\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"HRV_CONTROL_BYPASS_GET\",\"_help\":\"Hrv Control Bypass  Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Bypass\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"HRV_CONTROL_BYPASS_REPORT\",\"_help\":\"Hrv Control Bypass Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Bypass\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"HRV_CONTROL_BYPASS_SET\",\"_help\":\"Hrv Control Bypass Set\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"HRV_CONTROL_MODE_GET\",\"_help\":\"Hrv Control Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Demand Automatic\"},{\"_value\":\"Schedule\"},{\"_value\":\"Energy Savings Mode\"},{\"_value\":\"Manual\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"HRV_CONTROL_MODE_REPORT\",\"_help\":\"Hrv Control Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Demand Automatic\"},{\"_value\":\"Schedule\"},{\"_value\":\"Energy Savings Mode\"},{\"_value\":\"Manual\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"HRV_CONTROL_MODE_SET\",\"_help\":\"Hrv Control Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x0A\",\"_name\":\"HRV_CONTROL_MODE_SUPPORTED_GET\",\"_help\":\"Hrv Control Mode Supported Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Bypass Open Close\"},{\"_value\":\"Bypass Auto\"},{\"_value\":\"Modulated Bypass\"},{\"_value\":\"Ventilation Rate\"}],\"_key\":\"0x00\",\"_fieldname\":\"Manual Control Supported\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Demand Automatic\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Schedule\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Energy Savings Mode\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Manual\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x0B\",\"_name\":\"HRV_CONTROL_MODE_SUPPORTED_REPORT\",\"_help\":\"Hrv Control Mode Supported Report\",\"_comment\":\"\"},{\"_key\":\"0x08\",\"_name\":\"HRV_CONTROL_VENTILATION_RATE_GET\",\"_help\":\"Hrv Control Ventilation Rate  Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Ventilation Rate\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"HRV_CONTROL_VENTILATION_RATE_REPORT\",\"_help\":\"Hrv Control Ventilation Rate  Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Ventilation Rate\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"HRV_CONTROL_VENTILATION_RATE_SET\",\"_help\":\"Hrv Control Ventilation Rate Set\",\"_comment\":\"\"}],\"_key\":\"0x39\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_HRV_CONTROL\",\"_help\":\"Command Class Hrv Control\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Outdoor Air temperature\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Supply Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Exhaust Air temperature\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Discharge Air temperature\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Room temperature\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Relative Humidity in room\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Remaining filter life\",\"_flagmask\":\"0x06\"}],\"_key\":\"0x00\",\"_name\":\"Status Parameter\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"HRV_STATUS_GET\",\"_help\":\"Hrv Status Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Outdoor Air temperature\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Supply Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Exhaust Air temperature\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Discharge Air temperature\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Room temperature\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Relative Humidity in room\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Remaining filter life\",\"_flagmask\":\"0x06\"}],\"_key\":\"0x00\",\"_name\":\"Status Parameter\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"HRV_STATUS_REPORT\",\"_help\":\"Hrv Status Report\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"HRV_STATUS_SUPPORTED_GET\",\"_help\":\"Hrv Status Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Outdoor Air temperature\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Supply Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Exhaust Air temperature\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Discharge Air temperature\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Room temperature\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Relative Humidity in room\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Remaining filter life\",\"_flagmask\":\"0x06\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"HRV_STATUS_SUPPORTED_REPORT\",\"_help\":\"Hrv Status Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x37\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_HRV_STATUS\",\"_help\":\"Command Class Hrv Status\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"INDICATOR_GET\",\"_help\":\"Indicator Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"INDICATOR_REPORT\",\"_help\":\"Indicator Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"INDICATOR_SET\",\"_help\":\"Indicator Set\",\"_comment\":\"\"}],\"_key\":\"0x87\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_INDICATOR\",\"_help\":\"Command Class Indicator\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ARMED\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NOT_ARMED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"READY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"FAULT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ENTER_ID\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ENTER_PIN\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"OK\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"NOT_OK\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ZONE1_ARMED\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x0B\",\"_flagname\":\"ZONE2_ARMED\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x0C\",\"_flagname\":\"ZONE3_ARMED\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x0D\",\"_flagname\":\"ZONE4_ARMED\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x0E\",\"_flagname\":\"ZONE5_ARMED\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x0F\",\"_flagname\":\"ZONE6_ARMED\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x10\",\"_flagname\":\"LCD_BACKLIGHT\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x11\",\"_flagname\":\"BUTTON_BACKLIGHT_LETTERS\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x12\",\"_flagname\":\"BUTTON_BACKLIGHT_DIGITS\",\"_flagmask\":\"0x41\"},{\"_key\":\"0x13\",\"_flagname\":\"BUTTON_BACKLIGHT_COMMAND\",\"_flagmask\":\"0x42\"},{\"_key\":\"0x14\",\"_flagname\":\"BUTTON1_INDICATION\",\"_flagmask\":\"0x43\"},{\"_key\":\"0x15\",\"_flagname\":\"BUTTON2_INDICATION\",\"_flagmask\":\"0x44\"},{\"_key\":\"0x16\",\"_flagname\":\"BUTTON3_INDICATION\",\"_flagmask\":\"0x45\"},{\"_key\":\"0x17\",\"_flagname\":\"BUTTON4_INDICATION\",\"_flagmask\":\"0x46\"},{\"_key\":\"0x18\",\"_flagname\":\"BUTTON5_INDICATION\",\"_flagmask\":\"0x47\"},{\"_key\":\"0x19\",\"_flagname\":\"BUTTON6_INDICATION\",\"_flagmask\":\"0x48\"},{\"_key\":\"0x1A\",\"_flagname\":\"BUTTON7_INDICATION\",\"_flagmask\":\"0x49\"},{\"_key\":\"0x1B\",\"_flagname\":\"BUTTON8_INDICATION\",\"_flagmask\":\"0x4A\"},{\"_key\":\"0x1C\",\"_flagname\":\"BUTTON9_INDICATION\",\"_flagmask\":\"0x4B\"},{\"_key\":\"0x1D\",\"_flagname\":\"BUTTON10_INDICATION\",\"_flagmask\":\"0x4C\"},{\"_key\":\"0x1E\",\"_flagname\":\"BUTTON11_INDICATION\",\"_flagmask\":\"0x4D\"},{\"_key\":\"0x1F\",\"_flagname\":\"BUTTON12_INDICATION\",\"_flagmask\":\"0x4E\"},{\"_key\":\"0x20\",\"_flagname\":\"Buzzer\",\"_flagmask\":\"0xF0\"}],\"_key\":\"0x00\",\"_name\":\"Indicator ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x02\",\"_name\":\"INDICATOR_GET\",\"_help\":\"Indicator Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Indicator 0 Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Indicator Object Count\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ARMED\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NOT_ARMED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"READY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"FAULT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ENTER_ID\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ENTER_PIN\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"OK\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"NOT_OK\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ZONE1_ARMED\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x0B\",\"_flagname\":\"ZONE2_ARMED\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x0C\",\"_flagname\":\"ZONE3_ARMED\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x0D\",\"_flagname\":\"ZONE4_ARMED\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x0E\",\"_flagname\":\"ZONE5_ARMED\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x0F\",\"_flagname\":\"ZONE6_ARMED\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x10\",\"_flagname\":\"LCD_BACKLIGHT\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x11\",\"_flagname\":\"BUTTON_BACKLIGHT_LETTERS\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x12\",\"_flagname\":\"BUTTON_BACKLIGHT_DIGITS\",\"_flagmask\":\"0x41\"},{\"_key\":\"0x13\",\"_flagname\":\"BUTTON_BACKLIGHT_COMMAND\",\"_flagmask\":\"0x42\"},{\"_key\":\"0x14\",\"_flagname\":\"BUTTON1_INDICATION\",\"_flagmask\":\"0x43\"},{\"_key\":\"0x15\",\"_flagname\":\"BUTTON2_INDICATION\",\"_flagmask\":\"0x44\"},{\"_key\":\"0x16\",\"_flagname\":\"BUTTON3_INDICATION\",\"_flagmask\":\"0x45\"},{\"_key\":\"0x17\",\"_flagname\":\"BUTTON4_INDICATION\",\"_flagmask\":\"0x46\"},{\"_key\":\"0x18\",\"_flagname\":\"BUTTON5_INDICATION\",\"_flagmask\":\"0x47\"},{\"_key\":\"0x19\",\"_flagname\":\"BUTTON6_INDICATION\",\"_flagmask\":\"0x48\"},{\"_key\":\"0x1A\",\"_flagname\":\"BUTTON7_INDICATION\",\"_flagmask\":\"0x49\"},{\"_key\":\"0x1B\",\"_flagname\":\"BUTTON8_INDICATION\",\"_flagmask\":\"0x4A\"},{\"_key\":\"0x1C\",\"_flagname\":\"BUTTON9_INDICATION\",\"_flagmask\":\"0x4B\"},{\"_key\":\"0x1D\",\"_flagname\":\"BUTTON10_INDICATION\",\"_flagmask\":\"0x4C\"},{\"_key\":\"0x1E\",\"_flagname\":\"BUTTON11_INDICATION\",\"_flagmask\":\"0x4D\"},{\"_key\":\"0x1F\",\"_flagname\":\"BUTTON12_INDICATION\",\"_flagmask\":\"0x4E\"},{\"_key\":\"0x20\",\"_flagname\":\"Buzzer\",\"_flagmask\":\"0xF0\"}],\"_key\":\"0x00\",\"_name\":\"Indicator ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Multilevel\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Binary\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"On_Off_Period\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"On_Off_Cycles\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Low_power\",\"_flagmask\":\"0x10\"}],\"_key\":\"0x01\",\"_name\":\"Property ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x02\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x01\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x03\",\"_name\":\"INDICATOR_REPORT\",\"_help\":\"Indicator Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Indicator 0 Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Indicator Object Count\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ARMED\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NOT_ARMED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"READY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"FAULT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ENTER_ID\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ENTER_PIN\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"OK\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"NOT_OK\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ZONE1_ARMED\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x0B\",\"_flagname\":\"ZONE2_ARMED\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x0C\",\"_flagname\":\"ZONE3_ARMED\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x0D\",\"_flagname\":\"ZONE4_ARMED\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x0E\",\"_flagname\":\"ZONE5_ARMED\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x0F\",\"_flagname\":\"ZONE6_ARMED\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x10\",\"_flagname\":\"LCD_BACKLIGHT\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x11\",\"_flagname\":\"BUTTON_BACKLIGHT_LETTERS\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x12\",\"_flagname\":\"BUTTON_BACKLIGHT_DIGITS\",\"_flagmask\":\"0x41\"},{\"_key\":\"0x13\",\"_flagname\":\"BUTTON_BACKLIGHT_COMMAND\",\"_flagmask\":\"0x42\"},{\"_key\":\"0x14\",\"_flagname\":\"BUTTON1_INDICATION\",\"_flagmask\":\"0x43\"},{\"_key\":\"0x15\",\"_flagname\":\"BUTTON2_INDICATION\",\"_flagmask\":\"0x44\"},{\"_key\":\"0x16\",\"_flagname\":\"BUTTON3_INDICATION\",\"_flagmask\":\"0x45\"},{\"_key\":\"0x17\",\"_flagname\":\"BUTTON4_INDICATION\",\"_flagmask\":\"0x46\"},{\"_key\":\"0x18\",\"_flagname\":\"BUTTON5_INDICATION\",\"_flagmask\":\"0x47\"},{\"_key\":\"0x19\",\"_flagname\":\"BUTTON6_INDICATION\",\"_flagmask\":\"0x48\"},{\"_key\":\"0x1A\",\"_flagname\":\"BUTTON7_INDICATION\",\"_flagmask\":\"0x49\"},{\"_key\":\"0x1B\",\"_flagname\":\"BUTTON8_INDICATION\",\"_flagmask\":\"0x4A\"},{\"_key\":\"0x1C\",\"_flagname\":\"BUTTON9_INDICATION\",\"_flagmask\":\"0x4B\"},{\"_key\":\"0x1D\",\"_flagname\":\"BUTTON10_INDICATION\",\"_flagmask\":\"0x4C\"},{\"_key\":\"0x1E\",\"_flagname\":\"BUTTON11_INDICATION\",\"_flagmask\":\"0x4D\"},{\"_key\":\"0x1F\",\"_flagname\":\"BUTTON12_INDICATION\",\"_flagmask\":\"0x4E\"},{\"_key\":\"0x20\",\"_flagname\":\"Buzzer\",\"_flagmask\":\"0xF0\"}],\"_key\":\"0x00\",\"_name\":\"Indicator ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Multilevel\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Binary\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"On_Off_Period\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"On_Off_Cycles\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Low_power\",\"_flagmask\":\"0x10\"}],\"_key\":\"0x01\",\"_name\":\"Property ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x02\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x01\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x01\",\"_name\":\"INDICATOR_SET\",\"_help\":\"Indicator Set\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ARMED\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NOT_ARMED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"READY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"FAULT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ENTER_ID\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ENTER_PIN\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"OK\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"NOT_OK\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ZONE1_ARMED\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x0B\",\"_flagname\":\"ZONE2_ARMED\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x0C\",\"_flagname\":\"ZONE3_ARMED\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x0D\",\"_flagname\":\"ZONE4_ARMED\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x0E\",\"_flagname\":\"ZONE5_ARMED\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x0F\",\"_flagname\":\"ZONE6_ARMED\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x10\",\"_flagname\":\"LCD_BACKLIGHT\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x11\",\"_flagname\":\"BUTTON_BACKLIGHT_LETTERS\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x12\",\"_flagname\":\"BUTTON_BACKLIGHT_DIGITS\",\"_flagmask\":\"0x41\"},{\"_key\":\"0x13\",\"_flagname\":\"BUTTON_BACKLIGHT_COMMAND\",\"_flagmask\":\"0x42\"},{\"_key\":\"0x14\",\"_flagname\":\"BUTTON1_INDICATION\",\"_flagmask\":\"0x43\"},{\"_key\":\"0x15\",\"_flagname\":\"BUTTON2_INDICATION\",\"_flagmask\":\"0x44\"},{\"_key\":\"0x16\",\"_flagname\":\"BUTTON3_INDICATION\",\"_flagmask\":\"0x45\"},{\"_key\":\"0x17\",\"_flagname\":\"BUTTON4_INDICATION\",\"_flagmask\":\"0x46\"},{\"_key\":\"0x18\",\"_flagname\":\"BUTTON5_INDICATION\",\"_flagmask\":\"0x47\"},{\"_key\":\"0x19\",\"_flagname\":\"BUTTON6_INDICATION\",\"_flagmask\":\"0x48\"},{\"_key\":\"0x1A\",\"_flagname\":\"BUTTON7_INDICATION\",\"_flagmask\":\"0x49\"},{\"_key\":\"0x1B\",\"_flagname\":\"BUTTON8_INDICATION\",\"_flagmask\":\"0x4A\"},{\"_key\":\"0x1C\",\"_flagname\":\"BUTTON9_INDICATION\",\"_flagmask\":\"0x4B\"},{\"_key\":\"0x1D\",\"_flagname\":\"BUTTON10_INDICATION\",\"_flagmask\":\"0x4C\"},{\"_key\":\"0x1E\",\"_flagname\":\"BUTTON11_INDICATION\",\"_flagmask\":\"0x4D\"},{\"_key\":\"0x1F\",\"_flagname\":\"BUTTON12_INDICATION\",\"_flagmask\":\"0x4E\"},{\"_key\":\"0x20\",\"_flagname\":\"Buzzer\",\"_flagmask\":\"0xF0\"}],\"_key\":\"0x00\",\"_name\":\"Indicator ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x04\",\"_name\":\"INDICATOR_SUPPORTED_GET\",\"_help\":\"Indicator Supported Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ARMED\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NOT_ARMED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"READY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"FAULT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ENTER_ID\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ENTER_PIN\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"OK\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"NOT_OK\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ZONE1_ARMED\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x0B\",\"_flagname\":\"ZONE2_ARMED\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x0C\",\"_flagname\":\"ZONE3_ARMED\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x0D\",\"_flagname\":\"ZONE4_ARMED\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x0E\",\"_flagname\":\"ZONE5_ARMED\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x0F\",\"_flagname\":\"ZONE6_ARMED\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x10\",\"_flagname\":\"LCD_BACKLIGHT\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x11\",\"_flagname\":\"BUTTON_BACKLIGHT_LETTERS\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x12\",\"_flagname\":\"BUTTON_BACKLIGHT_DIGITS\",\"_flagmask\":\"0x41\"},{\"_key\":\"0x13\",\"_flagname\":\"BUTTON_BACKLIGHT_COMMAND\",\"_flagmask\":\"0x42\"},{\"_key\":\"0x14\",\"_flagname\":\"BUTTON1_INDICATION\",\"_flagmask\":\"0x43\"},{\"_key\":\"0x15\",\"_flagname\":\"BUTTON2_INDICATION\",\"_flagmask\":\"0x44\"},{\"_key\":\"0x16\",\"_flagname\":\"BUTTON3_INDICATION\",\"_flagmask\":\"0x45\"},{\"_key\":\"0x17\",\"_flagname\":\"BUTTON4_INDICATION\",\"_flagmask\":\"0x46\"},{\"_key\":\"0x18\",\"_flagname\":\"BUTTON5_INDICATION\",\"_flagmask\":\"0x47\"},{\"_key\":\"0x19\",\"_flagname\":\"BUTTON6_INDICATION\",\"_flagmask\":\"0x48\"},{\"_key\":\"0x1A\",\"_flagname\":\"BUTTON7_INDICATION\",\"_flagmask\":\"0x49\"},{\"_key\":\"0x1B\",\"_flagname\":\"BUTTON8_INDICATION\",\"_flagmask\":\"0x4A\"},{\"_key\":\"0x1C\",\"_flagname\":\"BUTTON9_INDICATION\",\"_flagmask\":\"0x4B\"},{\"_key\":\"0x1D\",\"_flagname\":\"BUTTON10_INDICATION\",\"_flagmask\":\"0x4C\"},{\"_key\":\"0x1E\",\"_flagname\":\"BUTTON11_INDICATION\",\"_flagmask\":\"0x4D\"},{\"_key\":\"0x1F\",\"_flagname\":\"BUTTON12_INDICATION\",\"_flagmask\":\"0x4E\"},{\"_key\":\"0x20\",\"_flagname\":\"Buzzer\",\"_flagmask\":\"0xF0\"}],\"_key\":\"0x00\",\"_name\":\"Indicator ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ARMED\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NOT_ARMED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"READY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"FAULT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ENTER_ID\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ENTER_PIN\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"OK\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"NOT_OK\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ZONE1_ARMED\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x0B\",\"_flagname\":\"ZONE2_ARMED\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x0C\",\"_flagname\":\"ZONE3_ARMED\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x0D\",\"_flagname\":\"ZONE4_ARMED\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x0E\",\"_flagname\":\"ZONE5_ARMED\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x0F\",\"_flagname\":\"ZONE6_ARMED\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x10\",\"_flagname\":\"LCD_BACKLIGHT\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x11\",\"_flagname\":\"BUTTON_BACKLIGHT_LETTERS\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x12\",\"_flagname\":\"BUTTON_BACKLIGHT_DIGITS\",\"_flagmask\":\"0x41\"},{\"_key\":\"0x13\",\"_flagname\":\"BUTTON_BACKLIGHT_COMMAND\",\"_flagmask\":\"0x42\"},{\"_key\":\"0x14\",\"_flagname\":\"BUTTON1_INDICATION\",\"_flagmask\":\"0x43\"},{\"_key\":\"0x15\",\"_flagname\":\"BUTTON2_INDICATION\",\"_flagmask\":\"0x44\"},{\"_key\":\"0x16\",\"_flagname\":\"BUTTON3_INDICATION\",\"_flagmask\":\"0x45\"},{\"_key\":\"0x17\",\"_flagname\":\"BUTTON4_INDICATION\",\"_flagmask\":\"0x46\"},{\"_key\":\"0x18\",\"_flagname\":\"BUTTON5_INDICATION\",\"_flagmask\":\"0x47\"},{\"_key\":\"0x19\",\"_flagname\":\"BUTTON6_INDICATION\",\"_flagmask\":\"0x48\"},{\"_key\":\"0x1A\",\"_flagname\":\"BUTTON7_INDICATION\",\"_flagmask\":\"0x49\"},{\"_key\":\"0x1B\",\"_flagname\":\"BUTTON8_INDICATION\",\"_flagmask\":\"0x4A\"},{\"_key\":\"0x1C\",\"_flagname\":\"BUTTON9_INDICATION\",\"_flagmask\":\"0x4B\"},{\"_key\":\"0x1D\",\"_flagname\":\"BUTTON10_INDICATION\",\"_flagmask\":\"0x4C\"},{\"_key\":\"0x1E\",\"_flagname\":\"BUTTON11_INDICATION\",\"_flagmask\":\"0x4D\"},{\"_key\":\"0x1F\",\"_flagname\":\"BUTTON12_INDICATION\",\"_flagmask\":\"0x4E\"},{\"_key\":\"0x20\",\"_flagname\":\"Buzzer\",\"_flagmask\":\"0xF0\"}],\"_key\":\"0x01\",\"_name\":\"Next Indicator ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Property Supported Bit Mask Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"2\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Multilevel\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Binary\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"On_Off_Period\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"On_Off_Cycles\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Low_power\",\"_flagmask\":\"0x10\"}],\"_key\":\"0x03\",\"_name\":\"Property Supported Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x05\",\"_name\":\"INDICATOR_SUPPORTED_REPORT\",\"_help\":\"Indicator Supported Report\"}],\"_key\":\"0x87\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_INDICATOR\",\"_help\":\"Command Class Indicator\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"IP_CONFIGURATION_GET\",\"_help\":\"Ip Configuration Get\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"IP_CONFIGURATION_RELEASE\",\"_help\":\"Ip Configuration Release\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"IP_CONFIGURATION_RENEW\",\"_help\":\"Ip Configuration Renew\",\"_comment\":\"\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Auto DNS\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Auto IP\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"IP Address\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Subnet Mask\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Gateway\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"DNS1\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"DNS2\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"LeaseTime\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"IP_CONFIGURATION_REPORT\",\"_help\":\"Ip Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Auto DNS\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Auto IP\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"IP Address\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Subnet Mask\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Gateway\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"DNS1\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"DNS2\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"IP_CONFIGURATION_SET\",\"_help\":\"Ip Configuration Set\",\"_comment\":\"\"}],\"_key\":\"0x9A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_IP_CONFIGURATION\",\"_help\":\"Command Class Ip Configuration\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"LANGUAGE_GET\",\"_help\":\"Language Get\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Language\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Country\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"LANGUAGE_REPORT\",\"_help\":\"Language Report\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Language\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Country\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"LANGUAGE_SET\",\"_help\":\"Language Set\",\"_comment\":\"\"}],\"_key\":\"0x89\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_LANGUAGE\",\"_help\":\"Command Class Language\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"LOCK_GET\",\"_help\":\"Lock Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"unlocked\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"locked\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Lock State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"LOCK_REPORT\",\"_help\":\"Lock Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"unlocked\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"locked\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Lock State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"LOCK_SET\",\"_help\":\"Lock Set\",\"_comment\":\"\"}],\"_key\":\"0x76\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_LOCK\",\"_help\":\"Command Class Lock\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"_key\":\"0x91\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MANUFACTURER_PROPRIETARY\",\"_help\":\"Command Class Manufacturer Proprietary\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"MANUFACTURER_SPECIFIC_GET\",\"_help\":\"Manufacturer Specific Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Product Type ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Product ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"MANUFACTURER_SPECIFIC_REPORT\",\"_help\":\"Manufacturer Specific Report\",\"_comment\":\"\"}],\"_key\":\"0x72\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MANUFACTURER_SPECIFIC\",\"_help\":\"Command Class Manufacturer Specific\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"MANUFACTURER_SPECIFIC_GET\",\"_help\":\"Manufacturer Specific Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Product Type ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Product ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"MANUFACTURER_SPECIFIC_REPORT\",\"_help\":\"Manufacturer Specific Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Serial Number\"}],\"_key\":\"0x00\",\"_fieldname\":\"Device ID Type\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"DEVICE_SPECIFIC_GET\",\"_help\":\"Device Specific Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Serial Number\"}],\"_key\":\"0x00\",\"_fieldname\":\"Device ID Type\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Device ID Data Length Indicator\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Binary\"}],\"_key\":\"0x01\",\"_fieldname\":\"Device ID Data Format\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Device ID Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"DEVICE_SPECIFIC_REPORT\",\"_help\":\"Device Specific Report\",\"_comment\":\"\"}],\"_key\":\"0x72\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_MANUFACTURER_SPECIFIC\",\"_help\":\"Command Class Manufacturer Specific\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"_key\":\"0xEF\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MARK\",\"_help\":\"Command Class Mark\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"METER_PULSE_GET\",\"_help\":\"Meter Pulse Get\",\"_comment\":\"\"},{\"param\":{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Pulse Count\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"METER_PULSE_REPORT\",\"_help\":\"Meter Pulse Report\",\"_comment\":\"\"}],\"_key\":\"0x35\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_METER_PULSE\",\"_help\":\"Command Class Meter Pulse\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Meter Point Adm Number Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"METER_TBL_TABLE_POINT_ADM_NO_SET\",\"_help\":\"Meter Tbl Table Point Adm No Set\",\"_comment\":\"\"},\"_key\":\"0x3C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_METER_TBL_CONFIG\",\"_help\":\"Command Class Meter Tbl Config\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Operating Status\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Operating Status Event ID\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Type\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0B\",\"_name\":\"METER_TBL_STATUS_REPORT\",\"_help\":\"Meter Tbl  Status  Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Maximum Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x0A\",\"_name\":\"METER_TBL_STATUS_DATE_GET\",\"_help\":\"Meter Tbl  Status Date Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Status Event Log Depth\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"METER_TBL_STATUS_DEPTH_GET\",\"_help\":\"Meter Tbl  Status Depth Get\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"METER_TBL_STATUS_SUPPORTED_GET\",\"_help\":\"Meter Tbl  Status Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Operating Status\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Status Event Log Depth\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"METER_TBL_STATUS_SUPPORTED_REPORT\",\"_help\":\"Meter Tbl  Status Supported Report\",\"_comment\":\"\"},{\"param\":{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Dataset Requested\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"METER_TBL_CURRENT_DATA_GET\",\"_help\":\"Meter Tbl Current Data Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Current Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Current Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0D\",\"_name\":\"METER_TBL_CURRENT_DATA_REPORT\",\"_help\":\"Meter Tbl Current Data Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Maximum Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Historical Dataset Requested\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0D\",\"_name\":\"Stop Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x0E\",\"_name\":\"METER_TBL_HISTORICAL_DATA_GET\",\"_help\":\"Meter Tbl Historical Data Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Historical Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Historical Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Historical Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0F\",\"_name\":\"METER_TBL_HISTORICAL_DATA_REPORT\",\"_help\":\"Meter Tbl Historical Data Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Creditmeter\"},{\"_value\":\"Prepayment meter\"},{\"_value\":\"Prepayment meter debt\"}],\"_key\":\"0x00\",\"_fieldname\":\"Pay Meter\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset Supported\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Dataset History Supported\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Data History Supported\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"METER_TBL_REPORT\",\"_help\":\"Meter Tbl Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"METER_TBL_TABLE_CAPABILITY_GET\",\"_help\":\"Meter Tbl Table Capability Get\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"METER_TBL_TABLE_ID_GET\",\"_help\":\"Meter Tbl Table Id Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Meter ID Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"METER_TBL_TABLE_ID_REPORT\",\"_help\":\"Meter Tbl Table Id Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"METER_TBL_TABLE_POINT_ADM_NO_GET\",\"_help\":\"Meter Tbl Table Point Adm No Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Meter Point Adm Number Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"METER_TBL_TABLE_POINT_ADM_NO_REPORT\",\"_help\":\"Meter Tbl Table Point Adm No Report\",\"_comment\":\"\"}],\"_key\":\"0x3D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_METER_TBL_MONITOR\",\"_help\":\"Command Class Meter Tbl Monitor\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Operating Status\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Operating Status Event ID\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Type\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0B\",\"_name\":\"METER_TBL_STATUS_REPORT\",\"_help\":\"Meter Tbl  Status  Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Maximum Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x0A\",\"_name\":\"METER_TBL_STATUS_DATE_GET\",\"_help\":\"Meter Tbl  Status Date Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Status Event Log Depth\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"METER_TBL_STATUS_DEPTH_GET\",\"_help\":\"Meter Tbl  Status Depth Get\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"METER_TBL_STATUS_SUPPORTED_GET\",\"_help\":\"Meter Tbl  Status Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Operating Status\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Status Event Log Depth\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"METER_TBL_STATUS_SUPPORTED_REPORT\",\"_help\":\"Meter Tbl  Status Supported Report\",\"_comment\":\"\"},{\"param\":{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Dataset Requested\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"METER_TBL_CURRENT_DATA_GET\",\"_help\":\"Meter Tbl Current Data Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7C\",\"_shifter\":\"2\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Operating Status Indication\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Current Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Current Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0D\",\"_name\":\"METER_TBL_CURRENT_DATA_REPORT\",\"_help\":\"Meter Tbl Current Data Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Maximum Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Historical Dataset Requested\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0D\",\"_name\":\"Stop Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x0E\",\"_name\":\"METER_TBL_HISTORICAL_DATA_GET\",\"_help\":\"Meter Tbl Historical Data Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7C\",\"_shifter\":\"2\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Operating Status Indication\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Historical Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Historical Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Historical Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0F\",\"_name\":\"METER_TBL_HISTORICAL_DATA_REPORT\",\"_help\":\"Meter Tbl Historical Data Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Creditmeter\"},{\"_value\":\"Prepayment meter\"},{\"_value\":\"Prepayment meter debt\"}],\"_key\":\"0x00\",\"_fieldname\":\"Pay Meter\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset Supported\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Dataset History Supported\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Data History Supported\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"METER_TBL_REPORT\",\"_help\":\"Meter Tbl Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"METER_TBL_TABLE_CAPABILITY_GET\",\"_help\":\"Meter Tbl Table Capability Get\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"METER_TBL_TABLE_ID_GET\",\"_help\":\"Meter Tbl Table Id Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Meter ID Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"METER_TBL_TABLE_ID_REPORT\",\"_help\":\"Meter Tbl Table Id Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"METER_TBL_TABLE_POINT_ADM_NO_GET\",\"_help\":\"Meter Tbl Table Point Adm No Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Meter Point Adm Number Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"METER_TBL_TABLE_POINT_ADM_NO_REPORT\",\"_help\":\"Meter Tbl Table Point Adm No Report\",\"_comment\":\"\"}],\"_key\":\"0x3D\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_METER_TBL_MONITOR\",\"_help\":\"Command Class Meter Tbl Monitor\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"METER_TBL_PUSH_CONFIGURATION_GET\",\"_help\":\"Meter Tbl Push Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Operating Status Push Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"PS\",\"_flagmask\":\"0x10\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Push Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Interval Months\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Interval Days\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Interval Hours\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Interval Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x06\",\"_name\":\"Push Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x03\",\"_name\":\"METER_TBL_PUSH_CONFIGURATION_REPORT\",\"_help\":\"Meter Tbl Push Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Operating Status Push Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"PS\",\"_flagmask\":\"0x10\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Push Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Interval Months\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Interval Days\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Interval Hours\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Interval Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x06\",\"_name\":\"Push Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x01\",\"_name\":\"METER_TBL_PUSH_CONFIGURATION_SET\",\"_help\":\"Meter Tbl Push Configuration Set\",\"_comment\":\"\"}],\"_key\":\"0x3E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_METER_TBL_PUSH\",\"_help\":\"Command Class Meter Tbl Push\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"METER_GET\",\"_help\":\"Meter Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Electric meter\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Gas meter\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Water meter\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x00\",\"_name\":\"Meter Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"METER_REPORT\",\"_help\":\"Meter Report\",\"_comment\":\"\"}],\"_key\":\"0x32\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_METER\",\"_help\":\"Command Class Meter\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"METER_GET\",\"_help\":\"Meter Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Delta Time\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Previous Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"METER_REPORT\",\"_help\":\"Meter Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"METER_RESET\",\"_help\":\"Meter Reset\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"METER_SUPPORTED_GET\",\"_help\":\"Meter Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Meter Reset\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale Supported\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"METER_SUPPORTED_REPORT\",\"_help\":\"Meter Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x32\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_METER\",\"_help\":\"Command Class Meter\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"METER_GET\",\"_help\":\"Meter Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Scale bit 2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale bits 10\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Delta Time\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Previous Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"METER_REPORT\",\"_help\":\"Meter Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"METER_RESET\",\"_help\":\"Meter Reset\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"METER_SUPPORTED_GET\",\"_help\":\"Meter Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Meter Reset\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Scale Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"METER_SUPPORTED_REPORT\",\"_help\":\"Meter Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x32\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_METER\",\"_help\":\"Command Class Meter\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Import\"},{\"_value\":\"Export\"},{\"_value\":\"Not to be used\"}],\"_key\":\"0x02\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Scale 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"METER_GET\",\"_help\":\"Meter Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":[{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Electric meter\"},{\"_value\":\"Gas meter\"},{\"_value\":\"Water meter\"}],\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Import\"},{\"_value\":\"Export\"},{\"_value\":\"Not to be used\"}],\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Scale bit 2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale bits 10\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Delta Time\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Previous Meter Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_optionaloffs\":\"0x03\",\"_optionalmask\":\"0xFF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Scale 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x02\",\"_name\":\"METER_REPORT\",\"_help\":\"Meter Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"METER_RESET\",\"_help\":\"Meter Reset\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"METER_SUPPORTED_GET\",\"_help\":\"Meter Supported Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":[{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Electric meter\"},{\"_value\":\"Gas meter\"},{\"_value\":\"Water meter\"}],\"_key\":\"0x00\",\"_fieldname\":\"Meter Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Import only\"},{\"_value\":\"Export only\"},{\"_value\":\"Import and Export\"}],\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Meter Reset\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Scale Supported 0\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"M.S.T\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of Scale Supported Bytes to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Scale Supported\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"METER_SUPPORTED_REPORT\",\"_help\":\"Meter Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x32\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_METER\",\"_help\":\"Command Class Meter\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"MOVE_TO_POSITION_GET\",\"_help\":\"Move To Position Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"close\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"open\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"MOVE_TO_POSITION_REPORT\",\"_help\":\"Move To Position Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"close\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"open\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"MOVE_TO_POSITION_SET\",\"_help\":\"Move To Position Set\",\"_comment\":\"\"}],\"_key\":\"0x51\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MTP_WINDOW_COVERING\",\"_help\":\"Command Class Mtp Window Covering\",\"_read_only\":\"false\",\"_comment\":\"OBSOLETED\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_GET\",\"_help\":\"Multi Channel Association Get\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_GROUPINGS_GET\",\"_help\":\"Multi Channel Association Groupings Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Groupings\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_GROUPINGS_REPORT\",\"_help\":\"Multi Channel Association Groupings Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Channel Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_REMOVE\",\"_help\":\"Multi Channel Association Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Max Nodes Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x04\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Channel Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_REPORT\",\"_help\":\"Multi Channel Association Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Channel Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_SET\",\"_help\":\"Multi Channel Association Set\",\"_comment\":\"\"}],\"_key\":\"0x8E\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION\",\"_help\":\"Command Class Multi Channel Association\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_GET\",\"_help\":\"Multi Channel Association Get\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_GROUPINGS_GET\",\"_help\":\"Multi Channel Association Groupings Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Groupings\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_GROUPINGS_REPORT\",\"_help\":\"Multi Channel Association Groupings Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Channel Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_REMOVE\",\"_help\":\"Multi Channel Association Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Max Nodes Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x04\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Channel Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_REPORT\",\"_help\":\"Multi Channel Association Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Channel Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"MULTI_CHANNEL_ASSOCIATION_SET\",\"_help\":\"Multi Channel Association Set\",\"_comment\":\"\"}],\"_key\":\"0x8E\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION\",\"_help\":\"Command Class Multi Channel Association\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"MULTI_CHANNEL_CAPABILITY_GET\",\"_help\":\"Multi Channel Capability Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"}],\"_key\":\"0x0A\",\"_name\":\"MULTI_CHANNEL_CAPABILITY_REPORT\",\"_help\":\"Multi Channel Capability Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Source End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Destination End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x0D\",\"_name\":\"MULTI_CHANNEL_CMD_ENCAP\",\"_help\":\"Multi Channel Cmd Encap\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"}],\"_key\":\"0x0B\",\"_name\":\"MULTI_CHANNEL_END_POINT_FIND\",\"_help\":\"Multi Channel End Point Find\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"}],\"variant_group\":{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"MULTI_CHANNEL_END_POINT_FIND_REPORT\",\"_help\":\"Multi Channel End Point Find Report\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"MULTI_CHANNEL_END_POINT_GET\",\"_help\":\"Multi Channel End Point Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Identical\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Points\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"MULTI_CHANNEL_END_POINT_REPORT\",\"_help\":\"Multi Channel End Point Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Instance\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x06\",\"_name\":\"MULTI_INSTANCE_CMD_ENCAP\",\"_help\":\"Multi Instance Cmd Encap\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},\"_key\":\"0x04\",\"_name\":\"MULTI_INSTANCE_GET\",\"_help\":\"Multi Instance Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Instances\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"MULTI_INSTANCE_REPORT\",\"_help\":\"Multi Instance Report\",\"_comment\":\"\"}],\"_key\":\"0x60\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL\",\"_help\":\"Command Class Multi Channel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"MULTI_CHANNEL_CAPABILITY_GET\",\"_help\":\"Multi Channel Capability Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"}],\"_key\":\"0x0A\",\"_name\":\"MULTI_CHANNEL_CAPABILITY_REPORT\",\"_help\":\"Multi Channel Capability Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Source End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Destination End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x0D\",\"_name\":\"MULTI_CHANNEL_CMD_ENCAP\",\"_help\":\"Multi Channel Cmd Encap\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"}],\"_key\":\"0x0B\",\"_name\":\"MULTI_CHANNEL_END_POINT_FIND\",\"_help\":\"Multi Channel End Point Find\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"}],\"variant_group\":{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"MULTI_CHANNEL_END_POINT_FIND_REPORT\",\"_help\":\"Multi Channel End Point Find Report\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"MULTI_CHANNEL_END_POINT_GET\",\"_help\":\"Multi Channel End Point Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Identical\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Points\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"MULTI_CHANNEL_END_POINT_REPORT\",\"_help\":\"Multi Channel End Point Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Instance\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x06\",\"_name\":\"MULTI_INSTANCE_CMD_ENCAP\",\"_help\":\"Multi Instance Cmd Encap\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},\"_key\":\"0x04\",\"_name\":\"MULTI_INSTANCE_GET\",\"_help\":\"Multi Instance Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Instances\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"MULTI_INSTANCE_REPORT\",\"_help\":\"Multi Instance Report\",\"_comment\":\"\"}],\"_key\":\"0x60\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL\",\"_help\":\"Command Class Multi Channel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"MULTI_CHANNEL_CAPABILITY_GET\",\"_help\":\"Multi Channel Capability Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"}],\"_key\":\"0x0A\",\"_name\":\"MULTI_CHANNEL_CAPABILITY_REPORT\",\"_help\":\"Multi Channel Capability Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Source End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Destination End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x0D\",\"_name\":\"MULTI_CHANNEL_CMD_ENCAP\",\"_help\":\"Multi Channel Cmd Encap\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"}],\"_key\":\"0x0B\",\"_name\":\"MULTI_CHANNEL_END_POINT_FIND\",\"_help\":\"Multi Channel End Point Find\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"}],\"variant_group\":{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"MULTI_CHANNEL_END_POINT_FIND_REPORT\",\"_help\":\"Multi Channel End Point Find Report\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"MULTI_CHANNEL_END_POINT_GET\",\"_help\":\"Multi Channel End Point Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Identical\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Individual End Points\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Aggregated End Points\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res3\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"MULTI_CHANNEL_END_POINT_REPORT\",\"_help\":\"Multi Channel End Point Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Instance\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x06\",\"_name\":\"MULTI_INSTANCE_CMD_ENCAP\",\"_help\":\"Multi Instance Cmd Encap\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},\"_key\":\"0x04\",\"_name\":\"MULTI_INSTANCE_GET\",\"_help\":\"Multi Instance Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Instances\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"MULTI_INSTANCE_REPORT\",\"_help\":\"Multi Instance Report\",\"_comment\":\"\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Aggregated End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x0E\",\"_name\":\"MULTI_CHANNEL_AGGREGATED_MEMBERS_GET\",\"_help\":\"Multi Channel Aggregated Members Get\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Aggregated End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Number of Bit Masks\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"1\",\"_lenmask\":\"0xFF\",\"_lenoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Aggregated Members Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x0F\",\"_name\":\"MULTI_CHANNEL_AGGREGATED_MEMBERS_REPORT\",\"_help\":\"Multi Channel Aggregated Members Report\"}],\"_key\":\"0x60\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL\",\"_help\":\"Command Class Multi Channel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Commands\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\",\"_sizechange\":\"-2\"},\"_key\":\"0x03\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x01\",\"_name\":\"Encapsulated_Command\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x01\",\"_name\":\"MULTI_CMD_ENCAP\",\"_help\":\"Multi Cmd Encap\",\"_comment\":\"\"},\"_key\":\"0x8F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MULTI_CMD\",\"_help\":\"Command Class Multi Cmd\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"MULTI_INSTANCE_ASSOCIATION_GET\",\"_help\":\"Multi Instance Association Get\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"MULTI_INSTANCE_ASSOCIATION_GROUPINGS_GET\",\"_help\":\"Multi Instance Association Groupings Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Groupings\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"MULTI_INSTANCE_ASSOCIATION_GROUPINGS_REPORT\",\"_help\":\"Multi Instance Association Groupings Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Instance Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Instance\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"MULTI_INSTANCE_ASSOCIATION_REMOVE\",\"_help\":\"Multi Instance Association Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Max Nodes Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x04\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Instance Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Instance\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"MULTI_INSTANCE_ASSOCIATION_REPORT\",\"_help\":\"Multi Instance Association Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"Marker\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Marker\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"This marker identifier is used to separate between nodes without and with end points attached. This field can be omitted in case no Multi Channel node follows.\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Multi Instance Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Instance\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"MULTI_INSTANCE_ASSOCIATION_SET\",\"_help\":\"Multi Instance Association Set\",\"_comment\":\"\"}],\"_key\":\"0x8E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION\",\"_help\":\"Command Class Multi Instance Association\",\"_read_only\":\"false\",\"_comment\":\"Discontinued\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Instance\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_REF\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Parameter\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_DATA\"}],\"_key\":\"0x06\",\"_name\":\"MULTI_INSTANCE_CMD_ENCAP\",\"_help\":\"Multi Instance Cmd Encap\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},\"_key\":\"0x04\",\"_name\":\"MULTI_INSTANCE_GET\",\"_help\":\"Multi Instance Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Instances\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"MULTI_INSTANCE_REPORT\",\"_help\":\"Multi Instance Report\",\"_comment\":\"\"}],\"_key\":\"0x60\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MULTI_INSTANCE\",\"_help\":\"Command Class Multi Instance\",\"_read_only\":\"false\",\"_comment\":\"Discontinued\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Max Age\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x03\",\"_name\":\"NODE_INFO_CACHED_GET\",\"_help\":\"Node Info Cached Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Age\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"STATUS_OK\"},{\"_value\":\"STATUS_NOT_RESPONDING\"},{\"_value\":\"STATUS_UNKNOWN\"}],\"_key\":\"0x01\",\"_fieldname\":\"Status\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Capability\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Listening\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Security\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Sensor\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Opt\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Basic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x08\",\"_name\":\"Non-Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Security Scheme 0 MARK\",\"_flagmask\":\"0xF1\"},{\"_key\":\"0x01\",\"_flagname\":\"Security Scheme 0 MARK\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x09\",\"_name\":\"Security Scheme 0 MARK\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Security Scheme 0 Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x04\",\"_name\":\"NODE_INFO_CACHED_REPORT\",\"_help\":\"Node Info Cached Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"NODE_LIST_GET\",\"_help\":\"Node List Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"false\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Latest\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"May not be the latest\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Node List Controller ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Node List Data\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"NODE_LIST_REPORT\",\"_help\":\"Node List Report\",\"_comment\":\"\"}],\"_key\":\"0x52\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_PROXY\",\"_help\":\"Command Class Network Management Proxy\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Max Age\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x03\",\"_name\":\"NODE_INFO_CACHED_GET\",\"_help\":\"Node Info Cached Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Age\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"STATUS_OK\"},{\"_value\":\"STATUS_NOT_RESPONDING\"},{\"_value\":\"STATUS_UNKNOWN\"}],\"_key\":\"0x01\",\"_fieldname\":\"Status\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Capability\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Listening\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Security\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Sensor\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Opt\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Granted Keys\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Basic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x08\",\"_name\":\"Non-Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Security MARK\",\"_flagmask\":\"0xF1\"},{\"_key\":\"0x01\",\"_flagname\":\"Security MARK\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x09\",\"_name\":\"Security MARK\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x04\",\"_name\":\"NODE_INFO_CACHED_REPORT\",\"_help\":\"Node Info Cached Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"NODE_LIST_GET\",\"_help\":\"Node List Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"false\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Latest\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"May not be the latest\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Node List Controller ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Node List Data\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"NODE_LIST_REPORT\",\"_help\":\"Node List Report\",\"_comment\":\"\"}],\"_key\":\"0x52\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_PROXY\",\"_help\":\"Command Class Network Management Proxy\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"LEARN_MODE_SET_CLASSIC\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"LEARN_MODE_SET_NWI\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"LEARN_MODE_SET_DISABLE\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"LEARN_MODE_SET\",\"_help\":\"Learn Mode Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"LEARN_MODE_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"LEARN_MODE_FAILED_TIMEOUT\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"LEARN_MODE_FAILED\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x04\",\"_flagname\":\"LEARN_MODE_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"New Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x02\",\"_name\":\"LEARN_MODE_SET_STATUS\",\"_help\":\"Learn Mode Set Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Destination Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"NODE_INFORMATION_SEND\",\"_help\":\"Node Information Send\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x03\",\"_name\":\"NETWORK_UPDATE_REQUEST\",\"_help\":\"Network Update Request\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"SUC_UPDATE_DONE\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"SUC_UPDATE_ABORT\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"SUC_UPDATE_WAIT\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"SUC_UPDATE_DISABLED\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"SUC_UPDATE_OVERFLOW\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NETWORK_UPDATE_REQUEST_STATUS\",\"_help\":\"Network Update Request Status\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x06\",\"_name\":\"DEFAULT_SET\",\"_help\":\"Default Set\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"DEFAULT_SET_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"DEFAULT_SET_BUSY\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x07\",\"_name\":\"DEFAULT_SET_COMPLETE\",\"_help\":\"Default Set Complete\"}],\"_key\":\"0x4D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_BASIC\",\"_help\":\"Command Class Network Management Basic\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"LEARN_MODE_SET_CLASSIC\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"LEARN_MODE_SET_NWI\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"LEARN_MODE_SET_DISABLE\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"LEARN_MODE_SET\",\"_help\":\"Learn Mode Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"LEARN_MODE_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"LEARN_MODE_FAILED_TIMEOUT\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"LEARN_MODE_FAILED\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x04\",\"_flagname\":\"LEARN_MODE_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"New Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Granted Keys\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"DSK\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x02\",\"_name\":\"LEARN_MODE_SET_STATUS\",\"_help\":\"Learn Mode Set Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Destination Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"NODE_INFORMATION_SEND\",\"_help\":\"Node Information Send\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x03\",\"_name\":\"NETWORK_UPDATE_REQUEST\",\"_help\":\"Network Update Request\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"SUC_UPDATE_DONE\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"SUC_UPDATE_ABORT\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"SUC_UPDATE_WAIT\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"SUC_UPDATE_DISABLED\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"SUC_UPDATE_OVERFLOW\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"NETWORK_UPDATE_REQUEST_STATUS\",\"_help\":\"Network Update Request Status\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x06\",\"_name\":\"DEFAULT_SET\",\"_help\":\"Default Set\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"DEFAULT_SET_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"DEFAULT_SET_BUSY\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x07\",\"_name\":\"DEFAULT_SET_COMPLETE\",\"_help\":\"Default Set Complete\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x08\",\"_name\":\"DSK_GET\",\"_help\":\"DSK Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"DSK\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x09\",\"_name\":\"DSK_REPORT\",\"_help\":\"DSK Report\"}],\"_key\":\"0x4D\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_BASIC\",\"_help\":\"Command Class Network Management Basic\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x07\",\"_name\":\"FAILED_NODE_REMOVE\",\"_help\":\"Failed Node Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"DONE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"FAILED_NODE_NOT_FOUND\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x03\",\"_flagname\":\"FAILED_NODE_REMOVE_FAIL\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x02\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x08\",\"_name\":\"FAILED_NODE_REMOVE_STATUS\",\"_help\":\"Failed Node Remove Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_ADD_ANY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_ADD_CONTROLLER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_ADD_SLAVE\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"NODE_ADD_EXISTING\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"NODE_ADD_STOP\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"NODE_ADD_STOP_FAILED\",\"_flagmask\":\"0x06\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"NODE_ADD\",\"_help\":\"Node Add\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_ADD_STATUS_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_ADD_STATUS_FAILED\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_ADD_STATUS_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"New Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Node Info Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Capability\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Listening\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Security\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Opt\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Basic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"NODE_ADD_STATUS\",\"_help\":\"Node Add Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_REMOVE_ANY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_REMOVE_CONTROLLER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_REMOVE_SLAVE\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"NODE_REMOVE_STOP\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"NODE_REMOVE\",\"_help\":\"Node Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_REMOVE_STATUS_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_REMOVE_STATUS_FAILED\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"NODE_REMOVE_STATUS\",\"_help\":\"Node Remove Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x02\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x09\",\"_name\":\"FAILED_NODE_REPLACE\",\"_help\":\"Failed Node Replace\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"DONE\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x02\",\"_flagname\":\"FAILED_NODE_REPLACE_FAIL\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x03\",\"_flagname\":\"FAILED_NODE_REPLACE_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0A\",\"_name\":\"FAILED_NODE_REPLACE_STATUS\",\"_help\":\"Failed Node Replace Status\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0B\",\"_name\":\"NODE_NEIGHBOR_UPDATE_REQUEST\",\"_help\":\"Node Neighbor Update Request\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NEIGHBOR_UPDATE_STATUS_DONE\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x02\",\"_flagname\":\"NEIGHBOR_UPDATE_STATUS_FAIL\",\"_flagmask\":\"0x23\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0C\",\"_name\":\"NODE_NEIGHBOR_UPDATE_STATUS\",\"_help\":\"Node Neighbor Update Status\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Source Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Destination Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0D\",\"_name\":\"RETURN_ROUTE_ASSIGN\",\"_help\":\"Return Route Assign\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"TRANSMIT_COMPLETE_OK\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"TRANSMIT_COMPLETE_NO_ACK\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"TRANSMIT_COMPLETE_FAIL\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0E\",\"_name\":\"RETURN_ROUTE_ASSIGN_COMPLETE\",\"_help\":\"Return Route Assign Complete\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0F\",\"_name\":\"RETURN_ROUTE_DELETE\",\"_help\":\"Return Route Delete\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"TRANSMIT_COMPLETE_OK\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"TRANSMIT_COMPLETE_NO_ACK\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"TRANSMIT_COMPLETE_FAIL\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x10\",\"_name\":\"RETURN_ROUTE_DELETE_COMPLETE\",\"_help\":\"Return Route Delete Complete\"}],\"_key\":\"0x34\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_INCLUSION\",\"_help\":\"Command Class Network Management Inclusion\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x07\",\"_name\":\"FAILED_NODE_REMOVE\",\"_help\":\"Failed Node Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"DONE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"FAILED_NODE_NOT_FOUND\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x03\",\"_flagname\":\"FAILED_NODE_REMOVE_FAIL\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x02\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x08\",\"_name\":\"FAILED_NODE_REMOVE_STATUS\",\"_help\":\"Failed Node Remove Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_ADD_ANY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_ADD_CONTROLLER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_ADD_SLAVE\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"NODE_ADD_EXISTING\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"NODE_ADD_STOP\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"NODE_ADD_STOP_FAILED\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"NODE_ADD_ANY_S2\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"NODE_ADD\",\"_help\":\"Node Add\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_ADD_STATUS_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_ADD_STATUS_FAILED\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_ADD_STATUS_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"New Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Node Info Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Capability\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Listening\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Security\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Opt\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Basic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Non-Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Security MARK\",\"_flagmask\":\"0xF1\"},{\"_key\":\"0x01\",\"_flagname\":\"Security MARK\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x0B\",\"_name\":\"Security MARK\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0C\",\"_name\":\"Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0D\",\"_name\":\"Granted Keys\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0E\",\"_name\":\"KEX Fail Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x02\",\"_name\":\"NODE_ADD_STATUS\",\"_help\":\"Node Add Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_REMOVE_ANY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_REMOVE_CONTROLLER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_REMOVE_SLAVE\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"NODE_REMOVE_STOP\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"NODE_REMOVE\",\"_help\":\"Node Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_REMOVE_STATUS_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_REMOVE_STATUS_FAILED\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"NODE_REMOVE_STATUS\",\"_help\":\"Node Remove Status\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x02\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x09\",\"_name\":\"FAILED_NODE_REPLACE\",\"_help\":\"Failed Node Replace\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"DONE\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x02\",\"_flagname\":\"FAILED_NODE_REPLACE_FAIL\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x03\",\"_flagname\":\"FAILED_NODE_REPLACE_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Granted Keys\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"KEX Fail Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0A\",\"_name\":\"FAILED_NODE_REPLACE_STATUS\",\"_help\":\"Failed Node Replace Status\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0B\",\"_name\":\"NODE_NEIGHBOR_UPDATE_REQUEST\",\"_help\":\"Node Neighbor Update Request\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NEIGHBOR_UPDATE_STATUS_DONE\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x02\",\"_flagname\":\"NEIGHBOR_UPDATE_STATUS_FAIL\",\"_flagmask\":\"0x23\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0C\",\"_name\":\"NODE_NEIGHBOR_UPDATE_STATUS\",\"_help\":\"Node Neighbor Update Status\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Source Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Destination Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0D\",\"_name\":\"RETURN_ROUTE_ASSIGN\",\"_help\":\"Return Route Assign\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"TRANSMIT_COMPLETE_OK\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"TRANSMIT_COMPLETE_NO_ACK\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"TRANSMIT_COMPLETE_FAIL\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0E\",\"_name\":\"RETURN_ROUTE_ASSIGN_COMPLETE\",\"_help\":\"Return Route Assign Complete\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x0F\",\"_name\":\"RETURN_ROUTE_DELETE\",\"_help\":\"Return Route Delete\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"TRANSMIT_COMPLETE_OK\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"TRANSMIT_COMPLETE_NO_ACK\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"TRANSMIT_COMPLETE_FAIL\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x10\",\"_name\":\"RETURN_ROUTE_DELETE_COMPLETE\",\"_help\":\"Return Route Delete Complete\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Request Client-Side Authentication\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Requested Keys\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x11\",\"_name\":\"NODE_ADD_KEYS_REPORT\",\"_help\":\"Node Add Keys Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Accept\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Grant Client-Side Authentication\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Granted Keys\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x12\",\"_name\":\"NODE_ADD_KEYS_SET\",\"_help\":\"Node Add Keys Set\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Input DSK Length\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"DSK\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x13\",\"_name\":\"NODE_ADD_DSK_REPORT\",\"_help\":\"Node Add DSK Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Input DSK Length\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Accept\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x0F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Input DSK\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x14\",\"_name\":\"NODE_ADD_DSK_SET\",\"_help\":\"Node Add DSK Set\"}],\"_key\":\"0x34\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_INCLUSION\",\"_help\":\"Command Class Network Management Inclusion\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"_key\":\"0x00\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NO_OPERATION\",\"_help\":\"NOP\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Node location char\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"NODE_NAMING_NODE_LOCATION_REPORT\",\"_help\":\"Node Naming Node Location  Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Node location char\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"NODE_NAMING_NODE_LOCATION_SET\",\"_help\":\"Node Naming Node Location  Set\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"NODE_NAMING_NODE_LOCATION_GET\",\"_help\":\"Node Naming Node Location Get\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"NODE_NAMING_NODE_NAME_GET\",\"_help\":\"Node Naming Node Name Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Node name char\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"NODE_NAMING_NODE_NAME_REPORT\",\"_help\":\"Node Naming Node Name Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Node name char\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"NODE_NAMING_NODE_NAME_SET\",\"_help\":\"Node Naming Node Name Set\",\"_comment\":\"\"}],\"_key\":\"0x77\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NODE_NAMING\",\"_help\":\"Command Class Node Naming\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"_key\":\"0xF0\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NON_INTEROPERABLE\",\"_help\":\"Command Class Non Interoperable\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"POWERLEVEL_GET\",\"_help\":\"Powerlevel Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NormalPower\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"minus1dBm\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"minus2dBm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"minus3dBm\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"minus4dBm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"minus5dBm\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"minus6dBm\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"minus7dBm\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"minus8dBm\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"minus9dBm\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x00\",\"_name\":\"Power level\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"POWERLEVEL_REPORT\",\"_help\":\"Powerlevel Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NormalPower\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"minus1dBm\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"minus2dBm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"minus3dBm\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"minus4dBm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"minus5dBm\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"minus6dBm\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"minus7dBm\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"minus8dBm\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"minus9dBm\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x00\",\"_name\":\"Power level\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"POWERLEVEL_SET\",\"_help\":\"Powerlevel Set\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"POWERLEVEL_TEST_NODE_GET\",\"_help\":\"Powerlevel Test Node Get\",\"_comment\":\"\"},{\"param\":[{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"ZW_TEST_NOT_A_NODEID\",\"_flagmask\":\"0x00\"},\"_key\":\"0x00\",\"_name\":\"Test NodeID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"ZW_TEST_FAILED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ZW_TEST_SUCCES\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"ZW_TEST_INPROGRESS\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Status of operation\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Test Frame Count\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"POWERLEVEL_TEST_NODE_REPORT\",\"_help\":\"Powerlevel Test Node Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Test NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NormalPower\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"minus1dBm\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"minus2dBm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"minus3dBm\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"minus4dBm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"minus5dBm\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"minus6dBm\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"minus7dBm\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"minus8dBm\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"minus9dBm\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Power level\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Test frame count\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"POWERLEVEL_TEST_NODE_SET\",\"_help\":\"Powerlevel Test Node Set\",\"_comment\":\"\"}],\"_key\":\"0x73\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_POWERLEVEL\",\"_help\":\"Command Class Powerlevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"CMD_ENCAPSULATION\",\"_help\":\"Cmd Encapsulation\",\"_comment\":\"\"},\"_key\":\"0x41\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_PREPAYMENT_ENCAPSULATION\",\"_help\":\"Command Class Prepayment Encapsulation\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Utility\"},{\"_value\":\"Monetary\"}],\"_key\":\"0x01\",\"_fieldname\":\"Balance Type\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"PREPAYMENT_BALANCE_GET\",\"_help\":\"Prepayment Balance Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Meter type\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Balance Type\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Balance Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Balance Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Debt Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Debt\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Emer Credit Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x05\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Emer Credit\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Currency\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Debt Recovery Percentage\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"PREPAYMENT_BALANCE_REPORT\",\"_help\":\"Prepayment Balance Report\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"PREPAYMENT_SUPPORTED_GET\",\"_help\":\"Prepayment Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Types Supported\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"PREPAYMENT_SUPPORTED_REPORT\",\"_help\":\"Prepayment Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x3F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_PREPAYMENT\",\"_help\":\"Command Class Prepayment\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"PROPRIETARY_GET\",\"_help\":\"Proprietary Get\",\"_comment\":\"\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"PROPRIETARY_REPORT\",\"_help\":\"Proprietary Report\",\"_comment\":\"\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"PROPRIETARY_SET\",\"_help\":\"Proprietary Set\",\"_comment\":\"\"}],\"_key\":\"0x88\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_PROPRIETARY\",\"_help\":\"Command Class Proprietary\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"PROTECTION_GET\",\"_help\":\"Protection Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Unprotected\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Protection by sequence\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"No operation possible\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Protection State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"PROTECTION_REPORT\",\"_help\":\"Protection Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Unprotected\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Protection by sequence\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"No operation possible\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Protection State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"PROTECTION_SET\",\"_help\":\"Protection Set\",\"_comment\":\"\"}],\"_key\":\"0x75\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_PROTECTION\",\"_help\":\"Command Class Protection\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x07\",\"_name\":\"PROTECTION_EC_GET\",\"_help\":\"Protection Ec Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},\"_key\":\"0x08\",\"_name\":\"PROTECTION_EC_REPORT\",\"_help\":\"Protection Ec Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},\"_key\":\"0x06\",\"_name\":\"PROTECTION_EC_SET\",\"_help\":\"Protection Ec Set\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"PROTECTION_GET\",\"_help\":\"Protection Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Local Protection State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"RF Protection State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"PROTECTION_REPORT\",\"_help\":\"Protection Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Local Protection State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"RF Protection State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"PROTECTION_SET\",\"_help\":\"Protection Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"PROTECTION_SUPPORTED_GET\",\"_help\":\"Protection Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Timeout\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Exclusive Control\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Local Protection State\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"RF Protection State\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"PROTECTION_SUPPORTED_REPORT\",\"_help\":\"Protection Supported Report\",\"_comment\":\"\"},{\"_key\":\"0x0A\",\"_name\":\"PROTECTION_TIMEOUT_GET\",\"_help\":\"Protection Timeout Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"No timer is set\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"No Timeout is set\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x0B\",\"_name\":\"PROTECTION_TIMEOUT_REPORT\",\"_help\":\"Protection Timeout Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"No timer is set\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"No Timeout \",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"PROTECTION_TIMEOUT_SET\",\"_help\":\"Protection Timeout Set\",\"_comment\":\"\"}],\"_key\":\"0x75\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_PROTECTION\",\"_help\":\"Command Class Protection\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Parameter Set IDs\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"RATE_TBL_REMOVE\",\"_help\":\"Rate Tbl Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Rate Char\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Rate Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Duration Minute\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Consumption Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Consumption Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Min Consumption Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Max Consumption Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Max Demand Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Max Demand Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x09\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Max Demand Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"DCP Rate ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"RATE_TBL_SET\",\"_help\":\"Rate Tbl Set\",\"_comment\":\"\"}],\"_key\":\"0x48\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_RATE_TBL_CONFIG\",\"_help\":\"Command Class Rate Tbl Config\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"RATE_TBL_ACTIVE_RATE_GET\",\"_help\":\"Rate Tbl Active Rate  Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"RATE_TBL_ACTIVE_RATE_REPORT\",\"_help\":\"Rate Tbl Active Rate  Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Dataset Requested\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"RATE_TBL_CURRENT_DATA_GET\",\"_help\":\"Rate Tbl Current Data Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Current Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Current Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x08\",\"_name\":\"RATE_TBL_CURRENT_DATA_REPORT\",\"_help\":\"Rate Tbl Current Data Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"RATE_TBL_GET\",\"_help\":\"Rate Tbl Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Maximum Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset Requested\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Start Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0D\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0E\",\"_name\":\"Stop Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"RATE_TBL_HISTORICAL_DATA_GET\",\"_help\":\"Rate Tbl Historical Data Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dataset\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Historical Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Historical Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Historical Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x0A\",\"_name\":\"RATE_TBL_HISTORICAL_DATA_REPORT\",\"_help\":\"Rate Tbl Historical Data Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Rate Char\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Rate Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Duration Minute\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Consumption Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Consumption Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Min Consumption Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Max Consumption Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Max Demand Scale\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Max Demand Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x09\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Max Demand Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"DCP Rate ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"RATE_TBL_REPORT\",\"_help\":\"Rate Tbl Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"RATE_TBL_SUPPORTED_GET\",\"_help\":\"Rate Tbl Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rates Supported\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Parameter Set Supported Bit Mask\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"RATE_TBL_SUPPORTED_REPORT\",\"_help\":\"Rate Tbl Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x49\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_RATE_TBL_MONITOR\",\"_help\":\"Command Class Rate Tbl Monitor\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"REMOTE_ASSOCIATION_ACTIVATE\",\"_help\":\"Remote Association Activate\",\"_comment\":\"\"},\"_key\":\"0x7C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_REMOTE_ASSOCIATION_ACTIVATE\",\"_help\":\"Command Class Remote Association Activate\",\"_read_only\":\"false\",\"_comment\":\"OBSOLETED\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Local Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"REMOTE_ASSOCIATION_CONFIGURATION_GET\",\"_help\":\"Remote Association Configuration Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"erase all lin\",\"_flagmask\":\"0x00\"},\"_key\":\"0x00\",\"_name\":\"Local Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"false\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"remove a link\",\"_flagmask\":\"0x00\"},\"_key\":\"0x01\",\"_name\":\"Remote NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Remote Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"REMOTE_ASSOCIATION_CONFIGURATION_REPORT\",\"_help\":\"Remote Association Configuration Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"erase all lin\",\"_flagmask\":\"0x00\"},\"_key\":\"0x00\",\"_name\":\"Local Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"false\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"remove a link\",\"_flagmask\":\"0x00\"},\"_key\":\"0x01\",\"_name\":\"Remote NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Remote Grouping identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"REMOTE_ASSOCIATION_CONFIGURATION_SET\",\"_help\":\"Remote Association Configuration Set\",\"_comment\":\"\"}],\"_key\":\"0x7D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_REMOTE_ASSOCIATION\",\"_help\":\"Command Class Remote Association\",\"_read_only\":\"false\",\"_comment\":\"OBSOLETED\"},{\"cmd\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"configured dimming duration\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCENE_ACTIVATION_SET\",\"_help\":\"Scene Activation Set\",\"_comment\":\"\"},\"_key\":\"0x2B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCENE_ACTIVATION\",\"_help\":\"Command Class Scene Activation\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCENE_ACTUATOR_CONF_GET\",\"_help\":\"Scene Actuator Conf Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCENE_ACTUATOR_CONF_REPORT\",\"_help\":\"Scene Actuator Conf Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Specify Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"factory default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Override\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCENE_ACTUATOR_CONF_SET\",\"_help\":\"Scene Actuator Conf Set\",\"_comment\":\"\"}],\"_key\":\"0x2C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCENE_ACTUATOR_CONF\",\"_help\":\"Command Class Scene Actuator Conf\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Group ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCENE_CONTROLLER_CONF_GET\",\"_help\":\"Scene Controller Conf Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Group ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},\"_key\":\"0x02\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCENE_CONTROLLER_CONF_REPORT\",\"_help\":\"Scene Controller Conf Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Group ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Scene ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"factory default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x02\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCENE_CONTROLLER_CONF_SET\",\"_help\":\"Scene Controller Conf Set\",\"_comment\":\"\"}],\"_key\":\"0x2D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCENE_CONTROLLER_CONF\",\"_help\":\"Command Class Scene Controller Conf\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"disabled\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"enabled\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Enabled\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_ENTRY_LOCK_ENABLE_ALL_SET\",\"_help\":\"Schedule Entry Lock Enable All Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"disabled\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"enabled\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"Enabled\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCHEDULE_ENTRY_LOCK_ENABLE_SET\",\"_help\":\"Schedule Entry Lock Enable Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_GET\",\"_help\":\"Schedule Entry Lock Week Day Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day of Week\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_REPORT\",\"_help\":\"Schedule Entry Lock Week Day Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day of Week\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_SET\",\"_help\":\"Schedule Entry Lock Week Day Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_GET\",\"_help\":\"Schedule Entry Lock Year Day Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_REPORT\",\"_help\":\"Schedule Entry Lock Year Day Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_SET\",\"_help\":\"Schedule Entry Lock Year Day Set\",\"_comment\":\"\"},{\"_key\":\"0x09\",\"_name\":\"SCHEDULE_ENTRY_TYPE_SUPPORTED_GET\",\"_help\":\"Schedule Entry Type Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Slots Week Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Slots Year Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x0A\",\"_name\":\"SCHEDULE_ENTRY_TYPE_SUPPORTED_REPORT\",\"_help\":\"Schedule Entry Type Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x4E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCHEDULE_ENTRY_LOCK\",\"_help\":\"Command Class Schedule Entry Lock\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"disabled\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"enabled\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Enabled\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_ENTRY_LOCK_ENABLE_ALL_SET\",\"_help\":\"Schedule Entry Lock Enable All Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"disabled\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"enabled\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"Enabled\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCHEDULE_ENTRY_LOCK_ENABLE_SET\",\"_help\":\"Schedule Entry Lock Enable Set\",\"_comment\":\"\"},{\"_key\":\"0x0B\",\"_name\":\"SCHEDULE_ENTRY_LOCK_TIME_OFFSET_GET\",\"_help\":\"Schedule Entry Lock Time Offset Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Hour TZO\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign TZO\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute TZO\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Minute Offset DST\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign Offset DST\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x0C\",\"_name\":\"SCHEDULE_ENTRY_LOCK_TIME_OFFSET_REPORT\",\"_help\":\"Schedule Entry Lock Time Offset Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Hour TZO\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign TZO\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute TZO\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Minute Offset DST\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign Offset DST\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x0D\",\"_name\":\"SCHEDULE_ENTRY_LOCK_TIME_OFFSET_SET\",\"_help\":\"Schedule Entry Lock Time Offset Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_GET\",\"_help\":\"Schedule Entry Lock Week Day Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day of Week\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_REPORT\",\"_help\":\"Schedule Entry Lock Week Day Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day of Week\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_SET\",\"_help\":\"Schedule Entry Lock Week Day Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_GET\",\"_help\":\"Schedule Entry Lock Year Day Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_REPORT\",\"_help\":\"Schedule Entry Lock Year Day Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_SET\",\"_help\":\"Schedule Entry Lock Year Day Set\",\"_comment\":\"\"},{\"_key\":\"0x09\",\"_name\":\"SCHEDULE_ENTRY_TYPE_SUPPORTED_GET\",\"_help\":\"Schedule Entry Type Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Slots Week Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Slots Year Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x0A\",\"_name\":\"SCHEDULE_ENTRY_TYPE_SUPPORTED_REPORT\",\"_help\":\"Schedule Entry Type Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x4E\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SCHEDULE_ENTRY_LOCK\",\"_help\":\"Command Class Schedule Entry Lock\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"disabled\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"enabled\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Enabled\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_ENTRY_LOCK_ENABLE_ALL_SET\",\"_help\":\"Schedule Entry Lock Enable All Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"disabled\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"enabled\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"Enabled\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SCHEDULE_ENTRY_LOCK_ENABLE_SET\",\"_help\":\"Schedule Entry Lock Enable Set\",\"_comment\":\"\"},{\"_key\":\"0x0B\",\"_name\":\"SCHEDULE_ENTRY_LOCK_TIME_OFFSET_GET\",\"_help\":\"Schedule Entry Lock Time Offset Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Hour TZO\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign TZO\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute TZO\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Minute Offset DST\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign Offset DST\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x0C\",\"_name\":\"SCHEDULE_ENTRY_LOCK_TIME_OFFSET_REPORT\",\"_help\":\"Schedule Entry Lock Time Offset Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Hour TZO\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign TZO\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute TZO\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Minute Offset DST\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign Offset DST\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x0D\",\"_name\":\"SCHEDULE_ENTRY_LOCK_TIME_OFFSET_SET\",\"_help\":\"Schedule Entry Lock Time Offset Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_GET\",\"_help\":\"Schedule Entry Lock Week Day Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day of Week\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_REPORT\",\"_help\":\"Schedule Entry Lock Week Day Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Day of Week\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCHEDULE_ENTRY_LOCK_WEEK_DAY_SET\",\"_help\":\"Schedule Entry Lock Week Day Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_GET\",\"_help\":\"Schedule Entry Lock Year Day Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x08\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_REPORT\",\"_help\":\"Schedule Entry Lock Year Day Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Stop Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SCHEDULE_ENTRY_LOCK_YEAR_DAY_SET\",\"_help\":\"Schedule Entry Lock Year Day Set\",\"_comment\":\"\"},{\"_key\":\"0x09\",\"_name\":\"SCHEDULE_ENTRY_TYPE_SUPPORTED_GET\",\"_help\":\"Schedule Entry Type Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Slots Week Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Slots Year Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of Slots Daily Repeating\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0A\",\"_name\":\"SCHEDULE_ENTRY_TYPE_SUPPORTED_REPORT\",\"_help\":\"Schedule Entry Type Supported Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0E\",\"_name\":\"SCHEDULE_ENTRY_LOCK_DAILY_REPEATING_GET\",\"_help\":\"Schedule Entry Lock Daily Repeating Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Week Day Bitmask\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Duration Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Duration Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0F\",\"_name\":\"SCHEDULE_ENTRY_LOCK_DAILY_REPEATING_REPORT\",\"_help\":\"Schedule Entry Lock Daily Repeating Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Erase\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Modify\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Set Action\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule Slot ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Week Day Bitmask\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Duration Hour\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Duration Minute\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x10\",\"_name\":\"SCHEDULE_ENTRY_LOCK_DAILY_REPEATING_SET\",\"_help\":\"Schedule Entry Lock Daily Repeating Set\"}],\"_key\":\"0x4E\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_SCHEDULE_ENTRY_LOCK\",\"_help\":\"Command Class Schedule Entry Lock\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SCREEN_ATTRIBUTES_GET\",\"_help\":\"Screen Attributes Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Lines\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Characters per Line\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Size of Line Buffer\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Numerical Presentation of a Character\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"SCREEN_ATTRIBUTES_REPORT\",\"_help\":\"Screen Attributes Report\",\"_comment\":\"\"}],\"_key\":\"0x93\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCREEN_ATTRIBUTES\",\"_help\":\"Command Class Screen Attributes\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SCREEN_ATTRIBUTES_GET\",\"_help\":\"Screen Attributes Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Lines\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Escape Sequence\",\"_flagmask\":\"0x20\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Characters per Line\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Size of Line Buffer\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Numerical Presentation of a Character\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Screen Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SCREEN_ATTRIBUTES_REPORT\",\"_help\":\"Screen Attributes Report\",\"_comment\":\"\"}],\"_key\":\"0x93\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SCREEN_ATTRIBUTES\",\"_help\":\"Command Class Screen Attributes\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x01\",\"_name\":\"SCREEN_MD_GET\",\"_help\":\"Screen Md Get\",\"_comment\":\"\"},{\"param\":{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Screen Settings\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"More Data\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Line Number\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Line Settings\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Clear\",\"_flagmask\":\"0x10\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Character Position\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of Characters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SCREEN_MD_REPORT\",\"_help\":\"Screen Md Report\",\"_comment\":\"\"}],\"_key\":\"0x92\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCREEN_MD\",\"_help\":\"Command Class Screen Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x01\",\"_name\":\"SCREEN_MD_GET\",\"_help\":\"Screen Md Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Char. Presentation\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Screen Settings\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Reserved1\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"More Data\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Screen Timeout\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Line Number\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Line Settings\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Clear\",\"_flagmask\":\"0x10\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Character Position\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of Characters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SCREEN_MD_REPORT\",\"_help\":\"Screen Md Report\",\"_comment\":\"\"}],\"_key\":\"0x92\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SCREEN_MD\",\"_help\":\"Command Class Screen Md\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x03\",\"_name\":\"SECURITY_PANEL_MODE_GET\",\"_help\":\"Security Panel Mode Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Arm Home\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Arm Away, No Delay\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Arm Away, Delayed\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Disarm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm Trigger\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x00\",\"_name\":\"MODE\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"SECURITY_PANEL_MODE_REPORT\",\"_help\":\"Security Panel Mode Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Arm Home\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Arm Away, No Delay\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Arm Away, Delayed\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Disarm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Alarm Trigger\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x00\",\"_name\":\"MODE\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"SECURITY_PANEL_MODE_SET\",\"_help\":\"Security Panel Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SECURITY_PANEL_MODE_SUPPORTED_GET\",\"_help\":\"Security Panel Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Mode Bit Mask\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SECURITY_PANEL_MODE_SUPPORTED_REPORT\",\"_help\":\"Security Panel Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x24\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_MODE\",\"_help\":\"Command Class Security Panel Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Number of Sensors\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_ZONE_SENSOR_INSTALLED_REPORT\",\"_help\":\"Command Class Security Panel Zone Sensor Installed Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Sensor Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SECURITY_PANEL_ZONE_SENSOR_TYPE_GET\",\"_help\":\"Security Panel Zone Sensor Type Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Sensor Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"ZWave Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SECURITY_PANEL_ZONE_SENSOR_TYPE_REPORT\",\"_help\":\"Security Panel Zone Sensor Type Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"SECURITY_PANEL_ZONE_SENSOR_INSTALLED_GET\",\"_help\":\"Security Panel Zone Sensor Installed Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Sensor Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SECURITY_PANEL_ZONE_SENSOR_STATE_GET\",\"_help\":\"Security Panel Zone Sensor State Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Sensor Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"ZWave Alarm Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"ZWave Alarm Event\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Event Parameters\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SECURITY_PANEL_ZONE_SENSOR_STATE_REPORT\",\"_help\":\"Security Panel Zone Sensor State Report\",\"_comment\":\"\"}],\"_key\":\"0x2F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_ZONE_SENSOR\",\"_help\":\"Command Class Security Panel Zone Sensor\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SECURITY_PANEL_ZONE_NUMBER_SUPPORTED_GET\",\"_help\":\"Security Panel Zone Number Supported Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"SECURITY_PANEL_ZONE_STATE_GET\",\"_help\":\"Security Panel Zone State Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Faulted\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Not-Faulted\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Bypass Faulted\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"Bypass Not-Faulted\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x01\",\"_name\":\"Zone State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SECURITY_PANEL_ZONE_STATE_REPORT\",\"_help\":\"Security Panel Zone State Report\",\"_comment\":\"\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Zones Supported\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"ZM\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Parameters1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"SECURITY_PANEL_ZONE_SUPPORTED_REPORT\",\"_help\":\"Security Panel Zone Supported Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SECURITY_PANEL_ZONE_TYPE_GET\",\"_help\":\"Security Panel Zone Type Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Zone Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Alarm Zone\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Notification Zone\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Zone Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SECURITY_PANEL_ZONE_TYPE_REPORT\",\"_help\":\"Security Panel Zone Type Report\",\"_comment\":\"\"}],\"_key\":\"0x2E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_ZONE\",\"_help\":\"Command Class Security Panel Zone\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Network Key byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"NETWORK_KEY_SET\",\"_help\":\"Network Key Set\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"NETWORK_KEY_VERIFY\",\"_help\":\"Network Key Verify\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"SECURITY_COMMANDS_SUPPORTED_GET\",\"_help\":\"Security Commands Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Command Class support\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"const\":{\"_key\":\"0x00\",\"_flagname\":\"COMMAND_CLASS_MARK\",\"_flagmask\":\"0xEF\"},\"_key\":\"0x02\",\"_name\":\"COMMAND_CLASS_MARK\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\",\"_comment\":\"The COMMAND_CLASS_MARK is used to indicate that all preceding command classes are supported and all following command classes are controlled.\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Command Class control\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"}],\"_key\":\"0x03\",\"_name\":\"SECURITY_COMMANDS_SUPPORTED_REPORT\",\"_help\":\"Security Commands Supported Report\",\"_comment\":\"\"},{\"param\":[{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"8\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Initialization Vector byte\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Sequence Counter\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x03\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Sequenced\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x02\",\"_flagname\":\"Second Frame\",\"_flagmask\":\"0x20\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Command byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Receivers nonce Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"8\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Message Authentication Code byte\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x81\",\"_name\":\"SECURITY_MESSAGE_ENCAPSULATION\",\"_help\":\"Security Message Encapsulation\",\"_comment\":\"\"},{\"param\":[{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"8\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Initialization Vector byte\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Sequence Counter\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x03\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Sequenced\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x02\",\"_flagname\":\"Second Frame\",\"_flagmask\":\"0x20\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Command byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Receivers nonce Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"8\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Message Authentication Code byte\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0xC1\",\"_name\":\"SECURITY_MESSAGE_ENCAPSULATION_NONCE_GET\",\"_help\":\"Security Message Encapsulation Nonce Get\",\"_comment\":\"\"},{\"_key\":\"0x40\",\"_name\":\"SECURITY_NONCE_GET\",\"_help\":\"Security Nonce Get\",\"_comment\":\"\"},{\"param\":{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"8\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Nonce byte\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"},\"_key\":\"0x80\",\"_name\":\"SECURITY_NONCE_REPORT\",\"_help\":\"Security Nonce Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Security Schemes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"SECURITY_SCHEME_GET\",\"_help\":\"Security Scheme Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Security Schemes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x08\",\"_name\":\"SECURITY_SCHEME_INHERIT\",\"_help\":\"Security Scheme Inherit\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Security Schemes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"SECURITY_SCHEME_REPORT\",\"_help\":\"Security Scheme Report\",\"_comment\":\"\"}],\"_key\":\"0x98\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SECURITY\",\"_help\":\"Command Class Security\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"General Purpose Alarm\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Smoke Alarm\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"CO Alarm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"CO2 Alarm\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"Heat Alarm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x06\",\"_flagname\":\"Water Leak Alarm\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x07\",\"_flagname\":\"Return first Alarm on supported list\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"SENSOR_ALARM_GET\",\"_help\":\"Sensor Alarm Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Source Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"General Purpose Alarm\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Smoke Alarm\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"CO Alarm\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"CO2 Alarm\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"Heat Alarm\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x06\",\"_flagname\":\"Water Leak Alarm\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x07\",\"_flagname\":\"Return first Alarm on supported list\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Sensor Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"no alarm\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"alarm\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x02\",\"_name\":\"Sensor State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Seconds\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"SENSOR_ALARM_REPORT\",\"_help\":\"Sensor Alarm Report\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"SENSOR_ALARM_SUPPORTED_GET\",\"_help\":\"Sensor Alarm Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Bit Masks\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SENSOR_ALARM_SUPPORTED_REPORT\",\"_help\":\"Sensor Alarm Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x9C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SENSOR_ALARM\",\"_help\":\"Command Class Sensor Alarm\",\"_read_only\":\"false\",\"_comment\":\"SDS10963-4 The Sensor Alarm command class can be used to realize Sensor Alarms.\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SENSOR_BINARY_GET\",\"_help\":\"Sensor Binary Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"idle\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"detected an event\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Value\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SENSOR_BINARY_REPORT\",\"_help\":\"Sensor Binary Report\",\"_comment\":\"\"}],\"_key\":\"0x30\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SENSOR_BINARY\",\"_help\":\"Command Class Sensor Binary\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"General\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"CO\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x06\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x07\",\"_flagname\":\"Water\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x08\",\"_flagname\":\"Freeze\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x09\",\"_flagname\":\"Tamper\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x0A\",\"_flagname\":\"Aux\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0B\",\"_flagname\":\"Door/Window\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tilt\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0D\",\"_flagname\":\"Motion\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0E\",\"_flagname\":\"Glass Break\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x02\",\"_name\":\"SENSOR_BINARY_GET\",\"_help\":\"Sensor Binary Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"idle\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"detected an event\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Value\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"General\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"CO\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x05\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x06\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x07\",\"_flagname\":\"Water\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x08\",\"_flagname\":\"Freeze\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x09\",\"_flagname\":\"Tamper\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x0A\",\"_flagname\":\"Aux\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0B\",\"_flagname\":\"Door/Window\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tilt\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0D\",\"_flagname\":\"Motion\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0E\",\"_flagname\":\"Glass Break\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0F\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Sensor Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"SENSOR_BINARY_REPORT\",\"_help\":\"Sensor Binary Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SENSOR_BINARY_SUPPORTED_GET_SENSOR\",\"_help\":\"Sensor Binary Supported Get Sensor\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"General\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Smoke\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"CO\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"CO2\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Water\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Freeze\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Tamper\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Aux\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Door/Window\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Tilt\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Motion\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Glass Break\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"First\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x04\",\"_name\":\"SENSOR_BINARY_SUPPORTED_SENSOR_REPORT\",\"_help\":\"Sensor Binary Supported Sensor Report\"}],\"_key\":\"0x30\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SENSOR_BINARY\",\"_help\":\"Command Class Sensor Binary\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SENSOR_TRIGGER_LEVEL_GET\",\"_help\":\"Sensor Trigger Level Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Relative humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Trigger Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"SENSOR_TRIGGER_LEVEL_REPORT\",\"_help\":\"Sensor Trigger Level Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Current\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Default\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Relative humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"}],\"_key\":\"0x01\",\"_name\":\"Sensor Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Trigger Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SENSOR_TRIGGER_LEVEL_SET\",\"_help\":\"Sensor Trigger Level Set\",\"_comment\":\"\"}],\"_key\":\"0x9E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SENSOR_CONFIGURATION\",\"_help\":\"Command Class Sensor Configuration\",\"_read_only\":\"false\",\"_comment\":\"This command class adds the possibility for sensors to act on either a measured value or on a\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Sensor Multilevel Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Sensor Multilevel Report\",\"_comment\":\"\"}],\"_key\":\"0x31\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Sensor Multilevel Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Sensor Multilevel Report\",\"_comment\":\"\"}],\"_key\":\"0x31\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Sensor Multilevel Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Sensor Multilevel Report\",\"_comment\":\"\"}],\"_key\":\"0x31\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Sensor Multilevel Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Sensor Multilevel Report\",\"_comment\":\"\"}],\"_key\":\"0x31\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Multilevel Sensor Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Multilevel Sensor Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SENSOR\",\"_help\":\"Multilevel Sensor Get Supported Sensor\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture\",\"_flagmask\":\"0x1F\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SENSOR_REPORT\",\"_help\":\"Multilevel Sensor Supported Sensor Report\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SCALE\",\"_help\":\"Multilevel Sensor Get Supported Scale\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale Bit Mask\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SCALE_REPORT\",\"_help\":\"Multilevel Sensor Supported Scale Report\"}],\"_key\":\"0x31\",\"_version\":\"5\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Multilevel Sensor Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Multilevel Sensor Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SENSOR\",\"_help\":\"Multilevel Sensor Get Supported Sensor\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature\",\"_flagmask\":\"0x22\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SENSOR_REPORT\",\"_help\":\"Multilevel Sensor Supported Sensor Report\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SCALE\",\"_help\":\"Multilevel Sensor Get Supported Scale\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale Bit Mask\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SCALE_REPORT\",\"_help\":\"Multilevel Sensor Supported Scale Report\"}],\"_key\":\"0x31\",\"_version\":\"6\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Multilevel Sensor Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Multilevel Sensor Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SENSOR\",\"_help\":\"Multilevel Sensor Get Supported Sensor\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI\",\"_flagmask\":\"0x33\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SENSOR_REPORT\",\"_help\":\"Multilevel Sensor Supported Sensor Report\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SCALE\",\"_help\":\"Multilevel Sensor Get Supported Scale\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale Bit Mask\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SCALE_REPORT\",\"_help\":\"Multilevel Sensor Supported Scale Report\"}],\"_key\":\"0x31\",\"_version\":\"7\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Multilevel Sensor Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Multilevel Sensor Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SENSOR\",\"_help\":\"Multilevel Sensor Get Supported Sensor\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SENSOR_REPORT\",\"_help\":\"Multilevel Sensor Supported Sensor Report\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SCALE\",\"_help\":\"Multilevel Sensor Get Supported Scale\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale Bit Mask\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SCALE_REPORT\",\"_help\":\"Multilevel Sensor Supported Scale Report\"}],\"_key\":\"0x31\",\"_version\":\"8\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"},{\"_key\":\"0x37\",\"_flagname\":\"Water Flow (v9)\",\"_flagmask\":\"0x38\"},{\"_key\":\"0x38\",\"_flagname\":\"Water Pressure (v9)\",\"_flagmask\":\"0x39\"},{\"_key\":\"0x39\",\"_flagname\":\"RF Signal Strength (v9)\",\"_flagmask\":\"0x3A\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SENSOR_MULTILEVEL_GET\",\"_help\":\"Multilevel Sensor Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"},{\"_key\":\"0x37\",\"_flagname\":\"Water Flow (v9)\",\"_flagmask\":\"0x38\"},{\"_key\":\"0x38\",\"_flagname\":\"Water Pressure (v9)\",\"_flagmask\":\"0x39\"},{\"_key\":\"0x39\",\"_flagname\":\"RF Signal Strength (v9)\",\"_flagmask\":\"0x3A\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Sensor Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SENSOR_MULTILEVEL_REPORT\",\"_help\":\"Multilevel Sensor Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SENSOR\",\"_help\":\"Multilevel Sensor Get Supported Sensor\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Air temperature\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Humidity\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"},{\"_key\":\"0x37\",\"_flagname\":\"Water Flow (v9)\",\"_flagmask\":\"0x38\"},{\"_key\":\"0x38\",\"_flagname\":\"Water Pressure (v9)\",\"_flagmask\":\"0x39\"},{\"_key\":\"0x39\",\"_flagname\":\"RF Signal Strength (v9)\",\"_flagmask\":\"0x3A\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SENSOR_REPORT\",\"_help\":\"Multilevel Sensor Supported Sensor Report\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"},{\"_key\":\"0x37\",\"_flagname\":\"Water Flow (v9)\",\"_flagmask\":\"0x38\"},{\"_key\":\"0x38\",\"_flagname\":\"Water Pressure (v9)\",\"_flagmask\":\"0x39\"},{\"_key\":\"0x39\",\"_flagname\":\"RF Signal Strength (v9)\",\"_flagmask\":\"0x3A\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_GET_SCALE\",\"_help\":\"Multilevel Sensor Get Supported Scale\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Temperature (version 1)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"General purpose value (version 1)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Luminance (version 1)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"Power (version 2)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"Relative humidity (version 2)\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x05\",\"_flagname\":\"Velocity (version 2) \",\"_flagmask\":\"0x06\"},{\"_key\":\"0x06\",\"_flagname\":\"Direction (version 2) \",\"_flagmask\":\"0x07\"},{\"_key\":\"0x07\",\"_flagname\":\"Atmospheric pressure (version 2) \",\"_flagmask\":\"0x08\"},{\"_key\":\"0x08\",\"_flagname\":\"Barometric pressure (version 2) \",\"_flagmask\":\"0x09\"},{\"_key\":\"0x09\",\"_flagname\":\"Solar radiation (version 2) \",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0A\",\"_flagname\":\"Dew point (version 2) \",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0B\",\"_flagname\":\"Rain rate (version 2) \",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0C\",\"_flagname\":\"Tide level (version 2) \",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0D\",\"_flagname\":\"Weight (version 3)\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0E\",\"_flagname\":\"Voltage (version 3)\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x0F\",\"_flagname\":\"Current (version 3)\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x10\",\"_flagname\":\"CO2-level (version 3)\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x11\",\"_flagname\":\"Air flow (version 3)\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x12\",\"_flagname\":\"Tank capacity (version 3)\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x13\",\"_flagname\":\"Distance (version 3)\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x14\",\"_flagname\":\"Angle Position (version 4)\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x15\",\"_flagname\":\"Rotation (v5)\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x16\",\"_flagname\":\"Water temperature (v5)\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x17\",\"_flagname\":\"Soil temperature (v5)\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x18\",\"_flagname\":\"Seismic intensity (v5)\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x19\",\"_flagname\":\"Seismic magnitude (v5)\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1A\",\"_flagname\":\"Ultraviolet (v5)\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1B\",\"_flagname\":\"Electrical resistivity (v5)\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1C\",\"_flagname\":\"Electrical conductivity (v5)\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1D\",\"_flagname\":\"Loudness (v5)\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1E\",\"_flagname\":\"Moisture (v5)\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x1F\",\"_flagname\":\"Frequency (v6)\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x20\",\"_flagname\":\"Time (v6)\",\"_flagmask\":\"0x21\"},{\"_key\":\"0x21\",\"_flagname\":\"Target Temperature (v6)\",\"_flagmask\":\"0x22\"},{\"_key\":\"0x22\",\"_flagname\":\"Particulate Matter 2.5 (v7)\",\"_flagmask\":\"0x23\"},{\"_key\":\"0x23\",\"_flagname\":\"Formaldehyde CH2O-level (v7)\",\"_flagmask\":\"0x24\"},{\"_key\":\"0x24\",\"_flagname\":\"Radon Concentration (v7)\",\"_flagmask\":\"0x25\"},{\"_key\":\"0x25\",\"_flagname\":\"Methane Density CH4 (v7)\",\"_flagmask\":\"0x26\"},{\"_key\":\"0x26\",\"_flagname\":\"Volatile Organic Compound (v7)\",\"_flagmask\":\"0x27\"},{\"_key\":\"0x27\",\"_flagname\":\"Carbon Monoxide CO-level (v7)\",\"_flagmask\":\"0x28\"},{\"_key\":\"0x28\",\"_flagname\":\"Soil Humidity (v7)\",\"_flagmask\":\"0x29\"},{\"_key\":\"0x29\",\"_flagname\":\"Soil Reactivity (v7)\",\"_flagmask\":\"0x2A\"},{\"_key\":\"0x2A\",\"_flagname\":\"Soil Salinity (v7)\",\"_flagmask\":\"0x2B\"},{\"_key\":\"0x2B\",\"_flagname\":\"Heart Rate (v7)\",\"_flagmask\":\"0x2C\"},{\"_key\":\"0x2C\",\"_flagname\":\"Blood Pressure (v7)\",\"_flagmask\":\"0x2D\"},{\"_key\":\"0x2D\",\"_flagname\":\"Muscle Mass (v7)\",\"_flagmask\":\"0x2E\"},{\"_key\":\"0x2E\",\"_flagname\":\"Fat Mass (v7)\",\"_flagmask\":\"0x2F\"},{\"_key\":\"0x2F\",\"_flagname\":\"Bone Mass (v7)\",\"_flagmask\":\"0x30\"},{\"_key\":\"0x30\",\"_flagname\":\"Total Body Water, TBW (v7)\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x31\",\"_flagname\":\"Basic Metabolic Rate, BMR (v7)\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x32\",\"_flagname\":\"Body Mass Index, BMI (v7)\",\"_flagmask\":\"0x33\"},{\"_key\":\"0x33\",\"_flagname\":\"Acceleration X-axis (v8)\",\"_flagmask\":\"0x34\"},{\"_key\":\"0x34\",\"_flagname\":\"Acceleration Y-axis (v8)\",\"_flagmask\":\"0x35\"},{\"_key\":\"0x35\",\"_flagname\":\"Acceleration Z-axis (v8)\",\"_flagmask\":\"0x36\"},{\"_key\":\"0x36\",\"_flagname\":\"Smoke Density (v8)\",\"_flagmask\":\"0x37\"},{\"_key\":\"0x37\",\"_flagname\":\"Water Flow (v9)\",\"_flagmask\":\"0x38\"},{\"_key\":\"0x38\",\"_flagname\":\"Water Pressure (v9)\",\"_flagmask\":\"0x39\"},{\"_key\":\"0x39\",\"_flagname\":\"RF Signal Strength (v9)\",\"_flagmask\":\"0x3A\"}],\"_key\":\"0x00\",\"_name\":\"Sensor Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Scale Bit Mask\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"SENSOR_MULTILEVEL_SUPPORTED_SCALE_REPORT\",\"_help\":\"Multilevel Sensor Supported Scale Report\"}],\"_key\":\"0x31\",\"_version\":\"9\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\",\"_help\":\"Command Class Sensor Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Disable sounding of all sensor alarms\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Disable sounding of all sensor alarms independent of bit mask which have received the alarm\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Disable sounding of all sensor alarms according to bit mask\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x04\",\"_flagname\":\"Disable sounding of all sensor alarms according to bit mask which have received the alarm\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Seconds\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of Bit Masks\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Bit Mask\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SENSOR_ALARM_SET\",\"_help\":\"Sensor Alarm Set\",\"_comment\":\"\"},\"_key\":\"0x9D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SILENCE_ALARM\",\"_help\":\"Command Class Silence Alarm\",\"_read_only\":\"false\",\"_comment\":\"SDS10963-4 The Alarm Silence command class can be used to nuisance silence to temporarily disable the sounding\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SIMPLE_AV_CONTROL_GET\",\"_help\":\"Simple Av Control Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of reports\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SIMPLE_AV_CONTROL_REPORT\",\"_help\":\"Simple Av Control Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Key Attributes\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Item ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Command\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x01\",\"_name\":\"SIMPLE_AV_CONTROL_SET\",\"_help\":\"Simple Av Control Set\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Report No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"SIMPLE_AV_CONTROL_SUPPORTED_GET\",\"_help\":\"Simple Av Control Supported Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Report No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"SIMPLE_AV_CONTROL_SUPPORTED_REPORT\",\"_help\":\"Simple Av Control Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x94\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SIMPLE_AV_CONTROL\",\"_help\":\"Command Class Simple Av Control\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_ALL_GET\",\"_help\":\"Switch All Get\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"SWITCH_ALL_OFF\",\"_help\":\"Switch All Off\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"SWITCH_ALL_ON\",\"_help\":\"Switch All On\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"excluded from the all on/all off functionality\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"excluded from the all on functionality but not all off\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"excluded from the all off functionality but not all on\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"included in the all on/all off functionality\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_ALL_REPORT\",\"_help\":\"Switch All Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"excluded from the all on/all off functionality\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"excluded from the all on functionality but not all off\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"excluded from the all off functionality but not all on\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"included in the all on/all off functionality\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"SWITCH_ALL_SET\",\"_help\":\"Switch All Set\",\"_comment\":\"\"}],\"_key\":\"0x27\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SWITCH_ALL\",\"_help\":\"Command Class Switch All\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_BINARY_GET\",\"_help\":\"Switch Binary Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_BINARY_REPORT\",\"_help\":\"Switch Binary Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Switch Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"SWITCH_BINARY_SET\",\"_help\":\"Switch Binary Set\",\"_comment\":\"\"}],\"_key\":\"0x25\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SWITCH_BINARY\",\"_help\":\"Command Class Switch Binary\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_BINARY_GET\",\"_help\":\"Switch Binary Get\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Current Value\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Target Value\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Already at the Target Value\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Unknown duration\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x03\",\"_name\":\"SWITCH_BINARY_REPORT\",\"_help\":\"Switch Binary Report\",\"_comment\":\"\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Target Value\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x01\",\"_name\":\"SWITCH_BINARY_SET\",\"_help\":\"Switch Binary Set\",\"_comment\":\"\"}],\"_key\":\"0x25\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SWITCH_BINARY\",\"_help\":\"Command Class Switch Binary\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_MULTILEVEL_GET\",\"_help\":\"Switch Multilevel Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_MULTILEVEL_REPORT\",\"_help\":\"Switch Multilevel Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"SWITCH_MULTILEVEL_SET\",\"_help\":\"Switch Multilevel Set\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Ignore Start Level\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Up/ Down\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_MULTILEVEL_START_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Start Level Change\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"SWITCH_MULTILEVEL_STOP_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Stop Level Change\",\"_comment\":\"\"}],\"_key\":\"0x26\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SWITCH_MULTILEVEL\",\"_help\":\"Command Class Switch Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_MULTILEVEL_GET\",\"_help\":\"Switch Multilevel Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_MULTILEVEL_REPORT\",\"_help\":\"Switch Multilevel Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Factory default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SWITCH_MULTILEVEL_SET\",\"_help\":\"Switch Multilevel Set\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Ignore Start Level\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Up/ Down\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_MULTILEVEL_START_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Start Level Change\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"SWITCH_MULTILEVEL_STOP_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Stop Level Change\",\"_comment\":\"\"}],\"_key\":\"0x26\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SWITCH_MULTILEVEL\",\"_help\":\"Command Class Switch Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_MULTILEVEL_GET\",\"_help\":\"Switch Multilevel Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_MULTILEVEL_REPORT\",\"_help\":\"Switch Multilevel Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Factory default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SWITCH_MULTILEVEL_SET\",\"_help\":\"Switch Multilevel Set\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"fieldenum\":[{\"fieldenum\":[{\"_value\":\"Increment\"},{\"_value\":\"Decrement\"},{\"_value\":\"Reserved\"},{\"_value\":\"None\"}],\"_key\":\"0x01\",\"_fieldname\":\"Inc Dec\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"fieldenum\":[{\"_value\":\"Up\"},{\"_value\":\"Down\"},{\"_value\":\"Reserved\"},{\"_value\":\"None\"}],\"_key\":\"0x03\",\"_fieldname\":\"Up Down\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Ignore Start Level\",\"_flagmask\":\"0x20\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Step Size\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_MULTILEVEL_START_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Start Level Change\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"SWITCH_MULTILEVEL_STOP_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Stop Level Change\",\"_comment\":\"\"},{\"_key\":\"0x06\",\"_name\":\"SWITCH_MULTILEVEL_SUPPORTED_GET\",\"_help\":\"Switch Multilevel Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Primary Switch Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Secondary Switch Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"SWITCH_MULTILEVEL_SUPPORTED_REPORT\",\"_help\":\"Switch Multilevel Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x26\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_SWITCH_MULTILEVEL\",\"_help\":\"Command Class Switch Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"SWITCH_MULTILEVEL_GET\",\"_help\":\"Switch Multilevel Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Current Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Target Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Already at the Target Value\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Unknown duration\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x03\",\"_name\":\"SWITCH_MULTILEVEL_REPORT\",\"_help\":\"Switch Multilevel Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Dimming Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"SWITCH_MULTILEVEL_SET\",\"_help\":\"Switch Multilevel Set\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"fieldenum\":[{\"fieldenum\":[{\"_value\":\"Increment\"},{\"_value\":\"Decrement\"},{\"_value\":\"Reserved\"},{\"_value\":\"None\"}],\"_key\":\"0x01\",\"_fieldname\":\"Inc Dec\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"fieldenum\":[{\"_value\":\"Up\"},{\"_value\":\"Down\"},{\"_value\":\"Reserved\"},{\"_value\":\"None\"}],\"_key\":\"0x03\",\"_fieldname\":\"Up Down\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Ignore Start Level\",\"_flagmask\":\"0x20\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Dimming Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Step Size\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_MULTILEVEL_START_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Start Level Change\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"SWITCH_MULTILEVEL_STOP_LEVEL_CHANGE\",\"_help\":\"Switch Multilevel Stop Level Change\",\"_comment\":\"\"},{\"_key\":\"0x06\",\"_name\":\"SWITCH_MULTILEVEL_SUPPORTED_GET\",\"_help\":\"Switch Multilevel Supported Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Primary Switch Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Secondary Switch Type\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"SWITCH_MULTILEVEL_SUPPORTED_REPORT\",\"_help\":\"Switch Multilevel Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x26\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_SWITCH_MULTILEVEL\",\"_help\":\"Command Class Switch Multilevel\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SWITCH_TOGGLE_BINARY_SET\",\"_help\":\"Switch Toggle Binary Set\",\"_comment\":\"SWITCH_TOGGLE_BINARY_SET\"},{\"_key\":\"0x02\",\"_name\":\"SWITCH_TOGGLE_BINARY_GET\",\"_help\":\"Switch Toggle Binary Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_TOGGLE_BINARY_REPORT\",\"_help\":\"Switch Toggle Binary Report\",\"_comment\":\"\"}],\"_key\":\"0x28\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SWITCH_TOGGLE_BINARY\",\"_help\":\"Command Class Switch Toggle Binary\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SWITCH_TOGGLE_MULTILEVEL_SET\",\"_help\":\"Switch Toggle Multilevel Set\",\"_comment\":\"SWITCH_TOGGLE_MULTILEVEL_SET\"},{\"_key\":\"0x02\",\"_name\":\"SWITCH_TOGGLE_MULTILEVEL_GET\",\"_help\":\"Switch Toggle Multilevel Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"off/disable\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"on/enable\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_TOGGLE_MULTILEVEL_REPORT\",\"_help\":\"Switch Toggle Multilevel Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Ignore Start Level\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Roll Over\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_TOGGLE_MULTILEVEL_START_LEVEL_CHANGE\",\"_help\":\"Switch Toggle Multilevel Start Level Change\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"SWITCH_TOGGLE_MULTILEVEL_STOP_LEVEL_CHANGE\",\"_help\":\"Switch Toggle Multilevel Stop Level Change\",\"_comment\":\"\"}],\"_key\":\"0x29\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL\",\"_help\":\"Command Class Switch Toggle Multilevel\",\"_read_only\":\"false\",\"_comment\":\"DEPRECATED\"},{\"cmd\":[{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Parameter Set IDs\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"TARIFF_TBL_REMOVE\",\"_help\":\"Tariff Tbl Remove\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Tariff Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Tariff Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"TARIFF_TBL_SET\",\"_help\":\"Tariff Tbl Set\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Currency\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Standing Charge Period\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Standing Charge Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x07\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Standing Charge Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Supplier Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x09\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"9\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Supplier Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"TARIFF_TBL_SUPPLIER_SET\",\"_help\":\"Tariff Tbl Supplier Set\",\"_comment\":\"\"}],\"_key\":\"0x4A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_TARIFF_CONFIG\",\"_help\":\"Command Class Tariff Config\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"TARIFF_TBL_COST_GET\",\"_help\":\"Tariff Tbl Cost Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Rate Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Start Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Start Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Start Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Start Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Stop Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Stop Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Stop Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Stop Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0B\",\"_name\":\"Stop Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0C\",\"_name\":\"Currency\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Cost Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x0D\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0E\",\"_name\":\"Cost Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"TARIFF_TBL_COST_REPORT\",\"_help\":\"Tariff Tbl Cost Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"TARIFF_TBL_GET\",\"_help\":\"Tariff Tbl Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Rate Parameter Set ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Tariff Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Tariff Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"TARIFF_TBL_REPORT\",\"_help\":\"Tariff Tbl Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"TARIFF_TBL_SUPPLIER_GET\",\"_help\":\"Tariff Tbl Supplier Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Currency\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Standing Charge Period\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Standing Charge Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x07\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"dword\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Standing Charge Value\",\"_type\":\"DWORD\",\"_typehashcode\":\"0x03\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Supplier Characters\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x09\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"9\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Supplier Character\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"TARIFF_TBL_SUPPLIER_REPORT\",\"_help\":\"Tariff Tbl Supplier Report\",\"_comment\":\"\"}],\"_key\":\"0x4B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_TARIFF_TBL_MONITOR\",\"_help\":\"Command Class Tariff Tbl Monitor\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_FAN_MODE_GET\",\"_help\":\"Thermostat Fan Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_FAN_MODE_REPORT\",\"_help\":\"Thermostat Fan Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_FAN_MODE_SET\",\"_help\":\"Thermostat Fan Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Fan Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"On\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto High\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"On High\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Fan Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x44\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_MODE\",\"_help\":\"Command Class Thermostat Fan Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_FAN_MODE_GET\",\"_help\":\"Thermostat Fan Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"},{\"_value\":\"Auto Medium\"},{\"_value\":\"Medium\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_FAN_MODE_REPORT\",\"_help\":\"Thermostat Fan Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"},{\"_value\":\"Auto Medium\"},{\"_value\":\"Medium\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Off\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_FAN_MODE_SET\",\"_help\":\"Thermostat Fan Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Fan Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Low\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto High\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"High\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Auto Medium\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Medium\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Fan Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x44\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_MODE\",\"_help\":\"Command Class Thermostat Fan Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_FAN_MODE_GET\",\"_help\":\"Thermostat Fan Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"},{\"_value\":\"Auto Medium\"},{\"_value\":\"Medium\"},{\"_value\":\"Circulation\"},{\"_value\":\"Humidity\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Off\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_FAN_MODE_REPORT\",\"_help\":\"Thermostat Fan Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"},{\"_value\":\"Auto Medium\"},{\"_value\":\"Medium\"},{\"_value\":\"Circulation\"},{\"_value\":\"Humidity\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Off\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_FAN_MODE_SET\",\"_help\":\"Thermostat Fan Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Fan Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Low\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto High\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"High\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Auto Medium\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Medium\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Circulation\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Humidity Circulation\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Fan Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x44\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_MODE\",\"_help\":\"Command Class Thermostat Fan Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_FAN_MODE_GET\",\"_help\":\"Thermostat Fan Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"},{\"_value\":\"Auto Medium\"},{\"_value\":\"Medium\"},{\"_value\":\"Circulation\"},{\"_value\":\"Humidity\"},{\"_value\":\"Left Right\"},{\"_value\":\"Up Down\"},{\"_value\":\"Quiet\"},{\"_value\":\"ReservedB\"},{\"_value\":\"ReservedC\"},{\"_value\":\"ReservedD\"},{\"_value\":\"ReservedE\"},{\"_value\":\"ReservedF\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Off\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_FAN_MODE_REPORT\",\"_help\":\"Thermostat Fan Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Auto Low\"},{\"_value\":\"Low\"},{\"_value\":\"Auto High\"},{\"_value\":\"High\"},{\"_value\":\"Auto Medium\"},{\"_value\":\"Medium\"},{\"_value\":\"Circulation\"},{\"_value\":\"Humidity\"},{\"_value\":\"Left Right\"},{\"_value\":\"Up Down\"},{\"_value\":\"Quiet\"},{\"_value\":\"ReservedB\"},{\"_value\":\"ReservedC\"},{\"_value\":\"ReservedD\"},{\"_value\":\"ReservedE\"},{\"_value\":\"ReservedF\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x70\",\"_shifter\":\"4\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Off\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_FAN_MODE_SET\",\"_help\":\"Thermostat Fan Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Fan Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Low\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto High\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"High\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Auto Medium\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Medium\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Circulation\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Humidity Circulation\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Left Right\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Up Down\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Quiet\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"ReservedB\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"ReservedC\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"ReservedD\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"ReservedE\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"ReservedF\",\"_flagmask\":\"0x0F\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_FAN_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Fan Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x44\",\"_version\":\"4\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_MODE\",\"_help\":\"Command Class Thermostat Fan Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_FAN_STATE_GET\",\"_help\":\"Thermostat Fan State Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Idle\"},{\"_value\":\"Running\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Operating State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_FAN_STATE_REPORT\",\"_help\":\"Thermostat Fan State Report\",\"_comment\":\"\"}],\"_key\":\"0x45\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_STATE\",\"_help\":\"Command Class Thermostat Fan State\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_FAN_STATE_GET\",\"_help\":\"Thermostat Fan State Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Idle\"},{\"_value\":\"Running\"},{\"_value\":\"Running High\"},{\"_value\":\"Running Medium\"},{\"_value\":\"Circulation\"},{\"_value\":\"Humidity Circulation\"},{\"_value\":\"Right-Left Circulation\"},{\"_value\":\"Up-Down Circulation\"},{\"_value\":\"Quiet Circulation\"}],\"_key\":\"0x00\",\"_fieldname\":\"Fan Operating State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_FAN_STATE_REPORT\",\"_help\":\"Thermostat Fan State Report\",\"_comment\":\"\"}],\"_key\":\"0x45\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_STATE\",\"_help\":\"Command Class Thermostat Fan State\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x0D\",\"_name\":\"THERMOSTAT_HEATING_STATUS_REPORT\",\"_help\":\"Thermostat Heating Heating Status Report\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_HEATING_MODE_GET\",\"_help\":\"Thermostat Heating Mode Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Off timed\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Off 3 hours\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Anti freeze\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Manual\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Temporary Manual\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Automatic\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Manual timed\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_HEATING_MODE_REPORT\",\"_help\":\"Thermostat Heating Mode Report\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Off timed\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Off 3 hours\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Anti freeze\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Manual\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Temporary Manual\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Automatic\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Manual timed\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_HEATING_MODE_SET\",\"_help\":\"Thermostat Heating Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x09\",\"_name\":\"THERMOSTAT_HEATING_RELAY_STATUS_GET\",\"_help\":\"Thermostat Heating Relay Status Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"on\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Relay Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x0A\",\"_name\":\"THERMOSTAT_HEATING_RELAY_STATUS_REPORT\",\"_help\":\"Thermostat Heating Relay Status Report\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Setpoint Nr\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_HEATING_SETPOINT_GET\",\"_help\":\"Thermostat Heating Setpoint Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Setpoint Nr\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x06\",\"_name\":\"THERMOSTAT_HEATING_SETPOINT_REPORT\",\"_help\":\"Thermostat Heating Setpoint Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Setpoint Nr\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_HEATING_SETPOINT_SET\",\"_help\":\"Thermostat Heating Setpoint Set\",\"_comment\":\"\"},{\"_key\":\"0x0C\",\"_name\":\"THERMOSTAT_HEATING_STATUS_GET\",\"_help\":\"Thermostat Heating Status Get\",\"_comment\":\"\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x0B\",\"_name\":\"THERMOSTAT_HEATING_STATUS_SET\",\"_help\":\"Thermostat Heating Status Set\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Minutes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Hours\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x11\",\"_name\":\"THERMOSTAT_HEATING_TIMED_OFF_SET\",\"_help\":\"Thermostat Heating Timed Off Set\",\"_comment\":\"\"}],\"_key\":\"0x38\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_HEATING\",\"_help\":\"Command Class Thermostat Heating\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_MODE_GET\",\"_help\":\"Thermostat Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Heat\"},{\"_value\":\"Cool\"},{\"_value\":\"Auto\"},{\"_value\":\"Auxiliary Heat\"},{\"_value\":\"Resume\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto Changeover\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_MODE_REPORT\",\"_help\":\"Thermostat Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Heat\"},{\"_value\":\"Cool\"},{\"_value\":\"Auto\"},{\"_value\":\"Auxiliary Heat\"},{\"_value\":\"Resume\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto Changeover\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_MODE_SET\",\"_help\":\"Thermostat Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cool\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Auxiliary/Emergency Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Resume\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Fan Only\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Furnace\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Dry Air\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Moist Air\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Auto Changeover\",\"_flagmask\":\"0x0A\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x40\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_MODE\",\"_help\":\"Command Class Thermostat Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_MODE_GET\",\"_help\":\"Thermostat Mode Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Heat\"},{\"_value\":\"Cool\"},{\"_value\":\"Auto\"},{\"_value\":\"Auxiliary Heat\"},{\"_value\":\"Resume\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto Changeover\"},{\"_value\":\"Energy Save Heat\"},{\"_value\":\"Energy Save Cool\"},{\"_value\":\"AWAY\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_MODE_REPORT\",\"_help\":\"Thermostat Mode Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Heat\"},{\"_value\":\"Cool\"},{\"_value\":\"Auto\"},{\"_value\":\"Auxiliary Heat\"},{\"_value\":\"Resume\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto Changeover\"},{\"_value\":\"Energy Save Heat\"},{\"_value\":\"Energy Save Cool\"},{\"_value\":\"AWAY\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_MODE_SET\",\"_help\":\"Thermostat Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cool\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Auxiliary/Emergency Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Resume\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Fan Only\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Furnace\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Dry Air\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Moist Air\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Auto Changeover\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Energy Save Heat\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Energy Save Cool\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"AWAY\",\"_flagmask\":\"0x0D\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x40\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_MODE\",\"_help\":\"Command Class Thermostat Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_MODE_GET\",\"_help\":\"Thermostat Mode Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Heat\"},{\"_value\":\"Cool\"},{\"_value\":\"Auto\"},{\"_value\":\"Auxiliary Heat\"},{\"_value\":\"Resume\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto Changeover\"},{\"_value\":\"Energy Save Heat\"},{\"_value\":\"Energy Save Cool\"},{\"_value\":\"AWAY\"},{\"_value\":\"Reserved\"},{\"_value\":\"FULL POWER\"},{\"_value\":\"Reserved0\"},{\"_value\":\"Reserved1\"},{\"_value\":\"Reserved2\"},{\"_value\":\"Reserved3\"},{\"_value\":\"Reserved4\"},{\"_value\":\"Reserved5\"},{\"_value\":\"Reserved6\"},{\"_value\":\"Reserved7\"},{\"_value\":\"Reserved8\"},{\"_value\":\"Reserved9\"},{\"_value\":\"ReservedA\"},{\"_value\":\"ReservedB\"},{\"_value\":\"ReservedC\"},{\"_value\":\"ReservedD\"},{\"_value\":\"ReservedE\"},{\"_value\":\"MANUFACTURER SPECIFC\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"No of Manufacturer Data fields\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xE0\",\"_sizeoffs\":\"5\"},\"_key\":\"0x01\",\"_name\":\"Manufacturer Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_MODE_REPORT\",\"_help\":\"Thermostat Mode Report\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Heat\"},{\"_value\":\"Cool\"},{\"_value\":\"Auto\"},{\"_value\":\"Auxiliary Heat\"},{\"_value\":\"Resume\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto Changeover\"},{\"_value\":\"Energy Save Heat\"},{\"_value\":\"Energy Save Cool\"},{\"_value\":\"AWAY\"},{\"_value\":\"Reserved\"},{\"_value\":\"FULL POWER\"},{\"_value\":\"Reserved0\"},{\"_value\":\"Reserved1\"},{\"_value\":\"Reserved2\"},{\"_value\":\"Reserved3\"},{\"_value\":\"Reserved4\"},{\"_value\":\"Reserved5\"},{\"_value\":\"Reserved6\"},{\"_value\":\"Reserved7\"},{\"_value\":\"Reserved8\"},{\"_value\":\"Reserved9\"},{\"_value\":\"ReservedA\"},{\"_value\":\"ReservedB\"},{\"_value\":\"ReservedC\"},{\"_value\":\"ReservedD\"},{\"_value\":\"ReservedE\"},{\"_value\":\"MANUFACTURER SPECIFC\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"No of Manufacturer Data fields\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xE0\",\"_sizeoffs\":\"5\"},\"_key\":\"0x01\",\"_name\":\"Manufacturer Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_MODE_SET\",\"_help\":\"Thermostat Mode Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_MODE_SUPPORTED_GET\",\"_help\":\"Thermostat Mode Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heat\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cool\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Auto\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Auxiliary/Emergency Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Resume\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Fan Only\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Furnace\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"Dry Air\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"Moist Air\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Auto Changeover\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Energy Save Heat\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"Energy Save Cool\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"AWAY\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"FULL POWER\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"Reserved0\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"Reserved1\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"Reserved3\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x14\",\"_flagname\":\"Reserved4\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x15\",\"_flagname\":\"Reserved5\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x16\",\"_flagname\":\"Reserved6\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x17\",\"_flagname\":\"Reserved7\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x18\",\"_flagname\":\"Reserved8\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x19\",\"_flagname\":\"Reserved9\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x1A\",\"_flagname\":\"ReservedA\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x1B\",\"_flagname\":\"ReservedB\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x1C\",\"_flagname\":\"ReservedC\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x1D\",\"_flagname\":\"ReservedD\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x1E\",\"_flagname\":\"ReservedE\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x1F\",\"_flagname\":\"MANUFACTURER SPECIFC\",\"_flagmask\":\"0x1F\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_MODE_SUPPORTED_REPORT\",\"_help\":\"Thermostat Mode Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x40\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_MODE\",\"_help\":\"Command Class Thermostat Mode\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_OPERATING_STATE_GET\",\"_help\":\"Thermostat Operating State Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Idle\"},{\"_value\":\"Heating\"},{\"_value\":\"Cooling\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Pending Heat\"},{\"_value\":\"Pending Cool\"},{\"_value\":\"Vent/Economizer\"}],\"_key\":\"0x00\",\"_fieldname\":\"Operating State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_OPERATING_STATE_REPORT\",\"_help\":\"Thermostat Operating State Report\",\"_comment\":\"\"}],\"_key\":\"0x42\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_OPERATING_STATE\",\"_help\":\"Command Class Thermostat Operating State\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_OPERATING_STATE_GET\",\"_help\":\"Thermostat Operating State Get\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Idle\"},{\"_value\":\"Heating\"},{\"_value\":\"Cooling\"},{\"_value\":\"Fan Only\"},{\"_value\":\"Pending Heat\"},{\"_value\":\"Pending Cool\"},{\"_value\":\"Vent/Economizer\"},{\"_value\":\"Aux Heating\"},{\"_value\":\"2nd Stage Heating\"},{\"_value\":\"2nd Stage Cooling\"},{\"_value\":\"2nd Stage Aux Heat\"},{\"_value\":\"3rd Stage Aux Heat\"}],\"_key\":\"0x00\",\"_fieldname\":\"Operating State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_OPERATING_STATE_REPORT\",\"_help\":\"Thermostat Operating State Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_OPERATING_STATE_LOGGING_SUPPORTED_GET\",\"_help\":\"Thermostat Operating State Logging Supported Get\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Idle\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Fan Only\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Pending Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Pending Cool\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Vent/Economizer\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Aux Heating\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"2nd Stage Heating\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"2nd Stage Cooling\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"2nd Stage Aux Heat\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"3rd Stage Aux Heat\",\"_flagmask\":\"0x0B\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_OPERATING_LOGGING_SUPPORTED_REPORT\",\"_help\":\"Thermostat Operating State Logging Supported Report\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Idle\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Fan Only\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Pending Heat\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Pending Cool\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Vent/Economizer\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"Aux Heating\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"2nd Stage Heating\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"2nd Stage Cooling\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"2nd Stage Aux Heat\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"3rd Stage Aux Heat\",\"_flagmask\":\"0x0B\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_OPERATING_STATE_LOGGING_GET\",\"_help\":\"Thermostat Operating State Logging Get\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"variant_group\":{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Operating State Log Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Usage Today (Hours)\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Usage Today (Minutes)\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Usage Yesterday (Hours)\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Usage Yesterday (Minutes)\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"THERMOSTAT_OPERATING_STATE_LOGGING_REPORT\",\"_help\":\"Thermostat Operating State Logging Report\"}],\"_key\":\"0x42\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_OPERATING_STATE\",\"_help\":\"Command Class Thermostat Operating State\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_SETBACK_GET\",\"_help\":\"Thermostat Setback Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"No override\"},{\"_value\":\"Temporary override\"},{\"_value\":\"Permanent override\"},{\"_value\":\"Reserved\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setback Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Frost Protection\",\"_flagmask\":\"0x79\"},{\"_key\":\"0x02\",\"_flagname\":\"Energy Saving Mode\",\"_flagmask\":\"0x7A\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7B\"},{\"_key\":\"0x04\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7C\"},{\"_key\":\"0x05\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7D\"},{\"_key\":\"0x06\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7E\"},{\"_key\":\"0x07\",\"_flagname\":\"Unused State\",\"_flagmask\":\"0x7F\"}],\"_key\":\"0x01\",\"_name\":\"Setback State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_SETBACK_REPORT\",\"_help\":\"Thermostat Setback Report\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"No override\"},{\"_value\":\"Temporary override\"},{\"_value\":\"Permanent override\"},{\"_value\":\"Reserved\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setback Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Frost Protection\",\"_flagmask\":\"0x79\"},{\"_key\":\"0x02\",\"_flagname\":\"Energy Saving Mode\",\"_flagmask\":\"0x7A\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7B\"},{\"_key\":\"0x04\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7C\"},{\"_key\":\"0x05\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7D\"},{\"_key\":\"0x06\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x7E\"},{\"_key\":\"0x07\",\"_flagname\":\"Unused State\",\"_flagmask\":\"0x7F\"}],\"_key\":\"0x01\",\"_name\":\"Setback State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_SETBACK_SET\",\"_help\":\"Thermostat Setback Set\",\"_comment\":\"\"}],\"_key\":\"0x47\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_SETBACK\",\"_help\":\"Command Class Thermostat Setback\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_SETPOINT_GET\",\"_help\":\"Thermostat Setpoint Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_SETPOINT_REPORT\",\"_help\":\"Thermostat Setpoint Report\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_SETPOINT_SET\",\"_help\":\"Thermostat Setpoint Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_SETPOINT_SUPPORTED_GET\",\"_help\":\"Thermostat Setpoint Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"None\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Furnace\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x04\",\"_flagname\":\"Dry Air\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Moist Air\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x06\",\"_flagname\":\"Auto changeover\",\"_flagmask\":\"0x0A\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_SETPOINT_SUPPORTED_REPORT\",\"_help\":\"Thermostat Setpoint Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x43\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_SETPOINT\",\"_help\":\"Command Class Thermostat Setpoint\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_SETPOINT_GET\",\"_help\":\"Thermostat Setpoint Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_SETPOINT_REPORT\",\"_help\":\"Thermostat Setpoint Report\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_SETPOINT_SET\",\"_help\":\"Thermostat Setpoint Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_SETPOINT_SUPPORTED_GET\",\"_help\":\"Thermostat Setpoint Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"None\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Furnace\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x04\",\"_flagname\":\"Dry Air\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Moist Air\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x06\",\"_flagname\":\"Auto changeover\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x07\",\"_flagname\":\"Energy Save Heating\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x08\",\"_flagname\":\"Energy Save Cooling\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x09\",\"_flagname\":\"Away Heating\",\"_flagmask\":\"0x0D\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_SETPOINT_SUPPORTED_REPORT\",\"_help\":\"Thermostat Setpoint Supported Report\",\"_comment\":\"\"}],\"_key\":\"0x43\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_SETPOINT\",\"_help\":\"Command Class Thermostat Setpoint\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"},{\"_value\":\"Away Cooling\"},{\"_value\":\"Full Power\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"THERMOSTAT_SETPOINT_GET\",\"_help\":\"Thermostat Setpoint Get\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"},{\"_value\":\"Away Cooling\"},{\"_value\":\"Full Power\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"THERMOSTAT_SETPOINT_REPORT\",\"_help\":\"Thermostat Setpoint Report\",\"_comment\":\"\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"},{\"_value\":\"Away Cooling\"},{\"_value\":\"Full Power\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"THERMOSTAT_SETPOINT_SET\",\"_help\":\"Thermostat Setpoint Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"THERMOSTAT_SETPOINT_SUPPORTED_GET\",\"_help\":\"Thermostat Setpoint Supported Get\",\"_comment\":\"\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"None\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Heating\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Cooling\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Furnace\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x04\",\"_flagname\":\"Dry Air\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x05\",\"_flagname\":\"Moist Air\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x06\",\"_flagname\":\"Auto changeover\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x07\",\"_flagname\":\"Energy Save Heating\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x08\",\"_flagname\":\"Energy Save Cooling\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x09\",\"_flagname\":\"Away Heating\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0A\",\"_flagname\":\"Away Cooling\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0B\",\"_flagname\":\"Full Power\",\"_flagmask\":\"0x0F\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"THERMOSTAT_SETPOINT_SUPPORTED_REPORT\",\"_help\":\"Thermostat Setpoint Supported Report\",\"_comment\":\"\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"},{\"_value\":\"Away Cooling\"},{\"_value\":\"Full Power\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x09\",\"_name\":\"THERMOSTAT_SETPOINT_CAPABILITIES_GET\",\"_help\":\"Thermostat Setpoint Capabilities Get\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"not supported\"},{\"_value\":\"Heating 1\"},{\"_value\":\"Cooling 1\"},{\"_value\":\"not supported1\"},{\"_value\":\"not supported2\"},{\"_value\":\"not supported3\"},{\"_value\":\"not supported4\"},{\"_value\":\"Furnace\"},{\"_value\":\"Dry Air\"},{\"_value\":\"Moist Air\"},{\"_value\":\"Auto changeover\"},{\"_value\":\"Energy Save Heating\"},{\"_value\":\"Energy Save Cooling\"},{\"_value\":\"Away Heating\"},{\"_value\":\"Away Cooling\"},{\"_value\":\"Full Power\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale1\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Min Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size2\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Scale2\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"MaxValue\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0A\",\"_name\":\"THERMOSTAT_SETPOINT_CAPABILITIES_REPORT\",\"_help\":\"Thermostat Setpoint Capabilities Report\"}],\"_key\":\"0x43\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_SETPOINT\",\"_help\":\"Command Class Thermostat Setpoint\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"TIME_PARAMETERS_GET\",\"_help\":\"Time Parameters Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour UTC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute UTC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second UTC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"TIME_PARAMETERS_REPORT\",\"_help\":\"Time Parameters Report\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Hour UTC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Minute UTC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Second UTC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"TIME_PARAMETERS_SET\",\"_help\":\"Time Parameters Set\",\"_comment\":\"\"}],\"_key\":\"0x8B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_TIME_PARAMETERS\",\"_help\":\"Command Class Time Parameters\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x03\",\"_name\":\"DATE_GET\",\"_help\":\"Date Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DATE_REPORT\",\"_help\":\"Date Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"TIME_GET\",\"_help\":\"Time Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Hour Local Time\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"RTC failure\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Hour Local Time\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"TIME_REPORT\",\"_help\":\"Time Report\",\"_comment\":\"\"}],\"_key\":\"0x8A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_TIME\",\"_help\":\"Command Class Time\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x03\",\"_name\":\"DATE_GET\",\"_help\":\"Date Get\",\"_comment\":\"\"},{\"param\":[{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Year\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Month\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Day\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"DATE_REPORT\",\"_help\":\"Date Report\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"TIME_GET\",\"_help\":\"Time Get\",\"_comment\":\"\"},{\"_key\":\"0x06\",\"_name\":\"TIME_OFFSET_GET\",\"_help\":\"Time Offset Get\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Hour TZO\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign TZO\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute TZO\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Minute Offset DST\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign Offset DST\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Month Start DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Day Start DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Hour Start DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Month End DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Day End DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Hour End DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"TIME_OFFSET_REPORT\",\"_help\":\"Time Offset Report\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Hour TZO\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign TZO\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Level\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute TZO\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Minute Offset DST\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Sign Offset DST\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Level2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Month Start DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Day Start DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Hour Start DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Month End DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Day End DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Hour End DST\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x05\",\"_name\":\"TIME_OFFSET_SET\",\"_help\":\"Time Offset Set\",\"_comment\":\"\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Hour Local Time\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"RTC failure\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Hour Local Time\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Minute Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Second Local Time\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"TIME_REPORT\",\"_help\":\"Time Report\",\"_comment\":\"\"}],\"_key\":\"0x8A\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_TIME\",\"_help\":\"Command Class Time\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"datagram_size_1 \",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"datagram_size_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Session ID\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Ext\",\"_flagmask\":\"0x08\"},\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Header Extension Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_optionaloffs\":\"0x02\",\"_optionalmask\":\"0x08\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Header Extension\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x02\",\"_optionalmask\":\"0x08\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Payload\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Frame Check Sequence\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"}],\"_key\":\"0xC0\",\"_name\":\"COMMAND_FIRST_SEGMENT\",\"_help\":\"First Segment\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"reserved2\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Session ID\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0xE8\",\"_name\":\"COMMAND_SEGMENT_COMPLETE\",\"_help\":\"Segment Complete\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"datagram_offset_1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Session ID\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"reserved2\",\"_flagmask\":\"0x08\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"datagram_offset_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0xC8\",\"_name\":\"COMMAND_SEGMENT_REQUEST\",\"_help\":\"Segment Request\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"reserved\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"pending_fragments\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0xF0\",\"_name\":\"COMMAND_SEGMENT_WAIT\",\"_help\":\"Segment Wait\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"datagram_size_1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"datagram_size_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"datagram_offset_1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Session ID\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"bitflag\":{\"_key\":\"0xFF\",\"_flagname\":\"Ext\",\"_flagmask\":\"0x08\"},\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"datagram_offset_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x04\",\"_name\":\"Header Extension Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_optionaloffs\":\"0x02\",\"_optionalmask\":\"0x08\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Header Extension\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\",\"_optionaloffs\":\"0x02\",\"_optionalmask\":\"0x08\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x06\",\"_name\":\"Payload\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Frame Check Sequence\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0xE0\",\"_name\":\"COMMAND_SUBSEQUENT_SEGMENT\",\"_help\":\"Subsequent Segment\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"}],\"_key\":\"0x55\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_TRANSPORT_SERVICE\",\"_help\":\"Command Class Transport Service\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"datagram_size_1 \",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"datagram_size_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Sequence No\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Payload\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0xC0\",\"_name\":\"COMMAND_FIRST_FRAGMENT\",\"_help\":\"First Fragment\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"datagram_size_1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"datagram_size_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"datagram_offset_1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Sequence No\",\"_fieldmask\":\"0x78\",\"_shifter\":\"3\"}],\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"datagram_offset_2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Payload\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Checksum\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0xE0\",\"_name\":\"COMMAND_SUBSEQUENT_FRAGMENT\",\"_help\":\"Subsequent Fragment\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"}],\"_key\":\"0x55\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_TRANSPORT_SERVICE\",\"_help\":\"Command Class Transport Service\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"USER_CODE_GET\",\"_help\":\"User Code Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Available (not set)\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Occupied\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved by administrator\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Status not available\",\"_flagmask\":\"0xFE\"}],\"_key\":\"0x01\",\"_name\":\"User ID Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"10\",\"_is_ascii\":\"true\"},\"_key\":\"0x02\",\"_name\":\"USER_CODE\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"USER_CODE_REPORT\",\"_help\":\"User Code Report\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Available (not set)\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Occupied\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved by administrator\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Status not available\",\"_flagmask\":\"0xFE\"}],\"_key\":\"0x01\",\"_name\":\"User ID Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"10\",\"_is_ascii\":\"true\"},\"_key\":\"0x02\",\"_name\":\"USER_CODE\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"USER_CODE_SET\",\"_help\":\"User Code Set\",\"_comment\":\"\"},{\"_key\":\"0x04\",\"_name\":\"USERS_NUMBER_GET\",\"_help\":\"Users Number Get\",\"_comment\":\"\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported Users\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x05\",\"_name\":\"USERS_NUMBER_REPORT\",\"_help\":\"Users Number Report\",\"_comment\":\"\"}],\"_key\":\"0x63\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_USER_CODE\",\"_help\":\"Command Class User Code\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Requested Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x13\",\"_name\":\"VERSION_COMMAND_CLASS_GET\",\"_help\":\"Version Command Class Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Requested Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Command Class Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x14\",\"_name\":\"VERSION_COMMAND_CLASS_REPORT\",\"_help\":\"Version Command Class Report\",\"_comment\":\"\"},{\"_key\":\"0x11\",\"_name\":\"VERSION_GET\",\"_help\":\"Version Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Z-Wave Library Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Z-Wave Protocol Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Z-Wave Protocol Sub Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Application Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Application Sub Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x12\",\"_name\":\"VERSION_REPORT\",\"_help\":\"Version Report\",\"_comment\":\"\"}],\"_key\":\"0x86\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_VERSION\",\"_help\":\"Command Class Version\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Requested Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},\"_key\":\"0x13\",\"_name\":\"VERSION_COMMAND_CLASS_GET\",\"_help\":\"Version Command Class Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Requested Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Command Class Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x14\",\"_name\":\"VERSION_COMMAND_CLASS_REPORT\",\"_help\":\"Version Command Class Report\",\"_comment\":\"\"},{\"_key\":\"0x11\",\"_name\":\"VERSION_GET\",\"_help\":\"Version Get\",\"_comment\":\"\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Z-Wave Library Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Z-Wave Protocol Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Z-Wave Protocol Sub Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Firmware 0 Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Firmware 0 Sub Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Hardware Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Number of firmware targets\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Firmware Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Firmware Sub Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"}],\"_key\":\"0x07\",\"_name\":\"vg\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x06\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\",\"_comment\":\"\"},\"_key\":\"0x12\",\"_name\":\"VERSION_REPORT\",\"_help\":\"Version Report\",\"_comment\":\"\"}],\"_key\":\"0x86\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_VERSION\",\"_help\":\"Command Class Version\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x05\",\"_name\":\"WAKE_UP_INTERVAL_GET\",\"_help\":\"Wake Up Interval Get\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x06\",\"_name\":\"WAKE_UP_INTERVAL_REPORT\",\"_help\":\"Wake Up Interval Report\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"WAKE_UP_INTERVAL_SET\",\"_help\":\"Wake Up Interval Set\",\"_comment\":\"\"},{\"_key\":\"0x08\",\"_name\":\"WAKE_UP_NO_MORE_INFORMATION\",\"_help\":\"Wake Up No More Information\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"WAKE_UP_NOTIFICATION\",\"_help\":\"Wake Up Notification\",\"_comment\":\"\"}],\"_key\":\"0x84\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_WAKE_UP\",\"_help\":\"Command Class Wake Up\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x09\",\"_name\":\"WAKE_UP_INTERVAL_CAPABILITIES_GET\",\"_help\":\"Wake Up Interval Capabilities Get\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Minimum Wake Up Interval Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Maximum Wake Up Interval Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Default Wake Up Interval Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Wake Up Interval Step Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"}],\"_key\":\"0x0A\",\"_name\":\"WAKE_UP_INTERVAL_CAPABILITIES_REPORT\",\"_help\":\"Wake Up Interval Capabilities Report\",\"_comment\":\"\"},{\"_key\":\"0x05\",\"_name\":\"WAKE_UP_INTERVAL_GET\",\"_help\":\"Wake Up Interval Get\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x06\",\"_name\":\"WAKE_UP_INTERVAL_REPORT\",\"_help\":\"Wake Up Interval Report\",\"_comment\":\"\"},{\"param\":[{\"bit_24\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Seconds\",\"_type\":\"BIT_24\",\"_typehashcode\":\"0x04\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"WAKE_UP_INTERVAL_SET\",\"_help\":\"Wake Up Interval Set\",\"_comment\":\"\"},{\"_key\":\"0x08\",\"_name\":\"WAKE_UP_NO_MORE_INFORMATION\",\"_help\":\"Wake Up No More Information\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"WAKE_UP_NOTIFICATION\",\"_help\":\"Wake Up Notification\",\"_comment\":\"\"}],\"_key\":\"0x84\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_WAKE_UP\",\"_help\":\"Command Class Wake Up\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x02\",\"_name\":\"BIND_ACCEPT\",\"_help\":\"Bind Accept\",\"_comment\":\"\"},{\"_key\":\"0x03\",\"_name\":\"BIND_COMPLETE\",\"_help\":\"Bind Complete\",\"_comment\":\"\"},{\"_key\":\"0x01\",\"_name\":\"BIND_REQUEST\",\"_help\":\"Bind Request\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZENSOR_NET\",\"_help\":\"Command Class Zensor Net\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Datagram Size 1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Datagram Size 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Datagram Tag\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Payload\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0xC0\",\"_name\":\"LOWPAN_FIRST_FRAGMENT\",\"_help\":\"Lowpan First Fragment\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Datagram Size 1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\",\"_cmd_mask\":\"0x07\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Datagram Size 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Datagram Tag\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Datagram Offset\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Payload\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0xE0\",\"_name\":\"LOWPAN_SUBSEQUENT_FRAGMENT\",\"_help\":\"Lowpan Subsequent Fragment\",\"_comment\":\"\",\"_cmd_mask\":\"0xF8\"}],\"_key\":\"0x4F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZIP_6LOWPAN\",\"_help\":\"Command Class Z/IP 6lowpan\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NAck - Option Error\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x02\",\"_flagname\":\"NAck - Queue Full\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x03\",\"_flagname\":\"NAck - Waiting\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x04\",\"_flagname\":\"NAck Response\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Ack Response\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x00\",\"_flagname\":\"Ack Request\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"More Information\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Z-Wave Cmd Included\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Header ext. included\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Source End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved3\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Destination End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit Address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Header extension\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x80\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x06\",\"_name\":\"Z-Wave command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x40\"}],\"_key\":\"0x02\",\"_name\":\"COMMAND_ZIP_PACKET\",\"_help\":\"Zip Packet\"},\"_key\":\"0x23\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZIP\",\"_help\":\"Command Class Z/IP\",\"_read_only\":\"false\",\"_comment\":\"OBSOLETED\"},{\"cmd\":{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NAck - Option Error\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x02\",\"_flagname\":\"NAck - Queue Full\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x03\",\"_flagname\":\"NAck - Waiting\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x04\",\"_flagname\":\"NAck Response\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Ack Response\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x00\",\"_flagname\":\"Ack Request\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Secure Origin\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x02\",\"_flagname\":\"More Information\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x03\",\"_flagname\":\"Z-Wave Cmd Included\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x04\",\"_flagname\":\"Header ext. included\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Source End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved3\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Destination End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit Address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Header Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x80\"},{\"variant\":{\"_paramoffs\":\"5\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\",\"_sizechange\":\"-1\"},\"_key\":\"0x06\",\"_name\":\"Header extension\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x80\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Z-Wave command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x40\"}],\"_key\":\"0x02\",\"_name\":\"COMMAND_ZIP_PACKET\",\"_help\":\"Zip Packet\"},\"_key\":\"0x23\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_ZIP\",\"_help\":\"Command Class Z/IP\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NAck - Option Error\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x02\",\"_flagname\":\"NAck - Queue Full\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x03\",\"_flagname\":\"NAck - Waiting\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x04\",\"_flagname\":\"NAck Response\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x05\",\"_flagname\":\"Ack Response\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x00\",\"_flagname\":\"Ack Request\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Secure Origin\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x02\",\"_flagname\":\"More Information\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x03\",\"_flagname\":\"Z-Wave Cmd Included\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x04\",\"_flagname\":\"Header ext. included\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Seq No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Source End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved3\",\"_flagmask\":\"0x80\"},\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Destination End Point\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Bit Address\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Header Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x80\"},{\"variant\":{\"_paramoffs\":\"5\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\",\"_sizechange\":\"-1\"},\"_key\":\"0x06\",\"_name\":\"Header extension\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x80\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Z-Wave command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x40\"}],\"_key\":\"0x02\",\"_name\":\"COMMAND_ZIP_PACKET\",\"_help\":\"Zip Packet\"},\"_key\":\"0x23\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_ZIP\",\"_help\":\"Command Class Z/IP\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":[{\"_key\":\"0x17\",\"_name\":\"ACCEPT_LOST\",\"_help\":\"Accept Lost\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x03\",\"_name\":\"ASSIGN_ID\",\"_help\":\"Assign Id\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x0C\",\"_name\":\"ASSIGN_RETURN_ROUTE\",\"_help\":\"Assign Return Route\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x14\",\"_name\":\"CMD_ASSIGN_SUC_RETURN_ROUTE\",\"_help\":\"Assign SUC Return Route\",\"_comment\":\"\"},{\"_key\":\"0x10\",\"_name\":\"CMD_AUTOMATIC_CONTROLLER_UPDATE_START\",\"_help\":\"Automatic Controller Update Start\",\"_comment\":\"\"},{\"_key\":\"0x1F\",\"_name\":\"CMD_NODES_EXIST\",\"_help\":\"Cmd Nodes Exist\",\"_comment\":\"\"},{\"_key\":\"0x20\",\"_name\":\"CMD_NODES_EXIST_REPLY\",\"_help\":\"Cmd Nodes Exist Reply\",\"_comment\":\"\"},{\"_key\":\"0x22\",\"_name\":\"CMD_SET_NWI_MODE\",\"_help\":\"Cmd Set Nwi Mode\",\"_comment\":\"\"},{\"_key\":\"0x07\",\"_name\":\"COMMAND_COMPLETE\",\"_help\":\"Command Complete\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x04\",\"_name\":\"FIND_NODES_IN_RANGE\",\"_help\":\"Find Nodes In Range\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x05\",\"_name\":\"GET_NODES_IN_RANGE\",\"_help\":\"Get Nodes In Range\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x16\",\"_name\":\"LOST\",\"_help\":\"Lost\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x0D\",\"_name\":\"NEW_NODE_REGISTERED\",\"_help\":\"New Node Registered\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x0E\",\"_name\":\"NEW_RANGE_REGISTERED\",\"_help\":\"New Range Registered\",\"_comment\":\"SDS10264-2\"},{\"param\":[{\"fieldenum\":[{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"Z-Wave Version 2.0\"},{\"_value\":\"Z-Wave version ZDK 5.0x, ZDK 4.2x\"},{\"_value\":\"Z-Wave version ZDK 4.5x and ZDK 6.0x\"},{\"_value\":\"Reserved\"},{\"_value\":\"Reserved\"},{\"_value\":\"Reserved\"},{\"_value\":\"Reserved\"}],\"_key\":\"0x00\",\"_fieldname\":\"Protocol Version\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"9.6 kbps\"},{\"_value\":\"40 kbps\"}],\"_key\":\"0x01\",\"_fieldname\":\"Max baud rate\",\"_fieldmask\":\"0x38\",\"_shifter\":\"3\"}],\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"Routing\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Listening\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Capability\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Security\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Controller\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Specific Device\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Routing Slave\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"Beam capability\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Sensor 250ms\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"Sensor 1000ms\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"Optional Functionality\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Security\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Reserved\"},{\"_value\":\"100 kbps\"},{\"_value\":\"200 kbps\"}],\"_key\":\"0x00\",\"_fieldname\":\"Speed Extension\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"enum\":[{\"_key\":\"0x01\",\"_name\":\"BASIC_TYPE_CONTROLLER\"},{\"_key\":\"0x04\",\"_name\":\"BASIC_TYPE_ROUTING_SLAVE\"},{\"_key\":\"0x03\",\"_name\":\"BASIC_TYPE_SLAVE\"},{\"_key\":\"0x02\",\"_name\":\"BASIC_TYPE_STATIC_CONTROLLER\"}],\"_key\":\"0x03\",\"_name\":\"Basic Device Class\",\"_type\":\"ENUM\",\"_typehashcode\":\"0x08\",\"_comment\":\"\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x02\"},{\"enum\":[{\"_key\":\"0x03\",\"_name\":\"GENERIC_TYPE_AV_CONTROL_POINT\"},{\"_key\":\"0x04\",\"_name\":\"GENERIC_TYPE_DISPLAY\"},{\"_key\":\"0x40\",\"_name\":\"GENERIC_TYPE_ENTRY_CONTROL\"},{\"_key\":\"0x01\",\"_name\":\"GENERIC_TYPE_GENERIC_CONTROLLER\"},{\"_key\":\"0x31\",\"_name\":\"GENERIC_TYPE_METER\"},{\"_key\":\"0x30\",\"_name\":\"GENERIC_TYPE_METER_PULSE\"},{\"_key\":\"0xFF\",\"_name\":\"GENERIC_TYPE_NON_INTEROPERABLE\"},{\"_key\":\"0x0F\",\"_name\":\"GENERIC_TYPE_REPEATER_SLAVE\"},{\"_key\":\"0x17\",\"_name\":\"GENERIC_TYPE_SECURITY_PANEL\"},{\"_key\":\"0x50\",\"_name\":\"GENERIC_TYPE_SEMI_INTEROPERABLE\"},{\"_key\":\"0xA1\",\"_name\":\"GENERIC_TYPE_SENSOR_ALARM\"},{\"_key\":\"0x20\",\"_name\":\"GENERIC_TYPE_SENSOR_BINARY\"},{\"_key\":\"0x21\",\"_name\":\"GENERIC_TYPE_SENSOR_MULTILEVEL\"},{\"_key\":\"0x02\",\"_name\":\"GENERIC_TYPE_STATIC_CONTROLLER\"},{\"_key\":\"0x10\",\"_name\":\"GENERIC_TYPE_SWITCH_BINARY\"},{\"_key\":\"0x11\",\"_name\":\"GENERIC_TYPE_SWITCH_MULTILEVEL\"},{\"_key\":\"0x12\",\"_name\":\"GENERIC_TYPE_SWITCH_REMOTE\"},{\"_key\":\"0x13\",\"_name\":\"GENERIC_TYPE_SWITCH_TOGGLE\"},{\"_key\":\"0x08\",\"_name\":\"GENERIC_TYPE_THERMOSTAT\"},{\"_key\":\"0x16\",\"_name\":\"GENERIC_TYPE_VENTILATION\"},{\"_key\":\"0x09\",\"_name\":\"GENERIC_TYPE_WINDOW_COVERING\"},{\"_key\":\"0x15\",\"_name\":\"GENERIC_TYPE_ZIP_NODE\"},{\"_key\":\"0x18\",\"_name\":\"GENERIC_TYPE_WALL_CONTROLLER\"},{\"_key\":\"0x05\",\"_name\":\"GENERIC_TYPE_NETWORK_EXTENDER\"},{\"_key\":\"0x06\",\"_name\":\"GENERIC_TYPE_APPLIANCE\"},{\"_key\":\"0x07\",\"_name\":\"GENERIC_TYPE_SENSOR_NOTIFICATION\"}],\"_key\":\"0x04\",\"_name\":\"Generic Device Class\",\"_type\":\"ENUM\",\"_typehashcode\":\"0x08\",\"_comment\":\"\",\"_encaptype\":\"GEN_DEV_REF\"},{\"multi_array\":[{\"paramdescloc\":{\"_key\":\"0x00\",\"_param\":\"4\",\"_paramdesc\":\"255\",\"_paramstart\":\"4\"}},{\"bitflag\":[{\"_key\":\"0x04\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x04\",\"_flagname\":\"SPECIFIC_TYPE_DOORBELL\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x04\",\"_flagname\":\"SPECIFIC_TYPE_SATELLITE_RECEIVER\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x04\",\"_flagname\":\"SPECIFIC_TYPE_SATELLITE_RECEIVER_V2\",\"_flagmask\":\"0x11\"}]},{\"bitflag\":[{\"_key\":\"0x05\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x05\",\"_flagname\":\"SPECIFIC_TYPE_SIMPLE_DISPLAY\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_DOOR_LOCK\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_ADVANCED_DOOR_LOCK\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_KEYPAD_DOOR_LOCK_DEADBOLT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_DOOR\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_GATE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_BARRIER_ADDON\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_BARRIER_OPEN_ONLY\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_BARRIER_CLOSE_ONLY\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_LOCKBOX\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x41\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_KEYPAD\",\"_flagmask\":\"0x0B\"}]},{\"bitflag\":[{\"_key\":\"0x02\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"SPECIFIC_TYPE_PORTABLE_REMOTE_CONTROLLER\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"SPECIFIC_TYPE_PORTABLE_SCENE_CONTROLLER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"SPECIFIC_TYPE_PORTABLE_INSTALLER_TOOL\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x02\",\"_flagname\":\"SPECIFIC_TYPE_REMOTE_CONTROL_AV\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x02\",\"_flagname\":\"SPECIFIC_TYPE_REMOTE_CONTROL_SIMPLE\",\"_flagmask\":\"0x06\"}]},{\"bitflag\":[{\"_key\":\"0x32\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x32\",\"_flagname\":\"SPECIFIC_TYPE_SIMPLE_METER\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x32\",\"_flagname\":\"SPECIFIC_TYPE_ADV_ENERGY_CONTROL\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x32\",\"_flagname\":\"SPECIFIC_TYPE_WHOLE_HOME_METER_SIMPLE\",\"_flagmask\":\"0x03\"}]},{\"bitflag\":{\"_key\":\"0x31\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"}},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"}},{\"bitflag\":[{\"_key\":\"0x10\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x10\",\"_flagname\":\"SPECIFIC_TYPE_REPEATER_SLAVE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x10\",\"_flagname\":\"SPECIFIC_TYPE_VIRTUAL_NODE\",\"_flagmask\":\"0x02\"}]},{\"bitflag\":[{\"_key\":\"0x18\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x18\",\"_flagname\":\"SPECIFIC_TYPE_ZONED_SECURITY_PANEL\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x51\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x51\",\"_flagname\":\"SPECIFIC_TYPE_ENERGY_PRODUCTION\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ADV_ZENSOR_NET_ALARM_SENSOR\",\"_flagmask\":\"0x05\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ADV_ZENSOR_NET_SMOKE_SENSOR\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_BASIC_ROUTING_ALARM_SENSOR\",\"_flagmask\":\"0x01\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_BASIC_ROUTING_SMOKE_SENSOR\",\"_flagmask\":\"0x06\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_BASIC_ZENSOR_NET_ALARM_SENSOR\",\"_flagmask\":\"0x03\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_BASIC_ZENSOR_NET_SMOKE_SENSOR\",\"_flagmask\":\"0x08\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ROUTING_ALARM_SENSOR\",\"_flagmask\":\"0x02\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ROUTING_SMOKE_SENSOR\",\"_flagmask\":\"0x07\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ZENSOR_NET_ALARM_SENSOR\",\"_flagmask\":\"0x04\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ZENSOR_NET_SMOKE_SENSOR\",\"_flagmask\":\"0x09\"},{\"_key\":\"0xA2\",\"_flagname\":\"SPECIFIC_TYPE_ALARM_SENSOR\",\"_flagmask\":\"0x0B\"}]},{\"bitflag\":[{\"_key\":\"0x21\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x21\",\"_flagname\":\"SPECIFIC_TYPE_ROUTING_SENSOR_BINARY\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x22\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x22\",\"_flagname\":\"SPECIFIC_TYPE_ROUTING_SENSOR_MULTILEVEL\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x22\",\"_flagname\":\"SPECIFIC_TYPE_CHIMNEY_FAN\",\"_flagmask\":\"0x02\"}]},{\"bitflag\":[{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_PC_CONTROLLER\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_SCENE_CONTROLLER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_STATIC_INSTALLER_TOOL\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_SET_TOP_BOX\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_SUB_SYSTEM_CONTROLLER\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_TV\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x03\",\"_flagname\":\"SPECIFIC_TYPE_GATEWAY\",\"_flagmask\":\"0x07\"}]},{\"bitflag\":[{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_POWER_SWITCH_BINARY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_SCENE_SWITCH_BINARY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_POWER_STRIP\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_SIREN\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_VALVE_OPEN_CLOSE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_COLOR_TUNABLE_BINARY\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x11\",\"_flagname\":\"SPECIFIC_TYPE_IRRIGATION_CONTROLLER\",\"_flagmask\":\"0x07\"}]},{\"bitflag\":[{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_CLASS_A_MOTOR_CONTROL\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_CLASS_B_MOTOR_CONTROL\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_CLASS_C_MOTOR_CONTROL\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_MOTOR_MULTIPOSITION\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_POWER_SWITCH_MULTILEVEL\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_SCENE_SWITCH_MULTILEVEL\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_FAN_SWITCH\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x12\",\"_flagname\":\"SPECIFIC_TYPE_COLOR_TUNABLE_MULTILEVEL\",\"_flagmask\":\"0x02\"}]},{\"bitflag\":[{\"_key\":\"0x13\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x13\",\"_flagname\":\"SPECIFIC_TYPE_SWITCH_REMOTE_BINARY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x13\",\"_flagname\":\"SPECIFIC_TYPE_SWITCH_REMOTE_MULTILEVEL\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x13\",\"_flagname\":\"SPECIFIC_TYPE_SWITCH_REMOTE_TOGGLE_BINARY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x13\",\"_flagname\":\"SPECIFIC_TYPE_SWITCH_REMOTE_TOGGLE_MULTILEVEL\",\"_flagmask\":\"0x04\"}]},{\"bitflag\":[{\"_key\":\"0x14\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x14\",\"_flagname\":\"SPECIFIC_TYPE_SWITCH_TOGGLE_BINARY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x14\",\"_flagname\":\"SPECIFIC_TYPE_SWITCH_TOGGLE_MULTILEVEL\",\"_flagmask\":\"0x02\"}]},{\"bitflag\":[{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_SETBACK_SCHEDULE_THERMOSTAT\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_SETBACK_THERMOSTAT\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_SETPOINT_THERMOSTAT\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_THERMOSTAT_GENERAL\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_THERMOSTAT_GENERAL_V2\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x09\",\"_flagname\":\"SPECIFIC_TYPE_THERMOSTAT_HEATING\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x17\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x17\",\"_flagname\":\"SPECIFIC_TYPE_RESIDENTIAL_HRV\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x0A\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x0A\",\"_flagname\":\"SPECIFIC_TYPE_SIMPLE_WINDOW_COVERING\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x16\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x16\",\"_flagname\":\"SPECIFIC_TYPE_ZIP_ADV_NODE\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x16\",\"_flagname\":\"SPECIFIC_TYPE_ZIP_TUN_NODE\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x19\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x19\",\"_flagname\":\"SPECIFIC_TYPE_BASIC_WALL_CONTROLLER\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x06\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x06\",\"_flagname\":\"SPECIFIC_TYPE_SECURE_EXTENDER\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x07\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x07\",\"_flagname\":\"SPECIFIC_TYPE_GENERAL_APPLIANCE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x07\",\"_flagname\":\"SPECIFIC_TYPE_KITCHEN_APPLIANCE\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x07\",\"_flagname\":\"SPECIFIC_TYPE_LAUNDRY_APPLIANCE\",\"_flagmask\":\"0x03\"}]},{\"bitflag\":[{\"_key\":\"0x08\",\"_flagname\":\"SPECIFIC_TYPE_NOT_USED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x08\",\"_flagname\":\"SPECIFIC_TYPE_NOTIFICATION_SENSOR\",\"_flagmask\":\"0x01\"}]}],\"_key\":\"0x05\",\"_name\":\"Specific Device Class\",\"_type\":\"MULTI_ARRAY\",\"_typehashcode\":\"0x0A\",\"_comment\":\"\",\"_encaptype\":\"SPEC_DEV_REF\"},{\"enum\":[{\"_key\":\"0x71\",\"_name\":\"COMMAND_CLASS_ALARM\"},{\"_key\":\"0x22\",\"_name\":\"COMMAND_CLASS_APPLICATION_STATUS\"},{\"_key\":\"0x9B\",\"_name\":\"COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION\"},{\"_key\":\"0x85\",\"_name\":\"COMMAND_CLASS_ASSOCIATION\"},{\"_key\":\"0x95\",\"_name\":\"COMMAND_CLASS_AV_CONTENT_DIRECTORY_MD\"},{\"_key\":\"0x97\",\"_name\":\"COMMAND_CLASS_AV_CONTENT_SEARCH_MD\"},{\"_key\":\"0x96\",\"_name\":\"COMMAND_CLASS_AV_RENDERER_STATUS\"},{\"_key\":\"0x99\",\"_name\":\"COMMAND_CLASS_AV_TAGGING_MD\"},{\"_key\":\"0x36\",\"_name\":\"COMMAND_CLASS_BASIC_TARIFF_INFO\"},{\"_key\":\"0x50\",\"_name\":\"COMMAND_CLASS_BASIC_WINDOW_COVERING\"},{\"_key\":\"0x20\",\"_name\":\"COMMAND_CLASS_BASIC\"},{\"_key\":\"0x80\",\"_name\":\"COMMAND_CLASS_BATTERY\"},{\"_key\":\"0x2A\",\"_name\":\"COMMAND_CLASS_CHIMNEY_FAN\"},{\"_key\":\"0x46\",\"_name\":\"COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE\"},{\"_key\":\"0x81\",\"_name\":\"COMMAND_CLASS_CLOCK\"},{\"_key\":\"0x70\",\"_name\":\"COMMAND_CLASS_CONFIGURATION\"},{\"_key\":\"0x21\",\"_name\":\"COMMAND_CLASS_CONTROLLER_REPLICATION\"},{\"_key\":\"0x56\",\"_name\":\"COMMAND_CLASS_CRC_16_ENCAP\"},{\"_key\":\"0x3A\",\"_name\":\"COMMAND_CLASS_DCP_CONFIG\"},{\"_key\":\"0x3B\",\"_name\":\"COMMAND_CLASS_DCP_MONITOR\"},{\"_key\":\"0x4C\",\"_name\":\"COMMAND_CLASS_DOOR_LOCK_LOGGING\"},{\"_key\":\"0x62\",\"_name\":\"COMMAND_CLASS_DOOR_LOCK\"},{\"_key\":\"0x90\",\"_name\":\"COMMAND_CLASS_ENERGY_PRODUCTION\"},{\"_key\":\"0x7A\",\"_name\":\"COMMAND_CLASS_FIRMWARE_UPDATE_MD\"},{\"_key\":\"0x8C\",\"_name\":\"COMMAND_CLASS_GEOGRAPHIC_LOCATION\"},{\"_key\":\"0x7B\",\"_name\":\"COMMAND_CLASS_GROUPING_NAME\"},{\"_key\":\"0x82\",\"_name\":\"COMMAND_CLASS_HAIL\"},{\"_key\":\"0x39\",\"_name\":\"COMMAND_CLASS_HRV_CONTROL\"},{\"_key\":\"0x37\",\"_name\":\"COMMAND_CLASS_HRV_STATUS\"},{\"_key\":\"0x87\",\"_name\":\"COMMAND_CLASS_INDICATOR\"},{\"_key\":\"0x9A\",\"_name\":\"COMMAND_CLASS_IP_CONFIGURATION\"},{\"_key\":\"0x89\",\"_name\":\"COMMAND_CLASS_LANGUAGE\"},{\"_key\":\"0x76\",\"_name\":\"COMMAND_CLASS_LOCK\"},{\"_key\":\"0x91\",\"_name\":\"COMMAND_CLASS_MANUFACTURER_PROPRIETARY\"},{\"_key\":\"0x72\",\"_name\":\"COMMAND_CLASS_MANUFACTURER_SPECIFIC\"},{\"_key\":\"0xEF\",\"_name\":\"COMMAND_CLASS_MARK\"},{\"_key\":\"0x35\",\"_name\":\"COMMAND_CLASS_METER_PULSE\"},{\"_key\":\"0x3C\",\"_name\":\"COMMAND_CLASS_METER_TBL_CONFIG\"},{\"_key\":\"0x3D\",\"_name\":\"COMMAND_CLASS_METER_TBL_MONITOR\"},{\"_key\":\"0x3E\",\"_name\":\"COMMAND_CLASS_METER_TBL_PUSH\"},{\"_key\":\"0x32\",\"_name\":\"COMMAND_CLASS_METER\"},{\"_key\":\"0x51\",\"_name\":\"COMMAND_CLASS_MTP_WINDOW_COVERING\"},{\"_key\":\"0x8E\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL_ASSOCIATION\"},{\"_key\":\"0x60\",\"_name\":\"COMMAND_CLASS_MULTI_CHANNEL\"},{\"_key\":\"0x8F\",\"_name\":\"COMMAND_CLASS_MULTI_CMD\"},{\"_key\":\"0x52\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_PROXY\"},{\"_key\":\"0x4D\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_BASIC\"},{\"_key\":\"0x34\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_INCLUSION\"},{\"_key\":\"0x00\",\"_name\":\"COMMAND_CLASS_NO_OPERATION\"},{\"_key\":\"0x77\",\"_name\":\"COMMAND_CLASS_NODE_NAMING\"},{\"_key\":\"0xF0\",\"_name\":\"COMMAND_CLASS_NON_INTEROPERABLE\"},{\"_key\":\"0x73\",\"_name\":\"COMMAND_CLASS_POWERLEVEL\"},{\"_key\":\"0x41\",\"_name\":\"COMMAND_CLASS_PREPAYMENT_ENCAPSULATION\"},{\"_key\":\"0x3F\",\"_name\":\"COMMAND_CLASS_PREPAYMENT\"},{\"_key\":\"0x88\",\"_name\":\"COMMAND_CLASS_PROPRIETARY\"},{\"_key\":\"0x75\",\"_name\":\"COMMAND_CLASS_PROTECTION\"},{\"_key\":\"0x48\",\"_name\":\"COMMAND_CLASS_RATE_TBL_CONFIG\"},{\"_key\":\"0x49\",\"_name\":\"COMMAND_CLASS_RATE_TBL_MONITOR\"},{\"_key\":\"0x7C\",\"_name\":\"COMMAND_CLASS_REMOTE_ASSOCIATION_ACTIVATE\"},{\"_key\":\"0x7D\",\"_name\":\"COMMAND_CLASS_REMOTE_ASSOCIATION\"},{\"_key\":\"0x2B\",\"_name\":\"COMMAND_CLASS_SCENE_ACTIVATION\"},{\"_key\":\"0x2C\",\"_name\":\"COMMAND_CLASS_SCENE_ACTUATOR_CONF\"},{\"_key\":\"0x2D\",\"_name\":\"COMMAND_CLASS_SCENE_CONTROLLER_CONF\"},{\"_key\":\"0x4E\",\"_name\":\"COMMAND_CLASS_SCHEDULE_ENTRY_LOCK\"},{\"_key\":\"0x93\",\"_name\":\"COMMAND_CLASS_SCREEN_ATTRIBUTES\"},{\"_key\":\"0x92\",\"_name\":\"COMMAND_CLASS_SCREEN_MD\"},{\"_key\":\"0x24\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_MODE\"},{\"_key\":\"0x2F\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_ZONE_SENSOR\"},{\"_key\":\"0x2E\",\"_name\":\"COMMAND_CLASS_SECURITY_PANEL_ZONE\"},{\"_key\":\"0x98\",\"_name\":\"COMMAND_CLASS_SECURITY\"},{\"_key\":\"0x9C\",\"_name\":\"COMMAND_CLASS_SENSOR_ALARM\"},{\"_key\":\"0x30\",\"_name\":\"COMMAND_CLASS_SENSOR_BINARY\"},{\"_key\":\"0x9E\",\"_name\":\"COMMAND_CLASS_SENSOR_CONFIGURATION\"},{\"_key\":\"0x31\",\"_name\":\"COMMAND_CLASS_SENSOR_MULTILEVEL\"},{\"_key\":\"0x9D\",\"_name\":\"COMMAND_CLASS_SILENCE_ALARM\"},{\"_key\":\"0x94\",\"_name\":\"COMMAND_CLASS_SIMPLE_AV_CONTROL\"},{\"_key\":\"0x27\",\"_name\":\"COMMAND_CLASS_SWITCH_ALL\"},{\"_key\":\"0x25\",\"_name\":\"COMMAND_CLASS_SWITCH_BINARY\"},{\"_key\":\"0x26\",\"_name\":\"COMMAND_CLASS_SWITCH_MULTILEVEL\"},{\"_key\":\"0x28\",\"_name\":\"COMMAND_CLASS_SWITCH_TOGGLE_BINARY\"},{\"_key\":\"0x29\",\"_name\":\"COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL\"},{\"_key\":\"0x4A\",\"_name\":\"COMMAND_CLASS_TARIFF_CONFIG\"},{\"_key\":\"0x4B\",\"_name\":\"COMMAND_CLASS_TARIFF_TBL_MONITOR\"},{\"_key\":\"0x44\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_MODE\"},{\"_key\":\"0x45\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_FAN_STATE\"},{\"_key\":\"0x38\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_HEATING\"},{\"_key\":\"0x40\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_MODE\"},{\"_key\":\"0x42\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_OPERATING_STATE\"},{\"_key\":\"0x47\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_SETBACK\"},{\"_key\":\"0x43\",\"_name\":\"COMMAND_CLASS_THERMOSTAT_SETPOINT\"},{\"_key\":\"0x8B\",\"_name\":\"COMMAND_CLASS_TIME_PARAMETERS\"},{\"_key\":\"0x8A\",\"_name\":\"COMMAND_CLASS_TIME\"},{\"_key\":\"0x55\",\"_name\":\"COMMAND_CLASS_TRANSPORT_SERVICE\"},{\"_key\":\"0x63\",\"_name\":\"COMMAND_CLASS_USER_CODE\"},{\"_key\":\"0x86\",\"_name\":\"COMMAND_CLASS_VERSION\"},{\"_key\":\"0x84\",\"_name\":\"COMMAND_CLASS_WAKE_UP\"},{\"_key\":\"0x02\",\"_name\":\"COMMAND_CLASS_ZENSOR_NET\"},{\"_key\":\"0x4F\",\"_name\":\"COMMAND_CLASS_ZIP_6LOWPAN\"},{\"_key\":\"0x23\",\"_name\":\"COMMAND_CLASS_ZIP\"},{\"_key\":\"0x01\",\"_name\":\"ZWAVE_CMD_CLASS\"},{\"_key\":\"0x57\",\"_name\":\"COMMAND_CLASS_APPLICATION_CAPABILITY\"},{\"_key\":\"0x33\",\"_name\":\"COMMAND_CLASS_SWITCH_COLOR\"},{\"_key\":\"0x53\",\"_name\":\"COMMAND_CLASS_SCHEDULE\"},{\"_key\":\"0x54\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_PRIMARY\"},{\"_key\":\"0x58\",\"_name\":\"COMMAND_CLASS_ZIP_ND\"},{\"_key\":\"0x59\",\"_name\":\"COMMAND_CLASS_ASSOCIATION_GRP_INFO\"},{\"_key\":\"0x5A\",\"_name\":\"COMMAND_CLASS_DEVICE_RESET_LOCALLY\"},{\"_key\":\"0x5B\",\"_name\":\"COMMAND_CLASS_CENTRAL_SCENE\"},{\"_key\":\"0x5C\",\"_name\":\"COMMAND_CLASS_IP_ASSOCIATION\"},{\"_key\":\"0x5D\",\"_name\":\"COMMAND_CLASS_ANTITHEFT\"},{\"_key\":\"0x5E\",\"_name\":\"COMMAND_CLASS_ZWAVEPLUS_INFO\"},{\"_key\":\"0x5F\",\"_name\":\"COMMAND_CLASS_ZIP_GATEWAY\"},{\"_key\":\"0x61\",\"_name\":\"COMMAND_CLASS_ZIP_PORTAL\"},{\"_key\":\"0x65\",\"_name\":\"COMMAND_CLASS_DMX\"},{\"_key\":\"0x66\",\"_name\":\"COMMAND_CLASS_BARRIER_OPERATOR\"},{\"_key\":\"0x67\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_INSTALLATION_MAINTENANCE\"},{\"_key\":\"0x68\",\"_name\":\"COMMAND_CLASS_ZIP_NAMING\"},{\"_key\":\"0x69\",\"_name\":\"COMMAND_CLASS_MAILBOX\"},{\"_key\":\"0x6A\",\"_name\":\"COMMAND_CLASS_WINDOW_COVERING\"},{\"_key\":\"0x9F\",\"_name\":\"COMMAND_CLASS_SECURITY_2\"},{\"_key\":\"0x6B\",\"_name\":\"COMMAND_CLASS_IRRIGATION\"},{\"_key\":\"0x6C\",\"_name\":\"COMMAND_CLASS_SUPERVISION\"},{\"_key\":\"0x64\",\"_name\":\"COMMAND_CLASS_HUMIDITY_CONTROL_SETPOINT\"},{\"_key\":\"0x6D\",\"_name\":\"COMMAND_CLASS_HUMIDITY_CONTROL_MODE\"},{\"_key\":\"0x6E\",\"_name\":\"COMMAND_CLASS_HUMIDITY_CONTROL_OPERATING_STATE\"},{\"_key\":\"0x6F\",\"_name\":\"COMMAND_CLASS_ENTRY_CONTROL\"},{\"_key\":\"0x74\",\"_name\":\"COMMAND_CLASS_INCLUSION_CONTROLLER\"}],\"_key\":\"0x06\",\"_name\":\"Command Classes\",\"_type\":\"ENUM_ARRAY\",\"_typehashcode\":\"0x09\",\"_comment\":\"\",\"_encaptype\":\"CMD_CLASS_REF\"}],\"_key\":\"0x01\",\"_name\":\"NODE_INFO\",\"_help\":\"Node Info\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x06\",\"_name\":\"NODE_RANGE_INFO\",\"_help\":\"Node Range Info\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x00\",\"_name\":\"ZWAVE_CMD_NOP\",\"_help\":\"NOP\",\"_comment\":\"\"},{\"_key\":\"0x18\",\"_name\":\"CMD_NOP_POWER\",\"_help\":\"NOP Power\",\"_comment\":\"\"},{\"_key\":\"0x02\",\"_name\":\"REQUEST_NODE_INFO\",\"_help\":\"Request Node Info\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x19\",\"_name\":\"ZWAVE_CMD_RESERVE_NODE_IDS\",\"_help\":\"Reserve Node ID\",\"_comment\":\"\"},{\"_key\":\"0x1A\",\"_name\":\"CMD_RESERVED_IDS\",\"_help\":\"Reserved ID\",\"_comment\":\"\"},{\"_key\":\"0x12\",\"_name\":\"CMD_SET_SUC\",\"_help\":\"Set SUC\",\"_comment\":\"\"},{\"_key\":\"0x13\",\"_name\":\"CMD_SET_SUC_ACK\",\"_help\":\"Set SUC ACK\",\"_comment\":\"\"},{\"_key\":\"0x15\",\"_name\":\"CMD_STATIC_ROUTE_REQUEST\",\"_help\":\"Static Route Request\",\"_comment\":\"\"},{\"_key\":\"0x11\",\"_name\":\"CMD_SUC_NODE_ID\",\"_help\":\"SUC Node ID\",\"_comment\":\"\"},{\"_key\":\"0x0B\",\"_name\":\"TRANSFER_END\",\"_help\":\"Transfer End\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x0F\",\"_name\":\"TRANSFER_NEW_PRIMARY_COMPLETE\",\"_help\":\"Transfer New Primary Complete\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x09\",\"_name\":\"TRANSFER_NODE_INFO\",\"_help\":\"Transfer Node Info\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x08\",\"_name\":\"TRANSFER_PRESENTATION\",\"_help\":\"Transfer Presentation\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x0A\",\"_name\":\"TRANSFER_RANGE_INFO\",\"_help\":\"Transfer Range Info\",\"_comment\":\"SDS10264-2\"},{\"_key\":\"0x23\",\"_name\":\"EXCLUDE_REQUEST\",\"_help\":\"Exclude Request\",\"_comment\":\"INS13044\"},{\"_key\":\"0x24\",\"_name\":\"ASSIGN_RETURN_ROUTE_PRIORITY\",\"_help\":\"Assign Return Route Priority\"},{\"_key\":\"0x25\",\"_name\":\"ASSIGN_SUC_RETURN_ROUTE_PRIORITY\",\"_help\":\"Assign SUC Return Route Priority\"}],\"_key\":\"0x01\",\"_version\":\"1\",\"_name\":\"ZWAVE_CMD_CLASS\",\"_help\":\"Z-Wave protocol Command Class\",\"_read_only\":\"false\",\"_comment\":\"\"},{\"cmd\":{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Dynamic\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Offending Command Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"CMD_CLASS_REF\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Offending Command\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"CMD_REF\"}],\"_key\":\"0x01\",\"_name\":\"COMMAND_COMMAND_CLASS_NOT_SUPPORTED\",\"_help\":\"Command Command Class Not Supported\"},\"_key\":\"0x57\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_APPLICATION_CAPABILITY\",\"_help\":\"Command Class Application Capability\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SWITCH_COLOR_SUPPORTED_GET\",\"_help\":\"Color Switch Supported Get\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component mask\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x02\",\"_name\":\"SWITCH_COLOR_SUPPORTED_REPORT\",\"_help\":\"Color Switch Supported Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_COLOR_GET\",\"_help\":\"Color Switch Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_COLOR_REPORT\",\"_help\":\"Color Switch Report\"},{\"param\":{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Color Component Count\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"SWITCH_COLOR_SET\",\"_help\":\"Color Switch Set\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Ignore Start State\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Up/Down\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x06\",\"_name\":\"SWITCH_COLOR_START_LEVEL_CHANGE\",\"_help\":\"Color Switch Start Level Change\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x07\",\"_name\":\"SWITCH_COLOR_STOP_LEVEL_CHANGE\",\"_help\":\"Color Switch Stop Level Change\"}],\"_key\":\"0x33\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SWITCH_COLOR\",\"_help\":\"Command Class Switch Color\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SWITCH_COLOR_SUPPORTED_GET\",\"_help\":\"Color Switch Supported Get\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component mask\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x02\",\"_name\":\"SWITCH_COLOR_SUPPORTED_REPORT\",\"_help\":\"Color Switch Supported Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_COLOR_GET\",\"_help\":\"Color Switch Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_COLOR_REPORT\",\"_help\":\"Color Switch Report\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Color Component Count\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"SWITCH_COLOR_SET\",\"_help\":\"Color Switch Set\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Ignore Start State\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Up/Down\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x06\",\"_name\":\"SWITCH_COLOR_START_LEVEL_CHANGE\",\"_help\":\"Color Switch Start Level Change\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x07\",\"_name\":\"SWITCH_COLOR_STOP_LEVEL_CHANGE\",\"_help\":\"Color Switch Stop Level Change\"}],\"_key\":\"0x33\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SWITCH_COLOR\",\"_help\":\"Command Class Switch Color\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SWITCH_COLOR_SUPPORTED_GET\",\"_help\":\"Color Switch Supported Get\"},{\"param\":{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component mask\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},\"_key\":\"0x02\",\"_name\":\"SWITCH_COLOR_SUPPORTED_REPORT\",\"_help\":\"Color Switch Supported Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x03\",\"_name\":\"SWITCH_COLOR_GET\",\"_help\":\"Color Switch Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Target Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Already at the Target Value\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Unknown duration\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x04\",\"_name\":\"SWITCH_COLOR_REPORT\",\"_help\":\"Color Switch Report\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Color Component Count\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"SWITCH_COLOR_SET\",\"_help\":\"Color Switch Set\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Ignore Start State\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Up/Down\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x03\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Level\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Instantly\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Default\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x03\",\"_name\":\"Duration\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x06\",\"_name\":\"SWITCH_COLOR_START_LEVEL_CHANGE\",\"_help\":\"Color Switch Start Level Change\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Color Component ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x07\",\"_name\":\"SWITCH_COLOR_STOP_LEVEL_CHANGE\",\"_help\":\"Color Switch Stop Level Change\"}],\"_key\":\"0x33\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_SWITCH_COLOR\",\"_help\":\"Command Class Switch Color\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"SCHEDULE_SUPPORTED_GET\",\"_help\":\"Schedule Support Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Supported Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Time Support\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Fallback Support\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Support Enable/Disable\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of supported CC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Supported Override Types\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Override Support\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported CC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Supported Command\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x03\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x02\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_SUPPORTED_REPORT\",\"_help\":\"Schedule Support Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Month\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Day of Month\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Weekday\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res.\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Duration Type\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Minute\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved3\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x07\",\"_name\":\"Properties5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Duration Byte\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Number of Cmd to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Cmd Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Cmd Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x0A\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x03\",\"_name\":\"COMMAND_SCHEDULE_SET\",\"_help\":\"Schedule Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x04\",\"_name\":\"COMMAND_SCHEDULE_GET\",\"_help\":\"Schedule Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"User Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Month\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Day of Month\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Weekday\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Res.\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Duration Type\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Minute\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved3\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x07\",\"_name\":\"Properties5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Duration Byte\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Number of Cmd to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Cmd Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Cmd Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x0A\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"COMMAND_SCHEDULE_REPORT\",\"_help\":\"Schedule Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x06\",\"_name\":\"SCHEDULE_REMOVE\",\"_help\":\"Schedule Remove\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x07\",\"_name\":\"SCHEDULE_STATE_SET\",\"_help\":\"Schedule State Set\"},{\"_key\":\"0x08\",\"_name\":\"SCHEDULE_STATE_GET\",\"_help\":\"Schedule State Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Supported Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Override\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reports to Follow\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Active_ID 1\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID 2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Active_ID 3\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID N\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x09\",\"_name\":\"SCHEDULE_STATE_REPORT\",\"_help\":\"Schedule State Report\"}],\"_key\":\"0x53\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SCHEDULE\",\"_help\":\"Command Class Schedule\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x01\",\"_name\":\"SCHEDULE_SUPPORTED_GET\",\"_help\":\"Schedule Support Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Supported Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Time Support\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Fallback Support\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Support Enable/Disable\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of supported CC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Supported Override Types\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Override Support\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Number of Supported Schedule Blocks\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported CC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Supported Command\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x03\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x02\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_SUPPORTED_REPORT\",\"_help\":\"Schedule Support Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Month\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved0\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Day of Month\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Weekday\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Duration Type\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Minute\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved3\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x07\",\"_name\":\"Properties5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Duration Byte\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Number of Cmd to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Cmd Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Cmd Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x0A\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x03\",\"_name\":\"COMMAND_SCHEDULE_SET\",\"_help\":\"Schedule Set\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"COMMAND_SCHEDULE_GET\",\"_help\":\"Schedule Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Month\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Day of Month\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Repeat every n hours\"},{\"_value\":\"Repeat every n days\"},{\"_value\":\"Repeat every n weeks\"}],\"_key\":\"0x01\",\"_fieldname\":\"Reserved0\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Weekday\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved1\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Duration Type\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Minute\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x07\",\"_name\":\"Properties5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Duration Byte\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Number of Cmd to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Cmd Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Cmd Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x0A\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"COMMAND_SCHEDULE_REPORT\",\"_help\":\"Schedule Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x06\",\"_name\":\"SCHEDULE_REMOVE\",\"_help\":\"Schedule Remove\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x07\",\"_name\":\"SCHEDULE_STATE_SET\",\"_help\":\"Schedule State Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x08\",\"_name\":\"SCHEDULE_STATE_GET\",\"_help\":\"Schedule State Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Supported Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Override\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reports to Follow\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Active_ID 1\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID 2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Active_ID 3\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID N\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x09\",\"_name\":\"SCHEDULE_STATE_REPORT\",\"_help\":\"Schedule State Report\"}],\"_key\":\"0x53\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_SCHEDULE\",\"_help\":\"Command Class Schedule\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x01\",\"_name\":\"SCHEDULE_SUPPORTED_GET\",\"_help\":\"Schedule Support Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Supported Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Time Support\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Fallback Support\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Support Enable/Disable\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Number of supported CC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Supported Override Types\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Override Support\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Number of Supported Schedule Blocks\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported CC\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Supported Command\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x03\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x03\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x02\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"SCHEDULE_SUPPORTED_REPORT\",\"_help\":\"Schedule Support Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Month\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Recurrence Offset\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Day of Month\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Repeat every n hours\"},{\"_value\":\"Repeat every n days\"},{\"_value\":\"Repeat every n weeks\"}],\"_key\":\"0x01\",\"_fieldname\":\"Recurrence Mode\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Reserved1\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Weekday\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Duration Type\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Minute\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Relative\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved3\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x07\",\"_name\":\"Properties5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Duration Byte\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Number of Cmd to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Cmd Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Cmd Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x0A\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x03\",\"_name\":\"COMMAND_SCHEDULE_SET\",\"_help\":\"Schedule Set\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"AID_RO_CTL\",\"_flagmask\":\"0x80\"},\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x04\",\"_name\":\"COMMAND_SCHEDULE_GET\",\"_help\":\"Schedule Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Start Year\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Month\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"AID_RO\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Day of Month\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Repeat every n hours\"},{\"_value\":\"Repeat every n days\"},{\"_value\":\"Repeat every n weeks\"}],\"_key\":\"0x01\",\"_fieldname\":\"Recurrence Mode\",\"_fieldmask\":\"0x60\",\"_shifter\":\"5\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"AID_RO_CTL\",\"_flagmask\":\"0x80\"},\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Weekday\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Reserved1\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Start Hour\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Duration Type\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Start Minute\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Relative\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Reserved2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x07\",\"_name\":\"Properties5\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Duration Byte\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Reports to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x0A\",\"_name\":\"Number of Cmd to Follow\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Cmd Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Cmd Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x0A\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"COMMAND_SCHEDULE_REPORT\",\"_help\":\"Schedule Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x06\",\"_name\":\"SCHEDULE_REMOVE\",\"_help\":\"Schedule Remove\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Schedule State\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x07\",\"_name\":\"SCHEDULE_STATE_SET\",\"_help\":\"Schedule State Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x08\",\"_name\":\"SCHEDULE_STATE_GET\",\"_help\":\"Schedule State Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Number of Supported Schedule ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Override\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reports to Follow\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Active_ID 1\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID 2\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Active_ID 3\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Active_ID N\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Schedule ID Block\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x09\",\"_name\":\"SCHEDULE_STATE_REPORT\",\"_help\":\"Schedule State Report\"}],\"_key\":\"0x53\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_SCHEDULE\",\"_help\":\"Command Class Schedule\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"CONTROLLER_CHANGE_START\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"CONTROLLER_CHANGE_STOP\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x02\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Ack\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Low Power\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Auto Route\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x03\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x04\",\"_flagname\":\"No Route\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x05\",\"_flagname\":\"Explore\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x06\",\"_flagname\":\"No Retransmission\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x07\",\"_flagname\":\"High Power\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x03\",\"_name\":\"tx Options\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\",\"_comment\":\"\"}],\"_key\":\"0x01\",\"_name\":\"CONTROLLER_CHANGE\",\"_help\":\"Controller Change\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Seq. No\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NODE_ADD_STATUS_DONE\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_ADD_STATUS_FAILED\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_ADD_STATUS_SECURITY_FAILED\",\"_flagmask\":\"0x09\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"New Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Node Info Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Capability\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Listening\",\"_flagmask\":\"0x80\"},\"_key\":\"0x05\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Security\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Opt\",\"_flagmask\":\"0x80\"},\"_key\":\"0x06\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Basic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x08\",\"_name\":\"Generic Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Specific Device Class\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x0A\",\"_name\":\"Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"CONTROLLER_CHANGE_STATUS\",\"_help\":\"Controller Change Status\"}],\"_key\":\"0x54\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_PRIMARY\",\"_help\":\"Command Class Network Management Primary\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x03\",\"_name\":\"ZIP_NODE_SOLICITATION\",\"_help\":\"Zip Node Solicitation\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Local\",\"_flagmask\":\"0x04\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"}],\"_key\":\"0x04\",\"_name\":\"ZIP_INV_NODE_SOLICITATION\",\"_help\":\"Zip Inverse Node Solicitation\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"INFORMATION_OK\"},{\"_value\":\"INFORMATION_OBSOLETE\"},{\"_value\":\"INFORMATION_NOT_FOUND\"}],\"_key\":\"0x00\",\"_fieldname\":\"Validity\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Local\",\"_flagmask\":\"0x04\"},\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"4\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Home ID\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x01\",\"_name\":\"ZIP_NODE_ADVERTISEMENT\",\"_help\":\"Zip Node Advertisement\"}],\"_key\":\"0x58\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZIP_ND\",\"_help\":\"Command Class Z/IP-ND\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x01\",\"_name\":\"ASSOCIATION_GROUP_NAME_GET\",\"_help\":\"Association Group Name Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Length of Name\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x02\",\"_name\":\"ASSOCIATION_GROUP_NAME_REPORT\",\"_help\":\"Association Group Name Report\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"List Mode\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Refresh cache\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"ASSOCIATION_GROUP_INFO_GET\",\"_help\":\"Association Group Info Get\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Group Count\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Dynamic Info\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"List mode\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Profile General\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Profile Control\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Profile Sensor\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x03\",\"_flagname\":\"Profile Notification\",\"_flagmask\":\"0x71\"}],\"_key\":\"0x02\",\"_name\":\"Profile1\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"multi_array\":[{\"paramdescloc\":{\"_key\":\"0x00\",\"_param\":\"2\",\"_paramdesc\":\"255\",\"_paramstart\":\"2\"}},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Profile General NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x00\",\"_flagname\":\"Profile General Lifeline\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY01\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY02\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY03\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY04\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY05\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY06\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY07\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY08\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY09\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY10\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY11\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY12\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY13\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY14\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY15\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY16\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY17\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY18\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY19\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY20\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY21\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY22\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY23\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY24\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY25\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY26\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY27\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY28\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY29\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY30\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY31\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY32\",\"_flagmask\":\"0x20\"}]}],\"_key\":\"0x03\",\"_name\":\"Profile2\",\"_type\":\"MULTI_ARRAY\",\"_typehashcode\":\"0x0A\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event Code\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x04\",\"_name\":\"ASSOCIATION_GROUP_INFO_REPORT\",\"_help\":\"Association Group Info Report\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Allow cache\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"ASSOCIATION_GROUP_COMMAND_LIST_GET\",\"_help\":\"Association Group Command List Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"List Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x06\",\"_name\":\"ASSOCIATION_GROUP_COMMAND_LIST_REPORT\",\"_help\":\"Association Group Command List Report\"}],\"_key\":\"0x59\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ASSOCIATION_GRP_INFO\",\"_help\":\"Command Class Association Group Info\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x01\",\"_name\":\"ASSOCIATION_GROUP_NAME_GET\",\"_help\":\"Association Group Name Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Length of Name\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x02\",\"_name\":\"ASSOCIATION_GROUP_NAME_REPORT\",\"_help\":\"Association Group Name Report\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"List Mode\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Refresh cache\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"ASSOCIATION_GROUP_INFO_GET\",\"_help\":\"Association Group Info Get\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Group Count\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Dynamic Info\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"List mode\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Profile General\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Profile Control\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Profile Sensor\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x03\",\"_flagname\":\"Profile Notification\",\"_flagmask\":\"0x71\"},{\"_key\":\"0x04\",\"_flagname\":\"Profile Meter\",\"_flagmask\":\"0x32\"}],\"_key\":\"0x02\",\"_name\":\"Profile1\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"multi_array\":[{\"paramdescloc\":{\"_key\":\"0x00\",\"_param\":\"2\",\"_paramdesc\":\"255\",\"_paramstart\":\"2\"}},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Profile General NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x00\",\"_flagname\":\"Profile General Lifeline\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY01\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY02\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY03\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY04\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY05\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY06\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY07\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY08\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY09\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY10\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY11\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY12\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY13\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY14\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY15\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY16\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY17\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY18\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY19\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY20\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY21\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY22\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY23\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY24\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY25\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY26\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY27\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY28\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY29\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY30\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY31\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY32\",\"_flagmask\":\"0x20\"}]},{\"bitflag\":[{\"_key\":\"0x31\",\"_flagname\":\"Profile MULTILEVEL_SENSOR_TYPE_TEMPERATURE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x31\",\"_flagname\":\"Profile MULTILEVEL_SENSOR_TYPE_HUMIDITY\",\"_flagmask\":\"0x05\"}]},{\"bitflag\":[{\"_key\":\"0x71\",\"_flagname\":\"Profile NOTIFICATION_TYPE_SMOKE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x71\",\"_flagname\":\"Profile NOTIFICATION_TYPE_CO2\",\"_flagmask\":\"0x03\"}]},{\"bitflag\":[{\"_key\":\"0x32\",\"_flagname\":\"Profile METER_TYPE_ELECTRIC\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x32\",\"_flagname\":\"Profile METER_TYPE_GAS\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x32\",\"_flagname\":\"Profile METER_TYPE_WATER\",\"_flagmask\":\"0x03\"}]}],\"_key\":\"0x03\",\"_name\":\"Profile2\",\"_type\":\"MULTI_ARRAY\",\"_typehashcode\":\"0x0A\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event Code\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x04\",\"_name\":\"ASSOCIATION_GROUP_INFO_REPORT\",\"_help\":\"Association Group Info Report\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Allow cache\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"ASSOCIATION_GROUP_COMMAND_LIST_GET\",\"_help\":\"Association Group Command List Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"List Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x06\",\"_name\":\"ASSOCIATION_GROUP_COMMAND_LIST_REPORT\",\"_help\":\"Association Group Command List Report\"}],\"_key\":\"0x59\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_ASSOCIATION_GRP_INFO\",\"_help\":\"Command Class Association Group Info\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x01\",\"_name\":\"ASSOCIATION_GROUP_NAME_GET\",\"_help\":\"Association Group Name Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Length of Name\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x02\",\"_name\":\"ASSOCIATION_GROUP_NAME_REPORT\",\"_help\":\"Association Group Name Report\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"List Mode\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Refresh cache\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"ASSOCIATION_GROUP_INFO_GET\",\"_help\":\"Association Group Info Get\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Group Count\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Dynamic Info\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"List mode\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Mode\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Profile General\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Profile Control\",\"_flagmask\":\"0x20\"},{\"_key\":\"0x02\",\"_flagname\":\"Profile Sensor\",\"_flagmask\":\"0x31\"},{\"_key\":\"0x03\",\"_flagname\":\"Profile Notification\",\"_flagmask\":\"0x71\"},{\"_key\":\"0x04\",\"_flagname\":\"Profile Meter\",\"_flagmask\":\"0x32\"},{\"_key\":\"0x05\",\"_flagname\":\"Profile Irrigation\",\"_flagmask\":\"0x6B\"}],\"_key\":\"0x02\",\"_name\":\"Profile1\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"multi_array\":[{\"paramdescloc\":{\"_key\":\"0x00\",\"_param\":\"2\",\"_paramdesc\":\"255\",\"_paramstart\":\"2\"}},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Profile General NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x00\",\"_flagname\":\"Profile General Lifeline\",\"_flagmask\":\"0x01\"}]},{\"bitflag\":[{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY01\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY02\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY03\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY04\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY05\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY06\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY07\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY08\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY09\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY10\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY11\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY12\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY13\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY14\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY15\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY16\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY17\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY18\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY19\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY20\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY21\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY22\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY23\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY24\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY25\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY26\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY27\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY28\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY29\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY30\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY31\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x20\",\"_flagname\":\"Profile Control KEY32\",\"_flagmask\":\"0x20\"}]},{\"bitflag\":[{\"_key\":\"0x31\",\"_flagname\":\"Profile MULTILEVEL_SENSOR_TYPE_TEMPERATURE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x31\",\"_flagname\":\"Profile MULTILEVEL_SENSOR_TYPE_HUMIDITY\",\"_flagmask\":\"0x05\"}]},{\"bitflag\":[{\"_key\":\"0x71\",\"_flagname\":\"Profile NOTIFICATION_TYPE_SMOKE\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x71\",\"_flagname\":\"Profile NOTIFICATION_TYPE_CO2\",\"_flagmask\":\"0x03\"}]},{\"bitflag\":[{\"_key\":\"0x32\",\"_flagname\":\"Profile METER_TYPE_ELECTRIC\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x32\",\"_flagname\":\"Profile METER_TYPE_GAS\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x32\",\"_flagname\":\"Profile METER_TYPE_WATER\",\"_flagmask\":\"0x03\"}]},{\"bitflag\":[{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 01\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 02\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 03\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 04\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 05\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 06\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 07\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 08\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 09\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 10\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 11\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 12\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 13\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 14\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 15\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 16\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 17\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 18\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 19\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 20\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 21\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 22\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 23\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 24\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 25\",\"_flagmask\":\"0x19\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 26\",\"_flagmask\":\"0x1A\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 27\",\"_flagmask\":\"0x1B\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 28\",\"_flagmask\":\"0x1C\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 29\",\"_flagmask\":\"0x1D\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 30\",\"_flagmask\":\"0x1E\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 31\",\"_flagmask\":\"0x1F\"},{\"_key\":\"0x6B\",\"_flagname\":\"Irrigation Channel 32\",\"_flagmask\":\"0x20\"}]}],\"_key\":\"0x03\",\"_name\":\"Profile2\",\"_type\":\"MULTI_ARRAY\",\"_typehashcode\":\"0x0A\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Reserved\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Event Code\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x04\",\"_name\":\"ASSOCIATION_GROUP_INFO_REPORT\",\"_help\":\"Association Group Info Report\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Allow cache\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"ASSOCIATION_GROUP_COMMAND_LIST_GET\",\"_help\":\"Association Group Command List Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"List Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x06\",\"_name\":\"ASSOCIATION_GROUP_COMMAND_LIST_REPORT\",\"_help\":\"Association Group Command List Report\"}],\"_key\":\"0x59\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_ASSOCIATION_GRP_INFO\",\"_help\":\"Command Class Association Group Info\",\"_read_only\":\"false\"},{\"cmd\":{\"_key\":\"0x01\",\"_name\":\"DEVICE_RESET_LOCALLY_NOTIFICATION\",\"_help\":\"Device Reset Locally Notification\"},\"_key\":\"0x5A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_DEVICE_RESET_LOCALLY\",\"_help\":\"Command Class Device Reset Locally\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"CENTRAL_SCENE_SUPPORTED_GET\",\"_help\":\"Central Scene Supported Get\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Supported Scenes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x02\",\"_name\":\"CENTRAL_SCENE_SUPPORTED_REPORT\",\"_help\":\"Central Scene Supported Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Key Attributes\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Scene Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"CENTRAL_SCENE_NOTIFICATION\",\"_help\":\"Central Scene Notification\"}],\"_key\":\"0x5B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_CENTRAL_SCENE\",\"_help\":\"Command Class Central Scene\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"CENTRAL_SCENE_SUPPORTED_GET\",\"_help\":\"Central Scene Supported Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Supported Scenes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Identical\",\"_flagmask\":\"0x01\"},\"bitfield\":[{\"_key\":\"0x01\",\"_fieldname\":\"Number of Bit Mask Bytes\",\"_fieldmask\":\"0x06\",\"_shifter\":\"1\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"129\",\"_lenmask\":\"0x06\",\"_lenoffs\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Key Pressed 1 time\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Key Released\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Key Held Down\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Key Pressed 2 times\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Key Pressed 3 times\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Key Pressed 4 times\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Key Pressed 5 times\",\"_flagmask\":\"0x06\"}],\"_key\":\"0x00\",\"_name\":\"Supported Key Attributes for Scene\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"CENTRAL_SCENE_SUPPORTED_REPORT\",\"_help\":\"Central Scene Supported Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Key Pressed 1 time\"},{\"_value\":\"Key Released\"},{\"_value\":\"Key Held Down\"},{\"_value\":\"Key Pressed 2 times\"},{\"_value\":\"Key Pressed 3 times\"},{\"_value\":\"Key Pressed 4 times\"},{\"_value\":\"Key Pressed 5 times\"}],\"_key\":\"0x00\",\"_fieldname\":\"Key Attributes\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Scene Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"CENTRAL_SCENE_NOTIFICATION\",\"_help\":\"Central Scene Notification\"}],\"_key\":\"0x5B\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_CENTRAL_SCENE\",\"_help\":\"Command Class Central Scene\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"CENTRAL_SCENE_SUPPORTED_GET\",\"_help\":\"Central Scene Supported Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Supported Scenes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Identical\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Slow Refresh Support\",\"_flagmask\":\"0x80\"}],\"bitfield\":[{\"_key\":\"0x01\",\"_fieldname\":\"Number of Bit Mask Bytes\",\"_fieldmask\":\"0x06\",\"_shifter\":\"1\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x78\",\"_shifter\":\"3\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"variant_group\":{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"129\",\"_lenmask\":\"0x06\",\"_lenoffs\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Key Pressed 1 time\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Key Released\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Key Held Down\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Key Pressed 2 times\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Key Pressed 3 times\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Key Pressed 4 times\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"Key Pressed 5 times\",\"_flagmask\":\"0x06\"}],\"_key\":\"0x00\",\"_name\":\"Supported Key Attributes for Scene\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x02\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x02\",\"_name\":\"CENTRAL_SCENE_SUPPORTED_REPORT\",\"_help\":\"Central Scene Supported Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Key Pressed 1 time\"},{\"_value\":\"Key Released\"},{\"_value\":\"Key Held Down\"},{\"_value\":\"Key Pressed 2 times\"},{\"_value\":\"Key Pressed 3 times\"},{\"_value\":\"Key Pressed 4 times\"},{\"_value\":\"Key Pressed 5 times\"}],\"_key\":\"0x00\",\"_fieldname\":\"Key Attributes\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x78\",\"_shifter\":\"3\"},\"bitflag\":{\"_key\":\"0x02\",\"_flagname\":\"Slow Refresh\",\"_flagmask\":\"0x80\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Scene Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"CENTRAL_SCENE_NOTIFICATION\",\"_help\":\"Central Scene Notification\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Slow Refresh\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x04\",\"_name\":\"CENTRAL_SCENE_CONFIGURATION_SET\",\"_help\":\"Central Scene Configuration Set\"},{\"_key\":\"0x05\",\"_name\":\"CENTRAL_SCENE_CONFIGURATION_GET\",\"_help\":\"Central Scene Configuration Get\"},{\"param\":{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Slow Refresh\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"CENTRAL_SCENE_CONFIGURATION_REPORT\",\"_help\":\"Central Scene Configuration Report\"}],\"_key\":\"0x5B\",\"_version\":\"3\",\"_name\":\"COMMAND_CLASS_CENTRAL_SCENE\",\"_help\":\"Command Class Central Scene\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"End Point\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"IP_ASSOCIATION_SET\",\"_help\":\"IP Association Set\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Index\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x02\",\"_name\":\"IP_ASSOCIATION_GET\",\"_help\":\"IP Association Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Index\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Actual Nodes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"End Point\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"IP_ASSOCIATION_REPORT\",\"_help\":\"IP Association Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Grouping Identifier\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"End Point\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"IP_ASSOCIATION_REMOVE\",\"_help\":\"IP Association Remove\"}],\"_key\":\"0x5C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_IP_ASSOCIATION\",\"_help\":\"Command Class Ip Association\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Number of Magic Code bytes\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Enable\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x7F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Magic Code\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Anti-theft Hint Number Bytes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Anti-theft Hint Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x01\",\"_name\":\"ANTITHEFT_SET\",\"_help\":\"Anti-theft Set\"},{\"_key\":\"0x02\",\"_name\":\"ANTITHEFT_GET\",\"_help\":\"Anti-theft Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Anti-theft Protection Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Anti-theft Hint Number Bytes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Anti-theft Hint Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x03\",\"_name\":\"ANTITHEFT_REPORT\",\"_help\":\"Anti-theft Report\"}],\"_key\":\"0x5D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ANTITHEFT\",\"_help\":\"Command Class Anti-theft\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Number of Magic Code bytes\",\"_fieldmask\":\"0x7F\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Enable\",\"_flagmask\":\"0x80\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x7F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Magic Code\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Anti-theft Hint Number Bytes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Anti-theft Hint Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x01\",\"_name\":\"ANTITHEFT_SET\",\"_help\":\"Anti-theft Set\"},{\"_key\":\"0x02\",\"_name\":\"ANTITHEFT_GET\",\"_help\":\"Anti-theft Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Anti-theft Protection Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Manufacturer ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Anti-theft Hint Number Bytes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Anti-theft Hint Byte\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x03\",\"_name\":\"ANTITHEFT_REPORT\",\"_help\":\"Anti-theft Report\"}],\"_key\":\"0x5D\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_ANTITHEFT\",\"_help\":\"Command Class Anti-theft\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"ZWAVEPLUS_INFO_GET\",\"_help\":\"Z-Wave+ Info Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Z-Wave+ Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_CENTRAL_STATIC\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_SUB_STATIC\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_PORTABLE\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_PORTABLE_REPORTING\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"ROLE_TYPE_SLAVE_PORTABLE\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"ROLE_TYPE_SLAVE_ALWAYS_ON\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ROLE_TYPE_SLAVE_SLEEPING_REPORTING\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ROLE_TYPE_SLAVE_SLEEPING_LISTENING\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x01\",\"_name\":\"Role Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_NODE\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_FOR_IP_ROUTER\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_FOR_IP_GATEWAY\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_FOR_IP_CLIENT_IP_NODE\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_FOR_IP_CLIENT_ZWAVE_NODE\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x02\",\"_name\":\"Node Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"ZWAVEPLUS_INFO_REPORT\",\"_help\":\"Z-Wave+ Info Report\"}],\"_key\":\"0x5E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZWAVEPLUS_INFO\",\"_help\":\"Command Class Z-Wave+ Info\",\"_read_only\":\"false\",\"_comment\":\"SDS11907-3\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"ZWAVEPLUS_INFO_GET\",\"_help\":\"Z-Wave+ Info Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Z-Wave+ Version\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_CENTRAL_STATIC\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_SUB_STATIC\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_PORTABLE\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"ROLE_TYPE_CONTROLLER_PORTABLE_REPORTING\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"ROLE_TYPE_SLAVE_PORTABLE\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"ROLE_TYPE_SLAVE_ALWAYS_ON\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ROLE_TYPE_SLAVE_SLEEPING_REPORTING\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"ROLE_TYPE_SLAVE_SLEEPING_LISTENING\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x01\",\"_name\":\"Role Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_NODE\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"NODE_TYPE_ZWAVEPLUS_FOR_IP_GATEWAY\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x02\",\"_name\":\"Node Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Installer Icon Type\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"User Icon Type\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x02\",\"_name\":\"ZWAVEPLUS_INFO_REPORT\",\"_help\":\"Z-Wave+ Info Report\"}],\"_key\":\"0x5E\",\"_version\":\"2\",\"_name\":\"COMMAND_CLASS_ZWAVEPLUS_INFO\",\"_help\":\"Command Class Z-Wave+ Info\",\"_read_only\":\"false\",\"_comment\":\"SDS11907-3\"},{\"cmd\":[{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Stand-alone\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Portal\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"GATEWAY_MODE_SET\",\"_help\":\"Gateway Mode Set\"},{\"_key\":\"0x02\",\"_name\":\"GATEWAY_MODE_GET\",\"_help\":\"Gateway Mode Get\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Stand-alone\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Portal\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Mode\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"GATEWAY_MODE_REPORT\",\"_help\":\"Gateway Mode Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Peer Profile\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Port\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Peer Name Length\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x03\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Peer Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x04\",\"_name\":\"GATEWAY_PEER_SET\",\"_help\":\"Gateway Peer Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Peer Profile\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x05\",\"_name\":\"GATEWAY_PEER_GET\",\"_help\":\"Gateway Peer Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Peer Profile\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Peer Count\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Port\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Peer Name Length\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x04\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x3F\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Peer Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x06\",\"_name\":\"GATEWAY_PEER_REPORT\",\"_help\":\"Gateway Peer Report\"},{\"param\":{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Lock\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Show\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"GATEWAY_LOCK_SET\",\"_help\":\"Gateway Lock Set\"},{\"param\":[{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Unsolicited IPv6 Destination\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Unsolicited Destination Port\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x08\",\"_name\":\"UNSOLICITED_DESTINATION_SET\",\"_help\":\"Unsolicited Destination Set \"},{\"_key\":\"0x09\",\"_name\":\"UNSOLICITED_DESTINATION_GET\",\"_help\":\"Unsolicited Destination Get\"},{\"param\":[{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Unsolicited IPv6 Destination\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Unsolicited Destination Port\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x0A\",\"_name\":\"UNSOLICITED_DESTINATION_REPORT\",\"_help\":\"Unsolicited Destination Report\"},{\"param\":[{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Non-Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Security Scheme 0 MARK\",\"_flagmask\":\"0xF1\"},{\"_key\":\"0x01\",\"_flagname\":\"Security Scheme 0 MARK\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x01\",\"_name\":\"Security Scheme 0 MARK\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Security Scheme 0 Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0B\",\"_name\":\"COMMAND_APPLICATION_NODE_INFO_SET\",\"_help\":\"Application Node Info Set\"},{\"_key\":\"0x0C\",\"_name\":\"COMMAND_APPLICATION_NODE_INFO_GET\",\"_help\":\"Application Node Info Get\"},{\"param\":[{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Non-Secure Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Security Scheme 0 MARK\",\"_flagmask\":\"0xF1\"},{\"_key\":\"0x01\",\"_flagname\":\"Security Scheme 0 MARK\",\"_flagmask\":\"0x00\"}],\"_key\":\"0x01\",\"_name\":\"Security Scheme 0 MARK\",\"_type\":\"MARKER\",\"_typehashcode\":\"0x0E\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Security Scheme 0 Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x0D\",\"_name\":\"COMMAND_APPLICATION_NODE_INFO_REPORT\",\"_help\":\"Application Node Info Report\"}],\"_key\":\"0x5F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZIP_GATEWAY\",\"_help\":\"Command Class Z/IP Gateway\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"LAN IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"LAN IPv6 Prefix Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Portal IPv6 Prefix\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Portal IPv6 Prefix Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Default Gateway IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"PAN IPv6 Prefix\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x01\",\"_name\":\"GATEWAY_CONFIGURATION_SET\",\"_help\":\"Gateway Configuration Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Status\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x02\",\"_name\":\"GATEWAY_CONFIGURATION_STATUS\",\"_help\":\"Gateway Configuration Status\"},{\"_key\":\"0x03\",\"_name\":\"GATEWAY_CONFIGURATION_GET\",\"_help\":\"Gateway Configuration Get\"},{\"param\":[{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"LAN IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"LAN IPv6 Prefix Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Portal IPv6 Prefix\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Portal IPv6 Prefix Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Default Gateway IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"PAN IPv6 Prefix\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x04\",\"_name\":\"GATEWAY_CONFIGURATION_REPORT\",\"_help\":\"Gateway Configuration Report\"}],\"_key\":\"0x61\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZIP_PORTAL\",\"_help\":\"Command Class Z/IP Portal\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Page ID\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Channel ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"DMX_ADDRESS_SET\",\"_help\":\"DMX Address Set\"},{\"_key\":\"0x02\",\"_name\":\"DMX_ADDRESS_GET\",\"_help\":\"DMX Address Get\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Page ID\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Channel ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x03\",\"_name\":\"DMX_ADDRESS_REPORT\",\"_help\":\"DMX Address Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Channel ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x04\",\"_name\":\"DMX_CAPABILITY_GET\",\"_help\":\"DMX Capability Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Channel ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Property ID\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Device Channels\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Max Channels\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"DMX_CAPABILITY_REPORT\",\"_help\":\"DMX Capability Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Source\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Page\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Sequence No\",\"_fieldmask\":\"0x30\",\"_shifter\":\"4\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xC0\",\"_shifter\":\"6\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"DMX channel\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x06\",\"_name\":\"DMX_DATA\",\"_help\":\"DMX Data\"}],\"_key\":\"0x65\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_DMX\",\"_help\":\"Command Class DMX\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"CLOSE\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"OPEN\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"Target Value\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x01\",\"_name\":\"BARRIER_OPERATOR_SET\",\"_help\":\"Barrier Operator Set\"},{\"_key\":\"0x02\",\"_name\":\"BARRIER_OPERATOR_GET\",\"_help\":\"Barrier Operator Get\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Closed\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Closing\",\"_flagmask\":\"0xFC\"},{\"_key\":\"0x02\",\"_flagname\":\"Stopped\",\"_flagmask\":\"0xFD\"},{\"_key\":\"0x03\",\"_flagname\":\"Opening\",\"_flagmask\":\"0xFE\"},{\"_key\":\"0x04\",\"_flagname\":\"Open\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x00\",\"_name\":\"State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"BARRIER_OPERATOR_REPORT\",\"_help\":\"Barrier Operator Report\"},{\"_key\":\"0x04\",\"_name\":\"BARRIER_OPERATOR_SIGNAL_SUPPORTED_GET\",\"_help\":\"Barrier Operator Signal Supported Get\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"NOT SUPPORTED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Audible Notification\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Visual Notification\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x05\",\"_name\":\"BARRIER_OPERATOR_SIGNAL_SUPPORTED_REPORT\",\"_help\":\"Barrier Operator Signal Supported Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NOT SUPPORTED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Audible Notification\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Visual Notification\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Subsystem Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"OFF\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ON\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Subsystem State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x06\",\"_name\":\"BARRIER_OPERATOR_SIGNAL_SET\",\"_help\":\"Barrier Operator Signal Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NOT SUPPORTED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Audible Notification\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Visual Notification\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Subsystem Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x07\",\"_name\":\"BARRIER_OPERATOR_SIGNAL_GET\",\"_help\":\"Barrier Operator Signal Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"NOT SUPPORTED\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x02\",\"_flagname\":\"Audible Notification\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x03\",\"_flagname\":\"Visual Notification\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Subsystem Type\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"OFF\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"ON\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Subsystem State\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x08\",\"_name\":\"BARRIER_OPERATOR_SIGNAL_REPORT\",\"_help\":\"Barrier Operator Signal Report\"}],\"_key\":\"0x66\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_BARRIER_OPERATOR\",\"_help\":\"Command Class Barrier Operator\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Repeater 1\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Repeater 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Repeater 3\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x04\",\"_name\":\"Repeater 4\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"9.6 kbit/sec\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"40 kbit/sec\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"100 kbit/sec\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x05\",\"_name\":\"Speed\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x01\",\"_name\":\"LAST_WORKING_ROUTE_SET\",\"_help\":\"Last Working Route Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},\"_key\":\"0x02\",\"_name\":\"LAST_WORKING_ROUTE_GET\",\"_help\":\"Last Working Route Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Repeater 1\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Repeater 2\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Repeater 3\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x04\",\"_name\":\"Repeater 4\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"9.6 kbit/sec\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"40 kbit/sec\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"100 kbit/sec\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x05\",\"_name\":\"Speed\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x03\",\"_name\":\"LAST_WORKING_ROUTE_REPORT\",\"_help\":\"Last Working Route Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},\"_key\":\"0x04\",\"_name\":\"STATISTICS_GET\",\"_help\":\"Statistics Get\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"NodeID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},\"variant_group\":{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Route Changes (RC)\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Transmission Count (TC)\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Neighbors (NB)\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Packet Error Count (PEC)\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"Sum of transmission times (TS)\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"Sum of transmission times squrared (TS2)\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x00\",\"_name\":\"Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x01\",\"_name\":\"Statistics\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"STATISTICS_REPORT\",\"_help\":\"Statistics Report\"},{\"_key\":\"0x06\",\"_name\":\"STATISTICS_CLEAR\",\"_help\":\"Statistics Clear\"}],\"_key\":\"0x67\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_NETWORK_MANAGEMENT_INSTALLATION_MAINTENANCE\",\"_help\":\"Command Class Network Management Installation and Maintenance\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},\"_key\":\"0x01\",\"_name\":\"ZIP_NAMING_NAME_SET\",\"_help\":\"Z/IP Name Set\"},{\"_key\":\"0x02\",\"_name\":\"ZIP_NAMING_NAME_GET\",\"_help\":\"Z/IP Name Get\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Name\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},\"_key\":\"0x03\",\"_name\":\"ZIP_NAMING_NAME_REPORT\",\"_help\":\"Z/IP Name Report\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Location\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},\"_key\":\"0x04\",\"_name\":\"ZIP_NAMING_LOCATION_SET\",\"_help\":\"Z/IP Location Set\"},{\"_key\":\"0x05\",\"_name\":\"ZIP_NAMING_LOCATION_GET\",\"_help\":\"Z/IP Location Get\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_is_ascii\":\"true\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Location\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},\"_key\":\"0x06\",\"_name\":\"ZIP_NAMING_LOCATION_REPORT\",\"_help\":\"Z/IP Location Report\"}],\"_key\":\"0x68\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ZIP_NAMING\",\"_help\":\"Command Class Z/IP Naming and Location\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"MAILBOX_CONFIGURATION_GET\",\"_help\":\"Mailbox Configuration Get\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Disable\"},{\"_value\":\"Enable Mailbox Service\"},{\"_value\":\"Enable Mailbox Proxy\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Forwarding Destination IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"UDP Port Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x02\",\"_name\":\"MAILBOX_CONFIGURATION_SET\",\"_help\":\"Mailbox Configuration Set\"},{\"param\":[{\"fieldenum\":[{\"fieldenum\":[{\"_value\":\"Disable\"},{\"_value\":\"Enable Mailbox Service\"},{\"_value\":\"Enable Mailbox Proxy\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"fieldenum\":[{\"_value\":\"Mailbox Service supported\"},{\"_value\":\"Mailbox Proxy supported\"}],\"_key\":\"0x01\",\"_fieldname\":\"Supported Modes\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Mailbox Capacity\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Forwarding Destination IPv6 Address\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"UDP Port Number\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x03\",\"_name\":\"MAILBOX_CONFIGURATION_REPORT\",\"_help\":\"Mailbox Configuration Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Push\"},{\"_value\":\"Pop\"},{\"_value\":\"Waiting\"},{\"_value\":\"Ping\"},{\"_value\":\"ACK\"},{\"_value\":\"NACK\"},{\"_value\":\"Queue Full\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitflag\":{\"_key\":\"0x01\",\"_flagname\":\"Last\",\"_flagmask\":\"0x04\"},\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF8\",\"_shifter\":\"3\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Queue Handle\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Mailbox Entry\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x04\",\"_name\":\"MAILBOX_QUEUE\",\"_help\":\"Mailbox Queue\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Queue Handle\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x05\",\"_name\":\"MAILBOX_WAKEUP_NOTIFICATION\",\"_help\":\"Mailbox Wakeup Notification\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Queue Handle\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x06\",\"_name\":\"MAILBOX_NODE_FAILING\",\"_help\":\"Mailbox Failing Node\"}],\"_key\":\"0x69\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_MAILBOX\",\"_help\":\"Command Class Mailbox\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"WINDOW_COVERING_SUPPORTED_GET\",\"_help\":\"Window Covering Supported Get\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Number of Parameter Mask bytes\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x0F\",\"_lenoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Parameter Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x02\",\"_name\":\"WINDOW_COVERING_SUPPORTED_REPORT\",\"_help\":\"Window Covering Supported Report\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"out_left 1\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"out_left 2\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"out_right 1\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"out_right 2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"in_left 1\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"in_left 2\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"in_right 1\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"in_right 2\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"in_right_left 1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"in_right_left 2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Vertical slats angle 1\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Vertical slats angle 2\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"out_bottom 1\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"out_bottom 2\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"out_top 1\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"out_top 2\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"in_bottom 1\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"in_bottom 2\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"in_top 1\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x13\",\"_flagname\":\"in_top 2\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x14\",\"_flagname\":\"in_top_bottom 1\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x15\",\"_flagname\":\"in_top_bottom 2\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x16\",\"_flagname\":\"Horizontal slats angle 1\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x17\",\"_flagname\":\"Horizontal slats angle 2\",\"_flagmask\":\"0x16\"}],\"_key\":\"0x00\",\"_name\":\"Parameter ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x03\",\"_name\":\"WINDOW_COVERING_GET\",\"_help\":\"Window Covering Get\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"out_left 1\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"out_left 2\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"out_right 1\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"out_right 2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"in_left 1\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"in_left 2\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"in_right 1\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"in_right 2\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"in_right_left 1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"in_right_left 2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Vertical slats angle 1\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Vertical slats angle 2\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"out_bottom 1\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"out_bottom 2\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"out_top 1\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"out_top 2\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"in_bottom 1\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"in_bottom 2\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"in_top 1\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x13\",\"_flagname\":\"in_top 2\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x14\",\"_flagname\":\"in_top_bottom 1\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x15\",\"_flagname\":\"in_top_bottom 2\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x16\",\"_flagname\":\"Horizontal slats angle 1\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x17\",\"_flagname\":\"Horizontal slats angle 2\",\"_flagmask\":\"0x16\"}],\"_key\":\"0x00\",\"_name\":\"Parameter ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Current Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Target Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"WINDOW_COVERING_REPORT\",\"_help\":\"Window Covering Report\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Parameter Count\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"variant_group\":{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"out_left 1\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"out_left 2\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"out_right 1\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"out_right 2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"in_left 1\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"in_left 2\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"in_right 1\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"in_right 2\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"in_right_left 1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"in_right_left 2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Vertical slats angle 1\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Vertical slats angle 2\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"out_bottom 1\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"out_bottom 2\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"out_top 1\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"out_top 2\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"in_bottom 1\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"in_bottom 2\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"in_top 1\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x13\",\"_flagname\":\"in_top 2\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x14\",\"_flagname\":\"in_top_bottom 1\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x15\",\"_flagname\":\"in_top_bottom 2\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x16\",\"_flagname\":\"Horizontal slats angle 1\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x17\",\"_flagname\":\"Horizontal slats angle 2\",\"_flagmask\":\"0x16\"}],\"_key\":\"0x00\",\"_name\":\"Parameter ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Value\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0x00\",\"_sizemask\":\"0x1F\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x05\",\"_name\":\"WINDOW_COVERING_SET\",\"_help\":\"Window Covering Set\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Res1\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Up Down\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Res2\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"out_left 1\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"out_left 2\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"out_right 1\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"out_right 2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"in_left 1\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"in_left 2\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"in_right 1\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"in_right 2\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"in_right_left 1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"in_right_left 2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Vertical slats angle 1\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Vertical slats angle 2\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"out_bottom 1\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"out_bottom 2\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"out_top 1\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"out_top 2\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"in_bottom 1\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"in_bottom 2\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"in_top 1\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x13\",\"_flagname\":\"in_top 2\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x14\",\"_flagname\":\"in_top_bottom 1\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x15\",\"_flagname\":\"in_top_bottom 2\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x16\",\"_flagname\":\"Horizontal slats angle 1\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x17\",\"_flagname\":\"Horizontal slats angle 2\",\"_flagmask\":\"0x16\"}],\"_key\":\"0x01\",\"_name\":\"Parameter ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x06\",\"_name\":\"WINDOW_COVERING_START_LEVEL_CHANGE\",\"_help\":\"Window Covering Start Level Change\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"out_left 1\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"out_left 2\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"out_right 1\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"out_right 2\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"in_left 1\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"in_left 2\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"in_right 1\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"in_right 2\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"in_right_left 1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"in_right_left 2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"Vertical slats angle 1\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"Vertical slats angle 2\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"out_bottom 1\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"out_bottom 2\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"out_top 1\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"out_top 2\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"in_bottom 1\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"in_bottom 2\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"in_top 1\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x13\",\"_flagname\":\"in_top 2\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x14\",\"_flagname\":\"in_top_bottom 1\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x15\",\"_flagname\":\"in_top_bottom 2\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x16\",\"_flagname\":\"Horizontal slats angle 1\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x17\",\"_flagname\":\"Horizontal slats angle 2\",\"_flagmask\":\"0x16\"}],\"_key\":\"0x00\",\"_name\":\"Parameter ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x07\",\"_name\":\"WINDOW_COVERING_STOP_LEVEL_CHANGE\",\"_help\":\"Window Covering Stop Level Change\"}],\"_key\":\"0x6A\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_WINDOW_COVERING\",\"_help\":\"Command Class Window Covering\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x01\",\"_name\":\"SECURITY_2_NONCE_GET\",\"_help\":\"S2 Nonce Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"SOS\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"MOS\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Receivers Entropy Input\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x02\",\"_name\":\"SECURITY_2_NONCE_REPORT\",\"_help\":\"S2 Nonce Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Extension\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Encrypted Extension\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"CCM Ciphertext Object\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Extension Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Type\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Critical\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"More to follow\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"0\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\",\"_sizechange\":\"-2\"},\"_key\":\"0x02\",\"_name\":\"Extension\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x02\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_optionaloffs\":\"0x01\",\"_optionalmask\":\"0x01\",\"_moretofollowoffs\":\"0x01\",\"_moretofollowmask\":\"0x80\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x03\",\"_name\":\"SECURITY_2_MESSAGE_ENCAPSULATION\",\"_help\":\"S2 Message Encapsulation\"},{\"_key\":\"0x04\",\"_name\":\"KEX_GET\",\"_help\":\"KEX Get\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Echo\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Request CSA\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Supported KEX Schemes\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Supported ECDH Profiles\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Unauthenticated\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Authenticated\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Access\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"S0\",\"_flagmask\":\"0x08\"}],\"_key\":\"0x03\",\"_name\":\"Requested Keys\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x05\",\"_name\":\"KEX_REPORT\",\"_help\":\"KEX Report\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Echo\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Request CSA\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Selected KEX Scheme\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Selected ECDH Profile\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Unauthenticated\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Authenticated\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"Access\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"S0\",\"_flagmask\":\"0x08\"}],\"_key\":\"0x03\",\"_name\":\"Granted Keys\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x06\",\"_name\":\"KEX_SET\",\"_help\":\"KEX Set\"},{\"param\":{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"KEX_KEY\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"KEX_SCHEME\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"KEX_CURVES\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"DECRYPT\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x04\",\"_flagname\":\"CANCEL\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x05\",\"_flagname\":\"AUTH\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x06\",\"_flagname\":\"KEY_GET\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x07\",\"_flagname\":\"KEY_VERIFY\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x08\",\"_flagname\":\"KEY_REPORT\",\"_flagmask\":\"0x0A\"}],\"_key\":\"0x00\",\"_name\":\"KEX Fail Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},\"_key\":\"0x07\",\"_name\":\"KEX_FAIL\",\"_help\":\"KEX Fail\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Including Node\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"ECDH Public Key\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x08\",\"_name\":\"PUBLIC_KEY_REPORT\",\"_help\":\"Public Key Report\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Unauthenticated\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Authenticated\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Access\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"S0\",\"_flagmask\":\"0x08\"}],\"_key\":\"0x00\",\"_name\":\"Requested Key\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x09\",\"_name\":\"SECURITY_2_NETWORK_KEY_GET\",\"_help\":\"S2 Network Key Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"true\",\"_showhex\":\"true\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Unauthenticated\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Authenticated\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Access\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"S0\",\"_flagmask\":\"0x08\"}],\"_key\":\"0x00\",\"_name\":\"Granted Key\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"arrayattrib\":{\"_key\":\"0x00\",\"_len\":\"16\",\"_is_ascii\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Network Key\",\"_type\":\"ARRAY\",\"_typehashcode\":\"0x05\"}],\"_key\":\"0x0A\",\"_name\":\"SECURITY_2_NETWORK_KEY_REPORT\",\"_help\":\"S2 Network Key Report\"},{\"_key\":\"0x0B\",\"_name\":\"SECURITY_2_NETWORK_KEY_VERIFY\",\"_help\":\"S2 Network Key Verify\"},{\"param\":{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Key Request Complete\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Key Verified\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x0C\",\"_name\":\"SECURITY_2_TRANSFER_END\",\"_help\":\"S2 Transfer End\"},{\"_key\":\"0x0D\",\"_name\":\"SECURITY_2_COMMANDS_SUPPORTED_GET\",\"_help\":\"S2 Commands Supported Get\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Command Class\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_encaptype\":\"CMD_CLASS_REF\"},\"_key\":\"0x0E\",\"_name\":\"SECURITY_2_COMMANDS_SUPPORTED_REPORT\",\"_help\":\"S2 Commands Supported Report\"},{\"_key\":\"0x0F\",\"_name\":\"SECURITY_2_CAPABILITIES_GET\",\"_help\":\"S2 Capabilities Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Supported SPANs\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Supported MPANs\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x10\",\"_name\":\"SECURITY_2_CAPABILITIES_REPORT\",\"_help\":\"S2 Capabilities Report\"}],\"_key\":\"0x9F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SECURITY_2\",\"_help\":\"Command Class Security 2\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"IRRIGATION_SYSTEM_INFO_GET\",\"_help\":\"Irrigation System Info Get\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":[{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0x06\",\"_shifter\":\"1\"},{\"_key\":\"0x02\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x03\",\"_fieldname\":\"Reserved3\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Total Number of Valves\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x02\",\"_name\":\"Total Number of Valve Tables\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Valve Table Max Size\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"}],\"_key\":\"0x03\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"}],\"_key\":\"0x02\",\"_name\":\"IRRIGATION_SYSTEM_INFO_REPORT\",\"_help\":\"Irrigation System Info Report\"},{\"_key\":\"0x03\",\"_name\":\"IRRIGATION_SYSTEM_STATUS_GET\",\"_help\":\"Irrigation System Status Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"System Voltage\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"Flow Sensor Detected\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Pressure Sensor Detected\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Rain Sensor Detected\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"Moisture Sensor Detected\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x01\",\"_name\":\"Sensor Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Flow Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Flow Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Flow Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x02\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"2\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x03\",\"_name\":\"Flow Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Pressure Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Pressure Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Pressure Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Pressure Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Shutoff Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"not programmed\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"emergency shutdown\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"high threshold triggered\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"low threshold triggered\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"valve errors\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x07\",\"_name\":\"System Error Status\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x08\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x09\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x04\",\"_name\":\"IRRIGATION_SYSTEM_STATUS_REPORT\",\"_help\":\"Irrigation System Status Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Master Valve Delay\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"High Pressure Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"High Pressure Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"High Pressure Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"High Pressure Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Low Pressure Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Low Pressure Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Low Pressure Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x03\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Low Pressure Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Rain Sensor Polarity\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Moisture Sensor Polarity\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Valid\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x05\",\"_name\":\"Sensor Polarity\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x05\",\"_name\":\"IRRIGATION_SYSTEM_CONFIG_SET\",\"_help\":\"Irrigation System Config Set\"},{\"_key\":\"0x06\",\"_name\":\"IRRIGATION_SYSTEM_CONFIG_GET\",\"_help\":\"Irrigation System Config Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Master Valve Delay\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"High Pressure Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"High Pressure Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"High Pressure Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"High Pressure Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Low Pressure Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Low Pressure Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Low Pressure Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x03\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Low Pressure Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Rain Sensor Polarity\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Moisture Sensor Polarity\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Valid\",\"_flagmask\":\"0x07\"}],\"_key\":\"0x05\",\"_name\":\"Sensor Polarity\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x07\",\"_name\":\"IRRIGATION_SYSTEM_CONFIG_REPORT\",\"_help\":\"Irrigation System Config Report\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x08\",\"_name\":\"IRRIGATION_VALVE_INFO_GET\",\"_help\":\"Irrigation Valve Info Get\"},{\"param\":[{\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Master\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Connected\",\"_flagmask\":\"0x02\"}],\"bitfield\":{\"_key\":\"0x02\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Nominal Current\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"short circuit\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"current high threshold\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"current low threshold\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"maximum flow\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"flow high threshold\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"flow low threshold\",\"_flagmask\":\"0x05\"}],\"_key\":\"0x03\",\"_name\":\"Valve Error Status\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x09\",\"_name\":\"IRRIGATION_VALVE_INFO_REPORT\",\"_help\":\"Irrigation Valve Info Report\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Nominal Current High Threshold\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Nominal Current Low Threshold\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Maximum Flow Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Maximum Flow Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Maximum Flow Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Maximum Flow Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Flow High Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Flow High Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Flow High Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Flow High Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Flow Low Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Flow Low Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Flow Low Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x08\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"8\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x09\",\"_name\":\"Flow Low Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Use Rain Sensor\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Use Moisture Sensor\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x0A\",\"_name\":\"Sensor Usage\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x0A\",\"_name\":\"IRRIGATION_VALVE_CONFIG_SET\",\"_help\":\"Irrigation Valve Config Set\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x0B\",\"_name\":\"IRRIGATION_VALVE_CONFIG_GET\",\"_help\":\"Irrigation Valve Config Get\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Nominal Current High Threshold\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x03\",\"_name\":\"Nominal Current Low Threshold\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Maximum Flow Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Maximum Flow Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Maximum Flow Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x04\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"4\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x05\",\"_name\":\"Maximum Flow Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Flow High Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Flow High Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Flow High Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x06\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"6\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x07\",\"_name\":\"Flow High Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Flow Low Threshold Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Flow Low Threshold Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},{\"_key\":\"0x02\",\"_fieldname\":\"Flow Low Threshold Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x08\",\"_name\":\"Properties4\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"8\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x09\",\"_name\":\"Flow Low Threshold Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Use Rain Sensor\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Use Moisture Sensor\",\"_flagmask\":\"0x01\"}],\"_key\":\"0x0A\",\"_name\":\"Sensor Usage\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x0C\",\"_name\":\"IRRIGATION_VALVE_CONFIG_REPORT\",\"_help\":\"Irrigation Valve Config Report\"},{\"param\":[{\"bitflag\":{\"_key\":\"0x00\",\"_flagname\":\"Master Valve\",\"_flagmask\":\"0x01\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFE\",\"_shifter\":\"1\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x0D\",\"_name\":\"IRRIGATION_VALVE_RUN\",\"_help\":\"Irrigation Valve Run\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Valve Table ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Duration\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x0E\",\"_name\":\"IRRIGATION_VALVE_TABLE_SET\",\"_help\":\"Irrigation Valve Table Set\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Valve Table ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x0F\",\"_name\":\"IRRIGATION_VALVE_TABLE_GET\",\"_help\":\"Irrigation Valve Table Get\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Valve Table ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"variant_group\":{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Valve ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"word\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Duration\",\"_type\":\"WORD\",\"_typehashcode\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"vg1\",\"_variantKey\":\"0x00\",\"_paramOffs\":\"0xFF\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0x00\",\"_typehashcode\":\"0x0D\"},\"_key\":\"0x10\",\"_name\":\"IRRIGATION_VALVE_TABLE_REPORT\",\"_help\":\"Irrigation Valve Table Report\"},{\"param\":{\"variant\":{\"_paramoffs\":\"255\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0x00\",\"_sizeoffs\":\"0\"},\"_key\":\"0x00\",\"_name\":\"Valve Table ID\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},\"_key\":\"0x11\",\"_name\":\"IRRIGATION_VALVE_TABLE_RUN\",\"_help\":\"Irrigation Valve Table Run\"},{\"param\":{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},\"_key\":\"0x12\",\"_name\":\"IRRIGATION_SYSTEM_SHUTOFF\",\"_help\":\"Irrigation System Shutoff\"}],\"_key\":\"0x6B\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_IRRIGATION\",\"_help\":\"Command Class Irrigation\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Session ID\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"Status Updates\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x01\",\"_name\":\"Encapsulated Command Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Encapsulated Command\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_encaptype\":\"CMD_ENCAP\",\"_skipfield\":\"true\"}],\"_key\":\"0x01\",\"_name\":\"SUPERVISION_GET\",\"_help\":\"Supervision Get\"},{\"param\":[{\"bitfield\":{\"_key\":\"0x00\",\"_fieldname\":\"Session ID\",\"_fieldmask\":\"0x3F\",\"_shifter\":\"0\"},\"bitflag\":[{\"_key\":\"0x01\",\"_flagname\":\"Reserved\",\"_flagmask\":\"0x40\"},{\"_key\":\"0x02\",\"_flagname\":\"More Status Updates\",\"_flagmask\":\"0x80\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"NO_SUPPORT\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"WORKING\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"FAIL\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"BUSY\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"SUCCESS\",\"_flagmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x02\",\"_name\":\"Duration\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x02\",\"_name\":\"SUPERVISION_REPORT\",\"_help\":\"Supervision Report\"}],\"_key\":\"0x6C\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_SUPERVISION\",\"_help\":\"Command Class Supervision\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_key\":\"0x01\",\"_value\":\"Humidifier\"},{\"_key\":\"0x02\",\"_value\":\"Dehumidifier\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Percentage\"},{\"_value\":\"Absolute\"}],\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x01\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_SET\",\"_help\":\"Humidity Control Setpoint Set\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_key\":\"0x01\",\"_value\":\"Humidifier\"},{\"_key\":\"0x02\",\"_value\":\"Dehumidifier\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_GET\",\"_help\":\"Humidity Control Setpoint Get\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_key\":\"0x01\",\"_value\":\"Humidifier\"},{\"_key\":\"0x02\",\"_value\":\"Dehumidifier\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Percentage\"},{\"_value\":\"Absolute\"}],\"_key\":\"0x01\",\"_fieldname\":\"Scale\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x03\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_REPORT\",\"_help\":\"Humidity Control Setpoint Report\"},{\"_key\":\"0x04\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_SUPPORTED_GET\",\"_help\":\"Humidity Control Setpoint Supported Get\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Humidifier\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"Dehumidifier\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x05\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_SUPPORTED_REPORT\",\"_help\":\"Humidity Control Setpoint Supported Report\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_key\":\"0x01\",\"_value\":\"Humidifier\"},{\"_key\":\"0x02\",\"_value\":\"Dehumidifier\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x06\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_SCALE_SUPPORTED_GET\",\"_help\":\"Humidity Control Setpoint Scale Supported Get\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Percentage\"},{\"_value\":\"Absolute\"}],\"_key\":\"0x00\",\"_fieldname\":\"Scale Bit Mask\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x07\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_SCALE_SUPPORTED_REPORT\",\"_help\":\"Humidity Control Setpoint Scale Supported Report\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_key\":\"0x01\",\"_value\":\"Humidifier\"},{\"_key\":\"0x02\",\"_value\":\"Dehumidifier\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x08\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_CAPABILITIES_GET\",\"_help\":\"Humidity Control Setpoint Capabilities Get\"},{\"param\":[{\"fieldenum\":{\"fieldenum\":[{\"_key\":\"0x01\",\"_value\":\"Humidifier\"},{\"_key\":\"0x02\",\"_value\":\"Dehumidifier\"}],\"_key\":\"0x00\",\"_fieldname\":\"Setpoint Type\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size1\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision1\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Percentage\"},{\"_value\":\"Absolute\"}],\"_key\":\"0x01\",\"_fieldname\":\"Scale1\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},\"_key\":\"0x01\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"1\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x02\",\"_name\":\"Minimum Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Size2\",\"_fieldmask\":\"0x07\",\"_shifter\":\"0\"},{\"_key\":\"0x02\",\"_fieldname\":\"Precision2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Percentage\"},{\"_value\":\"Absolute\"}],\"_key\":\"0x01\",\"_fieldname\":\"Scale2\",\"_fieldmask\":\"0x18\",\"_shifter\":\"3\"},\"_key\":\"0x03\",\"_name\":\"Properties3\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"false\",\"_signed\":\"true\",\"_sizemask\":\"0x07\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Maximum Value\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\"}],\"_key\":\"0x09\",\"_name\":\"HUMIDITY_CONTROL_SETPOINT_CAPABILITIES_REPORT\",\"_help\":\"Humidity Control Setpoint Capabilities Report\"}],\"_key\":\"0x64\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_HUMIDITY_CONTROL_SETPOINT\",\"_help\":\"Command Class Humidity Control Setpoint\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Humidify\"},{\"_value\":\"Dehumidify\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x01\",\"_name\":\"HUMIDITY_CONTROL_MODE_SET\",\"_help\":\"Humidity Control Mode Set\"},{\"_key\":\"0x02\",\"_name\":\"HUMIDITY_CONTROL_MODE_GET\",\"_help\":\"Humidity Control Mode Get\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Off\"},{\"_value\":\"Humidify\"},{\"_value\":\"Dehumidify\"}],\"_key\":\"0x00\",\"_fieldname\":\"Mode\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x03\",\"_name\":\"HUMIDITY_CONTROL_MODE_REPORT\",\"_help\":\"Humidity Control Mode Report\"},{\"_key\":\"0x04\",\"_name\":\"HUMIDITY_CONTROL_MODE_SUPPORTED_GET\",\"_help\":\"Humidity Control Mode Supported Get\"},{\"param\":{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"255\",\"_lenmask\":\"0x00\",\"_lenoffs\":\"0\",\"_len\":\"1\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"Off\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"Humidify\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"Dehumidify\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},\"_key\":\"0x05\",\"_name\":\"HUMIDITY_CONTROL_MODE_SUPPORTED_REPORT\",\"_help\":\"Humidity Control Mode Supported Report\"}],\"_key\":\"0x6D\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_HUMIDITY_CONTROL_MODE\",\"_help\":\"Command Class Humidity Control Mode\",\"_read_only\":\"false\"},{\"cmd\":[{\"_key\":\"0x01\",\"_name\":\"HUMIDITY_CONTROL_OPERATING_STATE_GET\",\"_help\":\"Humidity Control Operating State Get\"},{\"param\":{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"Idle\"},{\"_value\":\"Humidifying\"},{\"_value\":\"Dehumidifying\"}],\"_key\":\"0x00\",\"_fieldname\":\"Operating State\",\"_fieldmask\":\"0x0F\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xF0\",\"_shifter\":\"4\"},\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},\"_key\":\"0x02\",\"_name\":\"HUMIDITY_CONTROL_OPERATING_STATE_REPORT\",\"_help\":\"Humidity Control Operating State Report\"}],\"_key\":\"0x6E\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_HUMIDITY_CONTROL_OPERATING_STATE\",\"_help\":\"Command Class Humidity Control Operating State\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Sequence Number\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"fieldenum\":{\"fieldenum\":[{\"_value\":\"NA\"},{\"_value\":\"RAW\"},{\"_value\":\"ASCII\"},{\"_value\":\"MD5\"}],\"_key\":\"0x00\",\"_fieldname\":\"Data Type\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},\"bitfield\":{\"_key\":\"0x01\",\"_fieldname\":\"Reserved\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"},\"_key\":\"0x01\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"CACHING\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"CACHED_KEYS\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"ENTER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"DISARM_ALL\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"ARM_ALL\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"ARM_AWAY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ARM_HOME\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"EXIT_DELAY\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"ARM_1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"ARM_2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ARM_3\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"ARM_4\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"ARM_5\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"ARM_6\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"RFID\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"BELL\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"FIRE\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"POLICE\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"ALERT_PANIC\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"ALERT_MEDICAL\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x14\",\"_flagname\":\"GATE_OPEN\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x15\",\"_flagname\":\"GATE_CLOSE\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x16\",\"_flagname\":\"LOCK\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x17\",\"_flagname\":\"UNLOCK\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x18\",\"_flagname\":\"TEST\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x19\",\"_flagname\":\"CANCEL\",\"_flagmask\":\"0x19\"}],\"_key\":\"0x02\",\"_name\":\"Event Type\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x03\",\"_name\":\"Event Data Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"variant\":{\"_paramoffs\":\"3\",\"_showhex\":\"true\",\"_signed\":\"true\",\"_sizemask\":\"0xFF\",\"_sizeoffs\":\"0\"},\"_key\":\"0x04\",\"_name\":\"Event Data\",\"_type\":\"VARIANT\",\"_typehashcode\":\"0x0C\",\"_optionaloffs\":\"0x00\",\"_optionalmask\":\"0xFF\"}],\"_key\":\"0x01\",\"_name\":\"ENTRY_CONTROL_NOTIFICATION\",\"_help\":\"Entry Control Notification\"},{\"_key\":\"0x02\",\"_name\":\"ENTRY_CONTROL_KEY_SUPPORTED_GET\",\"_help\":\"Entry Control Key Supported Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Key Supported Bit Mask Length\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0xFF\",\"_lenoffs\":\"0\"},\"_key\":\"0x01\",\"_name\":\"Key Supported Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"}],\"_key\":\"0x03\",\"_name\":\"ENTRY_CONTROL_KEY_SUPPORTED_REPORT\",\"_help\":\"Entry Control Key Supported Report\"},{\"_key\":\"0x04\",\"_name\":\"ENTRY_CONTROL_EVENT_SUPPORTED_GET\",\"_help\":\"Entry Control Event Supported Get\"},{\"param\":[{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Data Type Supported Bit Mask Length\",\"_fieldmask\":\"0x03\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved1\",\"_fieldmask\":\"0xFC\",\"_shifter\":\"2\"}],\"_key\":\"0x00\",\"_name\":\"Properties1\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"0\",\"_lenmask\":\"0x03\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"NA\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"RAW\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"ASCII\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"MD5\",\"_flagmask\":\"0x03\"}],\"_key\":\"0x01\",\"_name\":\"Data Type Supported Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},{\"bitfield\":[{\"_key\":\"0x00\",\"_fieldname\":\"Event Supported Bit Mask Length\",\"_fieldmask\":\"0x1F\",\"_shifter\":\"0\"},{\"_key\":\"0x01\",\"_fieldname\":\"Reserved2\",\"_fieldmask\":\"0xE0\",\"_shifter\":\"5\"}],\"_key\":\"0x02\",\"_name\":\"Properties2\",\"_type\":\"STRUCT_BYTE\",\"_typehashcode\":\"0x07\",\"_comment\":\"\"},{\"bitmask\":{\"_key\":\"0x00\",\"_paramoffs\":\"2\",\"_lenmask\":\"0x1F\",\"_lenoffs\":\"0\"},\"bitflag\":[{\"_key\":\"0x00\",\"_flagname\":\"CACHING\",\"_flagmask\":\"0x00\"},{\"_key\":\"0x01\",\"_flagname\":\"CACHED_KEYS\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x02\",\"_flagname\":\"ENTER\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x03\",\"_flagname\":\"DISARM_ALL\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x04\",\"_flagname\":\"ARM_ALL\",\"_flagmask\":\"0x04\"},{\"_key\":\"0x05\",\"_flagname\":\"ARM_AWAY\",\"_flagmask\":\"0x05\"},{\"_key\":\"0x06\",\"_flagname\":\"ARM_HOME\",\"_flagmask\":\"0x06\"},{\"_key\":\"0x07\",\"_flagname\":\"EXIT_DELAY\",\"_flagmask\":\"0x07\"},{\"_key\":\"0x08\",\"_flagname\":\"ARM_1\",\"_flagmask\":\"0x08\"},{\"_key\":\"0x09\",\"_flagname\":\"ARM_2\",\"_flagmask\":\"0x09\"},{\"_key\":\"0x0A\",\"_flagname\":\"ARM_3\",\"_flagmask\":\"0x0A\"},{\"_key\":\"0x0B\",\"_flagname\":\"ARM_4\",\"_flagmask\":\"0x0B\"},{\"_key\":\"0x0C\",\"_flagname\":\"ARM_5\",\"_flagmask\":\"0x0C\"},{\"_key\":\"0x0D\",\"_flagname\":\"ARM_6\",\"_flagmask\":\"0x0D\"},{\"_key\":\"0x0E\",\"_flagname\":\"RFID\",\"_flagmask\":\"0x0E\"},{\"_key\":\"0x0F\",\"_flagname\":\"BELL\",\"_flagmask\":\"0x0F\"},{\"_key\":\"0x10\",\"_flagname\":\"FIRE\",\"_flagmask\":\"0x10\"},{\"_key\":\"0x11\",\"_flagname\":\"POLICE\",\"_flagmask\":\"0x11\"},{\"_key\":\"0x12\",\"_flagname\":\"ALERT_PANIC\",\"_flagmask\":\"0x12\"},{\"_key\":\"0x13\",\"_flagname\":\"ALERT_MEDICAL\",\"_flagmask\":\"0x13\"},{\"_key\":\"0x14\",\"_flagname\":\"GATE_OPEN\",\"_flagmask\":\"0x14\"},{\"_key\":\"0x15\",\"_flagname\":\"GATE_CLOSE\",\"_flagmask\":\"0x15\"},{\"_key\":\"0x16\",\"_flagname\":\"LOCK\",\"_flagmask\":\"0x16\"},{\"_key\":\"0x17\",\"_flagname\":\"UNLOCK\",\"_flagmask\":\"0x17\"},{\"_key\":\"0x18\",\"_flagname\":\"TEST\",\"_flagmask\":\"0x18\"},{\"_key\":\"0x19\",\"_flagname\":\"CANCEL\",\"_flagmask\":\"0x19\"}],\"_key\":\"0x03\",\"_name\":\"Event Type Supported Bit Mask\",\"_type\":\"BITMASK\",\"_typehashcode\":\"0x06\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x04\",\"_name\":\"Key Cached Size supported Minimum\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x05\",\"_name\":\"Key Cached Size supported Maximum\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x06\",\"_name\":\"Key Cached Timeout supported Minimum\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x07\",\"_name\":\"Key Cached Timeout supported Maximum\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x05\",\"_name\":\"ENTRY_CONTROL_EVENT_SUPPORTED_REPORT\",\"_help\":\"Entry Control Event Supported Report\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Key Cache Size\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Key Cache Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x06\",\"_name\":\"ENTRY_CONTROL_CONFIGURATION_SET\",\"_help\":\"Entry Control Configuration Set\"},{\"_key\":\"0x07\",\"_name\":\"ENTRY_CONTROL_CONFIGURATION_GET\",\"_help\":\"Entry Control Configuration Get\"},{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x00\",\"_name\":\"Key Cache Size\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"},{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"true\"},\"_key\":\"0x01\",\"_name\":\"Key Cache Timeout\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\"}],\"_key\":\"0x08\",\"_name\":\"ENTRY_CONTROL_CONFIGURATION_REPORT\",\"_help\":\"Entry Control Configuration Report\"}],\"_key\":\"0x6F\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_ENTRY_CONTROL\",\"_help\":\"Command Class Entry Control\",\"_read_only\":\"false\"},{\"cmd\":[{\"param\":[{\"valueattrib\":{\"_key\":\"0x00\",\"_hasdefines\":\"false\",\"_showhex\":\"false\"},\"_key\":\"0x00\",\"_name\":\"Node ID\",\"_type\":\"BYTE\",\"_typehashcode\":\"0x01\",\"_encaptype\":\"NODE_NUMBER\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"PROXY_INCLUSION\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"S0_INCLUSION\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x01\",\"_name\":\"Step ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x01\",\"_name\":\"INITIATE\",\"_help\":\"Initiate\"},{\"param\":[{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"PROXY_INCLUSION\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"S0_INCLUSION\",\"_flagmask\":\"0x02\"}],\"_key\":\"0x00\",\"_name\":\"Step ID\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"},{\"const\":[{\"_key\":\"0x00\",\"_flagname\":\"STEP_OK\",\"_flagmask\":\"0x01\"},{\"_key\":\"0x01\",\"_flagname\":\"STEP_USER_REJECTED\",\"_flagmask\":\"0x02\"},{\"_key\":\"0x02\",\"_flagname\":\"STEP_FAILED\",\"_flagmask\":\"0x03\"},{\"_key\":\"0x03\",\"_flagname\":\"STEP_NOT_SUPPORTED\",\"_flagmask\":\"0x04\"}],\"_key\":\"0x01\",\"_name\":\"Status\",\"_type\":\"CONST\",\"_typehashcode\":\"0x0B\"}],\"_key\":\"0x02\",\"_name\":\"COMPLETE\",\"_help\":\"Complete\"}],\"_key\":\"0x74\",\"_version\":\"1\",\"_name\":\"COMMAND_CLASS_INCLUSION_CONTROLLER\",\"_help\":\"Command Class Inclusion Controller\",\"_read_only\":\"false\"}]}}"
  },
  {
    "path": "modules/ZWave/index.js",
    "content": "/*** Z-Wave Binding module ********************************************************\n\nVersion: 3.0.2\n-------------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>, Niels Roche <nir@zwave.eu>\nCopyright: (c) Z-Wave.Me, 2020\n\n******************************************************************************/\n\nif (!String.prototype.padStart) {\n\tString.prototype.padStart = function padStart(targetLength,padString) {\n\t\ttargetLength = targetLength>>0; //floor if number or convert non-number to 0;\n\t\tpadString = String(padString || ' ');\n\t\tif (this.length > targetLength) {\n\t\t\treturn String(this);\n\t\t}\n\t\telse {\n\t\t\ttargetLength = targetLength-this.length;\n\t\t\tif (targetLength > padString.length) {\n\t\t\t\tpadString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed\n\t\t\t}\n\t\t\treturn padString.slice(0,targetLength) + String(this);\n\t\t}\n\t};\n}\n\n\nfunction ZWave(id, controller) {\n\n\t// if called without \"new\", return list of loaded Z-Way instances\n\tif (!(this instanceof ZWave)) {\n\t\treturn ZWave.list();\n\t}\n\n\tZWave.super_.call(this, id, controller);\n\n\tthis.ZWAY_DEVICE_CHANGE_TYPES = {\n\t\t\"DeviceAdded\": 0x01,\n\t\t\"DeviceRemoved\": 0x02,\n\t\t\"InstanceAdded\": 0x04,\n\t\t\"InstanceRemoved\": 0x08,\n\t\t\"CommandAdded\": 0x10,\n\t\t\"CommandRemoved\": 0x20,\n\t\t\"ZDDXSaved\": 0x100,\n\t\t\"EnumerateExisting\": 0x200\n\t};\n\n\tthis.ZWAY_DATA_CHANGE_TYPE = {\n\t\t\"Updated\": 0x01, // Value updated or child created\n\t\t\"Invalidated\": 0x02, // Value invalidated\n\t\t\"Deleted\": 0x03, // Data holder deleted - callback is called last time before being deleted\n\t\t\"ChildCreated\": 0x04, // New direct child node created\n\n\t\t// ORed flags\n\t\t\"PhantomUpdate\": 0x40, // Data holder updated with same value (only updateTime changed)\n\t\t\"ChildEvent\": 0x80 // Event from child node\n\t};\n\n\tthis.CC = {\n\t\t\"Basic\": 0x20,\n\t\t\"SwitchBinary\": 0x25,\n\t\t\"SwitchMultilevel\": 0x26,\n\t\t\"SwitchColor\": 0x33,\n\t\t\"SoundSwitch\": 0x79,\n\t\t\"SceneActivation\": 0x2b,\n\t\t\"Alarm\": 0x71,\n\t\t\"AlarmSensor\": 0x9c,\n\t\t\"SensorBinary\": 0x30,\n\t\t\"SensorMultilevel\": 0x31,\n\t\t\"Meter\": 0x32,\n\t\t\"MeterPulse\": 0x35,\n\t\t\"ThermostatMode\": 0x40,\n\t\t\"ThermostatSetPoint\": 0x43,\n\t\t\"ThermostatFanMode\": 0x44,\n\t\t\"DoorLock\": 0x62,\n\t\t\"CentralScene\": 0x5b,\n\t\t\"Battery\": 0x80,\n\t\t\"DeviceResetLocally\": 0x5a,\n\t\t\"BarrierOperator\": 0x66,\n\t\t\"Configuration\": 0x70,\n\t\t\"Wakeup\": 0x84\n\t};\n\n\tthis.default_expert_config = {\n\t\t'debug': false,\n\t\t'network_name': '',\n\t\t'date_format': '',\n\t\t'time_format': '',\n\t\t'time_zone': '',\n\t\t'notes': '',\n\t\t'ssid_name': '',\n\t\t'currentDateTime': '',\n\t\t'rss': ''\n\t};\n\n\t// z-way statistics\n\tthis.statistics = {\n\t\tRFTxFrames: {\n\t\t\tvalue: 0,\n\t\t\tupdateTime: 0\n\t\t},\n\t\tRFTxLBTBackOffs: {\n\t\t\tvalue: 0,\n\t\t\tupdateTime: 0\n\t\t},\n\t\tRFRxFrames: {\n\t\t\tvalue: 0,\n\t\t\tupdateTime: 0\n\t\t},\n\t\tRFRxLRCErrors: {\n\t\t\tvalue: 0,\n\t\t\tupdateTime: 0\n\t\t},\n\t\tRFRxCRC16Errors: {\n\t\t\tvalue: 0,\n\t\t\tupdateTime: 0\n\t\t},\n\t\tRFRxForeignHomeID: {\n\t\t\tvalue: 0,\n\t\t\tupdateTime: 0\n\t\t}\n\t};\n}\n\n// Module inheritance and setup\n\ninherits(ZWave, AutomationModule);\n\n_module = ZWave;\n\nObject.defineProperty(ZWave, \"list\", {\n\tvalue: function(__, req) {\n\t\t// show in the list if called directly (not via web) or role is admin or API is public\n\t\treturn Object.keys(ZWave).filter(function(name) {\n\t\t\treturn !req || req.role == controller.auth.ROLE.ADMIN || ZWave[name].publicAPI;\n\t\t});\n\t},\n\tenumerable: false,\n\twritable: false,\n\tconfigurable: false\n});\n\nws.allowExternalAccess(\"ZWave.list\", controller.auth.ROLE.ANONYMOUS); // we handle role inside the handler\n\nZWave.prototype.updateList = function() {\n\tthis.controller.setNamespace(\"zways\", this.controller.namespaces, ZWave.list().map(function(name) {\n\t\treturn {\n\t\t\tzwayName: name\n\t\t};\n\t}));\n};\n\nZWave.prototype.loadObject = function(name) {\n\ttry {\n\t\treturn loadObject(this.config.name + \"_\" + name);\n\t} catch (e) {\n\t\tthis.addNotification('warning','Error in storage file: '+ name + ' detected. Unable to load data - ERROR: '+ e.toString() + ' File will be rewritten if possible.','z-wave');\n\t\treturn null;\n\t}\n};\n\nZWave.prototype.saveObject = function(name, obj, immediate) {\n\treturn saveObject(this.config.name + \"_\" + name, obj, immediate);\n};\n\nZWave.prototype.init = function(config) {\n\tZWave.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\t// select the latest updated postfix.json\n\tthis.postfix = this.loadModuleJSON(\"postfix.json\");\n\t// postfix is common for all ZWave bindings\n\tupdatedPostfix = loadObject(\"postfix.json\");\n\n\tif (updatedPostfix && updatedPostfix.last_update && this.postfix.last_update && updatedPostfix.last_update > this.postfix.last_update) {\n\t\tthis.postfix = updatedPostfix;\n\t}\n\n\tthis.expert_config = this.loadObject(\"expertconfig.json\");\n\n\tif (!!!this.expert_config) {\n\t\tthis.expert_config = self.default_expert_config;\n\t\tthis.saveObject(\"expertconfig.json\", this.expert_config, true);\n\t}\n\n\tthis.cmdClasses = this.loadModuleJSON(\"cmd_classes.json\").zw_classes.cmd_class;\n\n\t// select custompostfix.json\n\tvar custom_postfix = loadObject(\"custompostfix.json\");\n\n\t// DSK collector\n\tthis.dskCollection = this.loadObject(\"dskCollection\") || [];\n\n\t// add custom_postfix to postfix\n\tif (!!custom_postfix) {\n\t\tvar custom_fixes = custom_postfix.fixes;\n\t\tvar pfixes = this.postfix.fixes;\n\n\t\tfor (var x in custom_fixes) {\n\t\t\tfor (var y in pfixes) {\n\t\t\t\tif (custom_fixes[x].p_id === pfixes[y].p_id) {\n\t\t\t\t\tcustom_fixes[x].id = pfixes[y].id;\n\t\t\t\t\t_.assign(pfixes[y], custom_fixes[x]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar id = Math.max.apply(Math, pfixes.map(function(fix) {\n\t\t\t\treturn fix.id;\n\t\t\t}));\n\t\t\tcustom_fixes[x].id = (id + 1);\n\t\t\tpfixes.push(custom_fixes[x]);\n\t\t}\n\n\t\tthis.postfix.fixes = pfixes;\n\t}\n\n\tthis.restartBindingCounter = 0;\n\n\tthis.startBinding();\n\tif (!this.zway) {\n\t\treturn;\n\t}\n\n\tthis._dataBind = function(dataBindings, zwayName, nodeId, instanceId, commandClassId, path, func, type) {\n\t\tif (zwayName === self.config.name && self.zway) {\n\t\t\tself.dataBind(dataBindings, self.zway, nodeId, instanceId, commandClassId, path, func, type);\n\t\t}\n\t};\n\tthis._dataUnbind = function(dataBindings) {\n\t\tself.dataUnbind(dataBindings);\n\t};\n\n\tthis.controller.on(\"ZWave.dataBind\", this._dataBind);\n\tthis.controller.on(\"ZWave.dataUnbind\", this._dataUnbind);\n\n\tthis.controller.emit(\"ZWave.register\", this.config.name);\n};\n\nZWave.prototype.startBinding = function() {\n\tvar self = this;\n\n\ttry {\n\t\tthis.zway = new ZWaveBinding(this.config.name, this.config.port, this.config.speed || 115200, {\n\t\t\tconfigFolder: this.config.config || 'config',\n\t\t\ttranslationsFolder: this.config.translations || 'translations',\n\t\t\tzddxFolder: this.config.ZDDX || 'ZDDX',\n\t\t\tterminationCallback: function() {\n\t\t\t\tself.terminating.call(self);\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\tthis.zway.discover();\n\t\t} catch (e1) {\n\t\t\tthis.zway.stop();\n\t\t\tconsole.log(e1.toString());\n\t\t\treturn;\n\t\t}\n\t} catch (e) {\n\t\tthis.zway = null;\n\t\tconsole.log(e.toString());\n\t\tthis.tryRestartLater(e);\n\t\treturn;\n\t}\n\n\t// started\n\tthis.restartBindingCounter = 0;\n\n\tthis.fastAccess = false;\n\tif (!global.zway) {\n\t\t// this is the first zway - make fast shortcut\n\t\tthis.fastAccess = true;\n\t}\n\n\tglobal.ZWave[this.config.name] = {\n\t\t\"zway\": this.zway,\n\t\t\"port\": this.config.port,\n\t\t\"publicAPI\": this.config.publicAPI,\n\t\t\"fastAccess\": this.fastAccess\n\t};\n\tthis.updateList();\n\n\tthis.stopped = false;\n\n\tif (this.config.enableAPI !== false) {\n\t\tthis.defineHandlers();\n\t}\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIAllow();\n\t\t}\n\t\tglobal[\"zway\"] = this.zway; // global variable\n\t\tglobal[\"ZWaveAPI\"] = this.ZWaveAPI;\n\t}\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIAllow(this.config.name);\n\t}\n\t_.extend(global[\"ZWave\"][this.config.name], this.ZWaveAPI);\n\n\tif (this.config.createVDev !== false) {\n\t\tthis.deadDetectionStart();\n\t\tthis.gateDevicesStart();\n\t}\n\t\n\tthis.timeUpdaterStart();\n\n\t// save data every hour for hot start\n\tthis.saveDataXMLTimer = setInterval(function() {\n\t\tself.zway.devices.SaveData();\n\t}, 3600 * 1000);\n\n\t// store parsed incoming and outgoing packets (for Zniffer)\n\tthis.parsedPackets = new LimitedArray(\n\t\tself.loadObject(\"parsedPackets.json\"),\n\t\tfunction(arr) {\n\t\t\tif (self.config.enablePacketLog !== \"runtime\" && self.config.enablePacketLog !== \"disable\") {\n\t\t\t\tself.saveObject(\"parsedPackets.json\", arr);\n\t\t\t}\n\t\t},\n\t\t100, // check it every 100 packets\n\t\t5000, // save up to 5000 packets\n\t\tfunction(element) { // save last day only\n\t\t\treturn element.id > (Date.now() - 86400 * 1000);\n\t\t}\n\t);\n\n\t// store incoming and outgoing packets as they are (for PacketLog)\n\tthis.originPackets = new LimitedArray(\n\t\tself.loadObject(\"originPackets.json\"),\n\t\tfunction(arr) {\n\t\t\tif (self.config.enablePacketLog !== \"runtime\" && self.config.enablePacketLog !== \"disable\") {\n\t\t\t\tself.saveObject(\"originPackets.json\", arr);\n\t\t\t}\n\t\t},\n\t\t100, // check it every 100 packets\n\t\t5000, // save up to 5000 packets\n\t\tfunction(element) { // save last day only\n\t\t\treturn element.updateTime > (Date.now() / 1000 - 86400);\n\t\t}\n\t);\n\n\tthis.refreshStatisticsPeriodically();\n\n\tthis.CommunicationLogger();\n\t\n\tthis.networkReorganizationInit();\n\t\n\tvar uartSpeed = function(type) {\n\t\tvar data = this;\n\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Updated\"])\n\t\tif (self.config.speed !== data.value) {\n\t\t\tself.config.speed = data.value;\n\t\t\tself.saveConfig();\n\t\t\tself.zway.stop();\n\t\t\tself.tryRestartLater();\n\t\t}\n\t\t\n\t}\n\tthis.zway.controller.data.hardware.uartSpeed.bind(uartSpeed);\n\t\n\tvar firmwareFaultNotify = function() {\n\t\tif (this.value != 0) {\n\t\t\thttp.request({\n\t\t\t\turl: \"https://service.z-wave.me/expertui/firmware-faults/\",\n\t\t\t\tasync: true,\n\t\t\t\tmethod: 'POST',\n\t\t\t\tdata: {\n\t\t\t\t\tuuid: self.zway.controller.data.uuid.value,\n\t\t\t\t\tbuild: self.zway.controller.data.firmware.build.value,\n\t\t\t\t\tcode: this.value,\n\t\t\t\t\tscb: this.scb.value.map(function(v) { return (\"00\" + v.toString(16)).slice(-2); }).join(\"\"),\n\t\t\t\t\treg: this.reg.value.map(function(v) { return (\"00\" + v.toString(16)).slice(-2); }).join(\"\"),\n\t\t\t\t\tstack: this.stack.value.map(function(v) { return (\"00\" + v.toString(16)).slice(-2); }).join(\"\"),\n\t\t\t\t\tzway: self.zway.controller.data.softwareRevisionVersion.value\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t};\n\tthis.zway.controller.data.firmware.fault.bind(firmwareFaultNotify);\n};\n\nZWave.prototype.stop = function() {\n\tconsole.log(\"--- ZWave.stop()\");\n\tZWave.super_.prototype.stop.call(this);\n\n\tthis.stopBinding();\n\n\tif (this._dataBind) {\n\t\tthis.controller.off(\"ZWave.dataBind\", this._dataBind);\n\t}\n\tif (this._dataUnbind) {\n\t\tthis.controller.off(\"ZWave.dataUnbind\", this._dataUnbind);\n\t}\n};\n\nZWave.prototype.stopBinding = function() {\n\tthis.controller.emit(\"ZWave.unregister\", this.config.name);\n\n\tthis.networkReorganization = null;\n\t\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStop();\n\t\tthis.deadDetectionStop();\n\t}\n\t\n\tthis.timeUpdaterStop();\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIRevoke();\n\t\t}\n\t\tif (global.zway) {\n\t\t\tdelete global[\"zway\"];\n\t\t\tdelete global[\"ZWaveAPI\"];\n\t\t}\n\t}\n\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIRevoke(this.config.name);\n\t}\n\n\tif (global.ZWave) {\n\t\tdelete global.ZWave[this.config.name];\n\t\tthis.updateList();\n\t}\n\n\t// clear statistics of packets\n\tif (this.originPackets) {\n\t\tthis.originPackets.finalize();\n\t\tthis.originPackets = null;\n\t}\n\tif (this.parsedPackets) {\n\t\tthis.parsedPackets.finalize();\n\t\tthis.parsedPackets = null;\n\t}\n\n\t// clear timers\n\tif (this.rssiTimer) {\n\t\tclearInterval(this.rssiTimer);\n\t\tthis.rssiTimer = undefined;\n\t}\n\n\tif (this.statisticsInterval) {\n\t\tclearInterval(this.statisticsInterval);\n\t\tthis.statisticsInterval = undefined;\n\t}\n\n\tif (this.saveDataXMLTimer) {\n\t\tclearInterval(this.saveDataXMLTimer);\n\t\tthis.saveDataXMLTimer = undefined;\n\t}\n\n\tthis.stopped = true;\n\tif (this.zway) {\n\t\ttry {\n\t\t\tthis.zway.stop();\n\t\t} catch (e) {\n\t\t\t// Z-Way has already gone\n\t\t}\n\t\tthis.zway = null;\n\t}\n};\n\nZWave.prototype.tryRestartLater = function(e) {\n\tvar delay = 10;\n\n\tif (this.restartBindingCounter < 5) {\n\t\tvar self = this;\n\n\t\tconsole.log(\"Trying to restart Z-Wave binding (\" + this.config.name + \") in \" + delay + \" seconds\");\n\t\tthis.restartBindingCounter++;\n\n\t\tsetTimeout(function() {\n\t\t\t// retry open after N seconds\n\t\t\tconsole.log(\"Restarting Z-Wave binding (\" + self.config.name + \")\");\n\t\t\tself.startBinding();\n\t\t}, delay * 1000);\n\n\t} else {\n\t\tvar langFile = this.loadModuleLang();\n\n\t\tconsole.log(\"Tried \" + this.restartBindingCounter + \" times without success. Stopping tries.\");\n\t\tthis.addNotification(\"critical\", langFile.err_binding_start + e.toString(), \"z-wave\");\n\t}\n};\n\nZWave.prototype.terminating = function() {\n\tif (!this.stopped) {\n\t\tconsole.log(\"Terminating Z-Wave binding\");\n\t\tthis.stopBinding();\n\t\tthis.tryRestartLater();\n\t}\n};\n\nZWave.prototype.CommunicationLogger = function() {\n\tvar self = this;\n\n\tvar inH = function(type) {\n\t\tvar data = this;\n\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\n\t\t// save the packet as it is\n\t\tdata.direction = \"input\";\n\t\tself.originPackets.push({\n\t\t\t\"updateTime\": data.updateTime,\n\t\t\t\"nodeId\": data.nodeId.value,\n\t\t\t\"dstNodeId\": data.dstNodeId.value,\n\t\t\t\"RSSI\": data.RSSI.value,\n\t\t\t\"hops\": data.hops.value,\n\t\t\t\"frameType\": data.frameType.value,\n\t\t\t\"duplicate\": data.duplicate.value,\n\t\t\t\"value\": data.value\n\t\t});\n\n\t\tdata = createIncomingEntry(data);\n\t\tdata.id = data.updateTime * 1000 + (new Date).getMilliseconds();\n\n\t\tself.parsedPackets.push(data);\n\t};\n\n\tvar outH = function(type) {\n\t\tvar data = this;\n\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\n\t\tdata.direction = \"output\";\n\t\tself.originPackets.push({\n\t\t\t\"updateTime\": data.updateTime,\n\t\t\t\"delivered\": data.delivered.value,\n\t\t\t\"deliveryTime\": data.deliveryTime.value,\n\t\t\t\"packetLength\": data.packetLength.value,\n\t\t\t\"nodeId\": data.nodeId.value,\n\t\t\t\"returnRSSI\": data.returnRSSI.value,\n\t\t\t\"hops\": data.hops.value,\n\t\t\t\"returnChannel\": data.returnChannel.value,\n\t\t\t\"txChannel\": data.txChannel.value,\n\t\t\t\"speed\": data.speed.value,\n\t\t\t\"schemeState\": data.schemeState.value,\n\t\t\t\"tries\": data.tries.value,\n\t\t\t\"lastFailPath\": data.lastFailPath.value,\n\t\t\t\"value\": data.value\n\t\t});\n\n\t\tdata = createOutgoingEntry(data);\n\t\tdata.id = data.updateTime * 1000 + (new Date).getMilliseconds();\n\n\t\tself.parsedPackets.push(data);\n\t};\n\n\tif (this.config.enablePacketLog !== \"disable\") {\n\t\t// process incoming packages\n\t\tthis.zway.controller.data.incomingPacket.bind(inH);\n\t\t// process outgoing packages\n\t\tthis.zway.controller.data.outgoingPacket.bind(outH);\n\t}\n\t\n\t// check if controller supports background rssi\n\tif (this.zway.controller.data.capabilities.value.indexOf(59) > -1) {\n\t\t// set timer that will request RSSI stats every 30 s\n\t\tthis.rssiTimer = setInterval(function() {\n\t\t\ttry {\n\t\t\t\tself.updateRSSIData(function(newValue) {\n\t\t\t\t\tvar data = self.loadObject(\"rssidata.json\") || [];\n\t\t\t\t\tif (!data) data = [];\n\t\t\t\t\tdata.push(newValue);\n\n\t\t\t\t\t// remove values older than 24h\n\t\t\t\t\tif (data.length > 1440) {\n\t\t\t\t\t\tvar lastDay = now - 86400;\n\t\t\t\t\t\tdata = _.filter(data, function(entry) {\n\t\t\t\t\t\t\treturn entry.time > lastDay;\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\tself.saveObject(\"rssidata.json\", data);\n\t\t\t\t});\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log('Cannot fetch background RSSI. Error:', e.message);\n\t\t\t}\n\t\t}, 1000 * 30);\n\t}\n\n\t// =================== helper functions ========================\n\n\tfunction RSSItoText(rssiValue) {\n\t\tif (rssiValue === 125) return \"too low\";\n\t\tif (rssiValue === 126) return \"too high\";\n\t\tif (rssiValue === 127) return \"not available\";\n\t\tif (rssiValue > 127) rssiValue -= 256;\n\t\treturn rssiValue.toString(10) + ' dBm';\n\t}\n\n\tfunction prepareRSSI(rssiPacket) {\n\t\tif (_.isArray(rssiPacket)) {\n\t\t\treturn rssiPacket.map(RSSItoText);\n\t\t} else {\n\t\t\treturn RSSItoText(rssiPacket);\n\t\t}\n\t}\n\n\tfunction packetApplication(packet, packetType) {\n\t\tvar encaps = [\n\t\t\t\t// MultiChannel\n\t\t\t\t{\n\t\t\t\t\tcc: 0x60,\n\t\t\t\t\tcmd: 0x0D,\n\t\t\t\t\thead: 4,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 2,\n\t\t\t\t\tdstI: 3,\n\t\t\t\t\tencap: 'I'\n\t\t\t\t},\n\t\t\t\t// MultiInstance\n\t\t\t\t{\n\t\t\t\t\tcc: 0x60,\n\t\t\t\t\tcmd: 0x06,\n\t\t\t\t\thead: 3,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 2,\n\t\t\t\t\tencap: 'I'\n\t\t\t\t},\n\t\t\t\t// Supervision\n\t\t\t\t{\n\t\t\t\t\tcc: 0x6C,\n\t\t\t\t\tcmd: 0x01,\n\t\t\t\t\thead: 4,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 0,\n\t\t\t\t\tencap: 'Su'\n\t\t\t\t},\n\t\t\t\t// MultiCommand\n\t\t\t\t{\n\t\t\t\t\tcc: 0x8F,\n\t\t\t\t\tcmd: 0x01,\n\t\t\t\t\thead: 2,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 0,\n\t\t\t\t\tencap: 'M'\n\t\t\t\t},\n\t\t\t\t// Security\n\t\t\t\t{\n\t\t\t\t\tcc: 0x98,\n\t\t\t\t\tcmd: 0x81,\n\t\t\t\t\thead: 0,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 0,\n\t\t\t\t\tencap: 'S'\n\t\t\t\t},\n\t\t\t\t// Security\n\t\t\t\t{\n\t\t\t\t\tcc: 0x98,\n\t\t\t\t\tcmd: 0xC1,\n\t\t\t\t\thead: 0,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 0,\n\t\t\t\t\tencap: 'S'\n\t\t\t\t},\n\t\t\t\t// Security S2\n\t\t\t\t{\n\t\t\t\t\tcc: 0x9F,\n\t\t\t\t\tcmd: 0x03,\n\t\t\t\t\thead: 0,\n\t\t\t\t\ttail: 0,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 0,\n\t\t\t\t\tencap: 'S2'\n\t\t\t\t},\n\t\t\t\t// CRC16\n\t\t\t\t{\n\t\t\t\t\tcc: 0x56,\n\t\t\t\t\tcmd: 0x01,\n\t\t\t\t\thead: 2,\n\t\t\t\t\ttail: 2,\n\t\t\t\t\tsrcI: 0,\n\t\t\t\t\tdstI: 0,\n\t\t\t\t\tencap: 'C'\n\t\t\t\t}\n\t\t\t],\n\t\t\tresult = {\n\t\t\t\tsrc: packetType === 'in' ? packet.nodeId.value : self.zway.controller.data.nodeId.value,\n\t\t\t\tdst: packetType === 'in' ? packet.dstNodeId.value : packet.nodeId.value,\n\t\t\t\tencap: '',\n\t\t\t\tapplication: ''\n\t\t\t};\n\n\t\tif (packetType === 'in' && packet.frameType.value === \"Node Info\") {\n\t\t\tresult.application = 'NIF (' + packet.value.slice(3).map(decToHex).join(', ') + ')';\n\t\t\treturn result;\n\t\t}\n\n\t\tvar payload = packet.value.slice(packetType === 'in' ? 0 : 4, packetType === 'in' ? undefined : -1);\n\n\t\tvar multiCmd = false;\n\n\t\tvar decapsulated = true;\n\t\twhile (decapsulated) {\n\t\t\tdecapsulated = false;\n\t\t\tfor (var i = 0; i < encaps.length; i++) {\n\t\t\t\tif (payload[0] === encaps[i].cc && payload[1] === encaps[i].cmd) {\n\t\t\t\t\t// get channels\n\t\t\t\t\tif (encaps[i].dstI !== 0 && encaps[i].srcI !== 0) {\n\t\t\t\t\t\tresult.dst += \":\" + payload[encaps[i].dstI];\n\t\t\t\t\t\tresult.src += \":\" + payload[encaps[i].srcI];\n\t\t\t\t\t} else if (encaps[i].dstI !== 0) {\n\t\t\t\t\t\t// in MultiInstance v1 there is only remote side channel ID\n\t\t\t\t\t\tif (packetType === 'in') {\n\t\t\t\t\t\t\tresult.src += \":\" + payload[encaps[i].dstI];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresult.dst += \":\" + payload[encaps[i].dstI];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// get inner payload\n\t\t\t\t\tif (encaps[i].head === 0) {\n\t\t\t\t\t\t// work with decrypted packet\n\t\t\t\t\t\tpayload = packet.securePayload.value;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpayload = payload.slice(encaps[i].head, encaps[i].tail === 0 ? undefined : -encaps[i].tail);\n\t\t\t\t\t}\n\t\t\t\t\tresult.encap = result.encap + \" \" + encaps[i].encap;\n\t\t\t\t\tif (encaps[i].cc === 0x8F) {\n\t\t\t\t\t\tmultiCmd = true;\n\t\t\t\t\t\tdecapsulated = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdecapsulated = true; // try next decapsulation\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (multiCmd) {\n\t\t\tvar n = payload[0];\n\t\t\tvar s = 2;\n\t\t\tfor (var j = 0; j < n; j++) {\n\t\t\t\tresult.application += (j ? ', ' : '') + decodePayload(payload.slice(s, s + payload[s - 1]));\n\t\t\t\ts += payload[s - 1] + 1;\n\t\t\t}\n\t\t} else {\n\t\t\tresult.application = decodePayload(payload);\n\t\t}\n\t\treturn result;\n\t}\n\n\tfunction decodePayload(payload) {\n\t\tif (payload.length == 0) {\n\t\t\treturn \"\";\n\t\t}\n\n\t\tvar ccId = \"0x\" + decToHex(payload[0]);\n\n\t\t// match CC\n\t\tvar findCmdClass = _.filter(self.cmdClasses, function(cc) {\n\t\t\treturn cc['_key'] === ccId;\n\t\t});\n\n\t\t// get latest version of filtered\n\t\tvar latestVersion = Math.max.apply(Math, findCmdClass.map(function(cc) {\n\t\t\treturn parseInt(cc['_version'], 10);\n\t\t})).toString();\n\n\t\t// match CC of the last version\n\t\tvar _cmdClass = _.filter(findCmdClass, function(cc) {\n\t\t\treturn cc['_version'] === latestVersion;\n\t\t})[0];\n\n\t\tif (!_cmdClass || _.isEmpty(_cmdClass)) {\n\t\t\treturn 'Unknow commad (' + payload.map(decToHex).join(', ') + ')';\n\t\t}\n\n\t\tif (payload.length == 1) {\n\t\t\treturn _cmdClass['_help'];\n\t\t}\n\n\t\tvar ccCmd = \"0x\" + decToHex(payload[1]);\n\n\t\tvar cmd;\n\t\tif (_.isArray(_cmdClass.cmd)) {\n\t\t\tcmd = _.filter(_cmdClass.cmd, function(cmd) {\n\t\t\t\treturn cmd['_key'] === ccCmd;\n\t\t\t})[0];\n\t\t} else {\n\t\t\tcmd = _cmdClass.cmd;\n\t\t}\n\n\t\tvar description = \"Unknow command\";\n\n\t\tif (typeof cmd === \"object\" && cmd.hasOwnProperty('_help') && cmd['_help'] !== '') {\n\t\t\tdescription = cmd['_help'];\n\t\t\tpayload = payload.slice(2);\n\t\t} else if (_cmdClass['_help'] && _cmdClass['_help'] !== '') {\n\t\t\tdescription = _cmdClass['_help'];\n\t\t\tpayload = payload.slice(1);\n\t\t}\n\n\t\treturn description + (payload.length ? ' (' + payload.map(decToHex).join(', ') + ')' : '');\n\t}\n\n\n\tfunction decToHex(decimal) {\n\t\treturn (\"00\" + decimal.toString(16).toUpperCase()).slice(-2);\n\t}\n\n\tfunction createIncomingEntry(packet) {\n\t\tvar pA = packetApplication(packet, 'in');\n\t\treturn {\n\t\t\ttype: 'incoming',\n\t\t\tupdateTime: packet.updateTime,\n\t\t\tsrc: pA.src,\n\t\t\tdest: pA.dst,\n\t\t\trssi: packet.RSSI && packet.RSSI.value ? prepareRSSI(packet.RSSI.value) : '',\n\t\t\tencaps: pA.encap,\n\t\t\tapplication: pA.application\n\t\t};\n\t}\n\n\tfunction createOutgoingEntry(packet) {\n\t\tvar pA = packetApplication(packet, 'out');\n\t\treturn {\n\t\t\ttype: 'outgoing',\n\t\t\tupdateTime: packet.updateTime,\n\t\t\tspeed: packet.speed && packet.speed.value ? packet.speed.value : '',\n\t\t\trssi: packet.returnRSSI && packet.returnRSSI.value ? prepareRSSI(packet.returnRSSI.value) : '',\n\t\t\thops: packet.hops && packet.hops.value ? packet.hops.value : '',\n\t\t\ttries: packet.tries && packet.tries.value ? packet.tries.value : '',\n\t\t\tsrc: pA.src,\n\t\t\tdest: pA.dst,\n\t\t\trssi: packet.returnRSSI && packet.returnRSSI.value ? prepareRSSI(packet.returnRSSI.value) : '',\n\t\t\tencaps: pA.encap,\n\t\t\tapplication: pA.application\n\t\t};\n\t}\n};\n\nZWave.prototype.refreshStatisticsPeriodically = function() {\n\tvar self = this;\n\n\tthis.clearNetStats = function() {\n\t\tself.zway.ClearNetworkStats();\n\n\t\tObject.keys(self.statistics).map(function(key) {\n\t\t\tself.statistics[key].value = 0;\n\t\t});\n\n\t\tself.updateNetStats();\n\t};\n\n\tthis.updateNetStats = function() {\n\t\ttry {\n\t\t\tvar stats = ['RFTxFrames', 'RFTxLBTBackOffs', 'RFRxFrames', 'RFRxLRCErrors', 'RFRxCRC16Errors', 'RFRxForeignHomeID'],\n\t\t\t\t// get the biggest value of all stat params\n\t\t\t\tmaxPaketCnt = Math.max.apply(null, Object.keys(self.statistics).map(function(key) {\n\t\t\t\t\treturn self.statistics[key].value\n\t\t\t\t}));\n\n\t\t\t// reset network statistics\n\t\t\tif (maxPaketCnt > 32768) { // 2^15\n\t\t\t\tself.zway.ClearNetworkStats();\n\n\t\t\t\tself.zway.GetNetworkStats(function() {\n\t\t\t\t\tstats.forEach(function(key) {\n\t\t\t\t\t\tself.statistics[key] = {\n\t\t\t\t\t\t\tvalue: self.zway.controller.data.statistics[key].value,\n\t\t\t\t\t\t\tupdateTime: self.zway.controller.data.statistics[key].updateTime\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\t// update network statistics\n\t\t\t} else {\n\t\t\t\tself.zway.GetNetworkStats(function() {\n\t\t\t\t\tstats.forEach(function(key) {\n\t\t\t\t\t\tself.statistics[key] = {\n\t\t\t\t\t\t\tvalue: self.statistics[key].value ? self.statistics[key].value + self.zway.controller.data.statistics[key].value : self.zway.controller.data.statistics[key].value,\n\t\t\t\t\t\t\tupdateTime: self.zway.controller.data.statistics[key].updateTime\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.log('Failed to update/remove network statistics.', e.toString());\n\n\t\t\tif (this.statisticsInterval) {\n\t\t\t\tclearInterval(this.statisticsInterval);\n\t\t\t\tthis.statisticsInterval = undefined;\n\t\t\t}\n\t\t}\n\t};\n\n\t// initial call\n\tthis.updateNetStats();\n\n\t// intervall function collecting network statistic data\n\tthis.statisticsInterval = setInterval(function() {\n\t\tself.updateNetStats();\n\t}, 600 * 1000);\n};\n\n/*\n * this function uses the S2 or Smart Start QR code information\n * to generate readable entries in this.dskCollection\n * DSKs of new entries will also be added automatically to the provisioning list\n */\nZWave.prototype.addDSKEntry = function(entry) {\n\tfunction safeInt(string, defaultValue) {\n\t\tvar digit = +string;\n\t\tdefaultValue = defaultValue || 0;\n\t\tif (!isNaN(digit)) {\n\t\t\treturn digit;\n\t\t}\n\n\t\treturn defaultValue;\n\t}\n\n\tfunction decStrToHexStr(decimal) {\n\t\tvar value = parseInt(decimal, 10),\n\t\t\thexString = value.toString(16).toUpperCase(),\n\t\t\tbyteLength = 2 * Math.floor(Math.log(value ? value : 1) / 8 / Math.LN2 + 1),\n\t\t\tzeros = (new Array(byteLength + 1)).join(\"0\");\n\n\t\treturn \"0x\" + (zeros + hexString).slice(-byteLength);\n\t};\n\n\tfunction parseWithoutProductType(entry) {\n\t\tvar isValid = /^(\\d{5}-){7}\\d{5}$/.test(entry);\n\n\t\treturn {\n\t\t\tDSK: isValid ? entry : null,\n\t\t\tisValid: isValid,\n\t\t};\n\t}\n\n\tfunction parseWithZws2dskPrefix(entry) {\n\t\treturn parseWithoutProductType(entry.slice(8));\n\t}\n\n\tfunction checkHashSum(entry, hash) {\n\t\tvar data = crypto.sha1(entry.substring(9));\n\t\tdata = new Uint8Array(data);\n\n\t\treturn hash ===  (\"00000\" + ((data[0] << 8) + data[1]).toString(10)).slice(-5);\n\t}\n\n\tfunction extractType(input) {\n\t\tvar info;\n\t\tif (!input || !(info = input.match(/^(\\d{2})(\\d{2})(\\d+)$/))) {\n\t\t\treturn ;\n\t\t}\n\n\t\tvar value = info[3].substring(0, safeInt(info[2]));\n\t\tvar other = info[3].substring(safeInt(info[2]));\n\t\tvar ret = extractType(other);\n\t\tvar ans = [{ typeCritical: safeInt(info[1], -1), value: value }];\n\n\t\treturn ret ? ans.concat(ret) : ans;\n\t}\n\n\tfunction block(source, start, count) {\n\t\tvar blockSize = 5;\n\t\tcount = count || 1;\n\t\tstart = safeInt(start);\n\n\t\treturn decStrToHexStr(source.substring(start * blockSize, (start + count) * blockSize));\n\t}\n\n\tfunction codeToDevice(code) {\n\t\tvar typeMap = {\n\t\t\t0: function (val) {\n\t\t\t\treturn {\n\t\t\t\t\tdeviceTypeGeneric: block(val, 0).substring(0, 2),\n\t\t\t\t\tdeviceTypeSpecific: block(val, 0).substring(2),\n\t\t\t\t\tinstallerIconType: block(val, 1),\n\t\t\t\t}\n\t\t\t},\n\t\t\t2: function (val) {\n\t\t\t\treturn {\n\t\t\t\t\tmanufacturerId: block(val, 0),\n\t\t\t\t\tproductType: block(val, 1),\n\t\t\t\t\tproductId: block(val, 2),\n\t\t\t\t\tapplicationVersion: block(val[0], 3),\n\t\t\t\t}\n\t\t\t},\n\t\t\t4: function (val) {\n\t\t\t\treturn {\n\t\t\t\t\trequestInterval: safeInt(val) * 128\n\t\t\t\t}\n\t\t\t},\n\t\t\t6: function (val) {\n\t\t\t\tvar info = val.match(/^(\\d{2})(\\d{40})$/);\n\t\t\t\tif (info)\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpresentationFormat: safeInt(info[1]),\n\t\t\t\t\t\tUUID: info[2].match(/\\d{5}/g).join('-')\n\t\t\t\t\t}\n\n\t\t\t\treturn {};\n\t\t\t},\n\t\t\t8: function (val) {\n\t\t\t\treturn {\n\t\t\t\t\tclassicalSupported: !!(block(val, 0, 3) & 0x01),\n\t\t\t\t\tlongRangeSupported: !!(block(val, 0, 3) & 0x02),\n\t\t\t\t}\n\t\t\t},\n\t\t}\n\n\t\tvar lambda = typeMap[code.typeCritical];\n\t\tif (lambda) {\n\t\t\treturn lambda(code.value);\n\t\t}\n\n\t\treturn {}\n\t}\n\n\tfunction strCodeToSecurity(code) {\n\t\treturn {\n\t\t\tS2ReqKeys: decStrToHexStr(code),\n\t\t\tS2Unauthenticated: !!(code & 0x01),\n\t\t\tS2Authenticated: !!(code & 0x02),\n\t\t\tS2AccessControl : !!(code & 0x04),\n\t\t\tS0: !!(code  & 0x80)\n\t\t}\n\t}\n\n\tfunction parseTypes(types) {\n\t\tvar result = {};\n\t\t_.forEach(types, function (type) {\n\t\t\t_.extendOwn(result, codeToDevice(type));\n\t\t})\n\n\t\treturn result;\n\t}\n\n\tfunction parseWithProductType(entry) {\n\t\tvar result = {\n\t\t\tDSK: null\n\t\t};\n\n\t\tvar info = entry.match(/^90(\\d{2})(\\d{5})(\\d{3})(\\d{40})(\\d+)$/);\n\t\tvar types;\n\t\tif (info && checkHashSum(entry, info[2]) && (types = extractType(info[5]))) {\n\t\t\tresult = {\n\t\t\t\tVersion: decStrToHexStr(info[1]),\n\t\t\t\tisSmartStart: info[1] === '01',\n\t\t\t\tChksum: decStrToHexStr(info[2]),\n\t\t\t\tDSK: info[4].match(/\\d{5}/g).join('-'),\n\t\t\t}\n\t\t\t_.extendOwn(result, strCodeToSecurity(info[3]), parseTypes(types), { isValid: true })\n\t\t}\n\n\t\treturn result;\n\t}\n\n\tfunction storeDsk(self, dskEntry) {\n\t\tif (_.find(self.dskCollection, function (item) {\n\t\t\treturn item.ZW_QR === dskEntry.ZW_QR;\n\t\t})) {\n\t\t\treturn 409; // already exits key\n\t\t}\n\n\t\tself.dskCollection.push(dskEntry);\n\n\t\tif (dskEntry.DSK) {\n\t\t\tvar dskProvisioningList = self.getDSKProvisioningList();\n\n\t\t\t// add DSK to provisioning list\n\t\t\tdskProvisioningList.push(dskEntry.DSK);\n\n\t\t\t// save dskProvisioningList\n\t\t\tself.saveDSKProvisioningList(dskProvisioningList);\n\t\t}\n\n\t\tself.saveObject(\"dskCollection\", self.dskCollection, true);\n\n\t\treturn 200; // success\n\t}\n\n\tvar dskEntry = {\n\t\tid: findSmallestNotAssignedIntegerValue(this.dskCollection, 'id'),\n\t\tisSmartStart: false,\n\t\tstate: 'pending',\n\t\tnodeId: null,\n\t\ttimestamp: Date.now(),\n\t\tZW_QR: entry,\n\t\tPId: '',\n\t\tgivenName: null,\n\t\tlocation: 0,\n\t\taddedAt: null,\n\t\tDSK: null,\n\t\tisValid: false,\n\t\tclassicalSupported: true,\n\t\tlongRangeSupported: false,\n\t}\n\n\tvar parsers = [parseWithProductType, parseWithoutProductType, parseWithZws2dskPrefix];\n\tvar parsed = {};\n\n\n\tfor (var index = 0; index < parsers.length; ++index) {\n\t\tparsed = parsers[index](entry);\n\t\tif (parsed.DSK) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tdskEntry = _.extend(dskEntry, parsed);\n\n\treturn storeDsk(this, dskEntry);\n};\n\n/*\n * this function allows you to update a S2 or Smart Start QR code entry from this.dskCollection\n * DSKs of changed entries will also be changed automatically in the provisioning list\n */\nZWave.prototype.updateDSKEntry = function(dskEntry) {\n\tvar oldDSKEntry = {},\n\t    entryIndex = _.findIndex(this.dskCollection, function(entry) {\n\t\treturn entry.id === dskEntry.id;\n\t    }),\n\t    successful = false;\n\n\t// update DSK in provisioning list and this.dskCollection\n\ttry {\n\t\t// check this entry id already exists\n\t\tif (entryIndex > -1 && this.dskCollection[entryIndex]) {\n\t\t\t// fetch old DSK entry\n\t\t\toldDSKEntry = this.dskCollection[entryIndex];\n\n\t\t\t// replace old DSK entry\n\t\t\tthis.dskCollection[entryIndex] = dskEntry;\n\n\t\t\t// get dskProvisioningList\n\t\t\tdskProvisioningList = this.getDSKProvisioningList();\n\n\t\t\t// update provisioning list\n\t\t\tdskIndex = _.findIndex(dskProvisioningList, function(entry) {\n\t\t\t\treturn oldDSKEntry['DSK'] === entry;\n\t\t\t});\n\n\t\t\t// replace the provisioning list entry\n\t\t\tif (dskIndex > -1 && dskProvisioningList[dskIndex] !== dskEntry['DSK']) {\n\t\t\t\tdskProvisioningList[dskIndex] = dskEntry['DSK'];\n\t\t\t\t// save dskProvisioningList\n\t\t\t\tthis.saveDSKProvisioningList(dskProvisioningList);\n\t\t\t} else if (dskProvisioningList[dskIndex] !== dskEntry['DSK']) {\n\t\t\t\tdskProvisioningList.push(dskEntry['DSK']);\n\t\t\t\t// save dskProvisioningList\n\t\t\t\tthis.saveDSKProvisioningList(dskProvisioningList);\n\t\t\t}\n\n\t\t\t// save dsk collection\n\t\t\tthis.saveObject(\"dskCollection\", this.dskCollection, true);\n\n\t\t\tsuccessful = true;\n\t\t}\n\t} catch (e) {\n\t\tthis.addNotification(\"error\", 'Update DSK entry error: ' + e.toString(), \"module\");\n\t}\n\n\treturn successful;\n};\n\n/*\n * this function allows you to remove a S2 or Smart Start QR code entry from this.dskCollection\n * DSKs of removed entries will also be removed automatically from the provisioning list\n */\nZWave.prototype.removeDSKEntry = function(dskEntryID) {\n\tvar oldDSKEntry = {},\n\t    entryIndex = _.findIndex(this.dskCollection, function(entry) {\n\t\treturn entry.id === dskEntryID || entry.id === parseInt(dskEntryID, 10);\n\t    }),\n\t    successful = false;\n\n\t// remove DSK from provisioning list\n\ttry {\n\t\tif (entryIndex > -1 && this.dskCollection[entryIndex]) {\n\t\t\t// fetch old DSK entry\n\t\t\toldDSKEntry = this.dskCollection[entryIndex];\n\n\t\t\t// remove DSK entry\n\t\t\tthis.dskCollection.splice(entryIndex, 1);\n\n\t\t\t// get dskProvisioningList\n\t\t\tdskProvisioningList = this.getDSKProvisioningList();\n\n\t\t\t// remove from provisioning list\n\t\t\tdskProvisioningList = _.filter(dskProvisioningList, function(dsk) {\n\t\t\t\treturn dsk !== oldDSKEntry['DSK'];\n\t\t\t});\n\n\t\t\t// save dskProvisioningList\n\t\t\tthis.saveDSKProvisioningList(dskProvisioningList);\n\n\t\t\t// save dsk collection\n\t\t\tthis.saveObject(\"dskCollection\", this.dskCollection, true);\n\n\t\t\tsuccessful = true;\n\t\t}\n\t} catch (e) {\n\t\tthis.addNotification(\"error\", 'Remove DSK entry error: ' + e.toString(), \"module\");\n\t}\n\n\treturn successful;\n};\n\n/*\n * this function allows you to get all S2 or Smart Start QR code entries from this.dskCollection\n * or excactly one specified by it's entry id\n */\nZWave.prototype.getDSKCollection = function(dskEntryID) {\n\tif (dskEntryID) {\n\t\tvar dskEntry = _.filter(this.dskCollection, function(dskEntry) {\n\t\t\treturn dskEntry.id === dskEntryID || dskEntry.id === parseInt(dskEntryID, 10);\n\t\t});\n\n\t\treturn dskEntry[0] ? dskEntry[0] : [];\n\t} else {\n\t\treturn this.dskCollection;\n\t}\n}\n\nZWave.prototype.networkReorganizationInit = function() {\n\t// 1. Walk thru all mains first\n\t// 1.1 If some failes, do them in second round and repeat it N_TRIES times (max hops in Z-Wave)\n\t// 2. Walk thru all FLiRS (N_TRIES tries)\n\t// 3. Walk thru batteries\n\t\n\tvar N_TRIES = 4;\n\n\tfunction NetworkReorganization(that) {\n\t\tthis.nodes = [];\n\t\tthis.log = [];\n\t\t\n\t\tthis.zway = that.zway;\n\t\tthis.langFile = that.loadModuleLang();\n\t}\n\n\tNetworkReorganization.prototype.start = function() {\n\t\tthis.addLog(this.langFile.reorg_start, 0);\n\t\t\n\t\tthis.nodes = this.getNodesList();\n\t\t\n\t\tthis.log = [];\n\n\t\tthis.checkNextStep();\n\t};\n\n\tNetworkReorganization.prototype.getNodesList = function() {\n\t\tvar self = this;\n\t\t\n\t\treturn Object.keys(this.zway.devices).filter(function(nodeId) {\n\t\t\t// filter self and portable controllers\n\t\t\treturn nodeId != self.zway.controller.data.nodeId.value && self.zway.devices[nodeId].data.basicType.value !== 1;\n\t\t}).map(function(nodeId) {\n\t\t\tvar node = self.zway.devices[nodeId],\n\t\t\t    isListening = node.data.isListening.value,\n\t\t\t    isFLiRS = node.data.sensor250.value || node.data.sensor1000.value;\n\t\t\t\n\t\t\treturn {\n\t\t\t\tnodeId: nodeId,\n\t\t\t\tisMains: isListening,\n\t\t\t\tisFLiRS: isFLiRS,\n\t\t\t\tisSleeping: !isListening && !isFLiRS,\n\t\t\t\ttries: 0,\n\t\t\t\tfail: false,\n\t\t\t\tdone: false\n\t\t\t};\n\t\t});\n\t};\n\n\tNetworkReorganization.prototype.getNodeById = function(nodeId) {\n\t\treturn this.nodes.filter(function(node) { return nodeId == node.nodeId; })[0];\n\t};\n\n\tNetworkReorganization.prototype.successCbk = function(nodeId) {\n\t\tthis.addLog(this.langFile.reorg_node_done, nodeId);\n\t\t\n\t\tvar node = this.getNodeById(nodeId);\n\t\tif (node) {\n\t\t\tnode.done = true;\n\t\t}\n\t\t\n\t\tthis.assignRoutesToAssociated(nodeId);\n\t\t\n\t\tthis.checkNextStep();\n\t};\n\n\tNetworkReorganization.prototype.failureCbk = function(nodeId) {\n\t\tthis.addLog(this.langFile.reorg_node_failed, nodeId);\n\t\t\n\t\tvar node = this.getNodeById(nodeId);\n\t\tif (node) {\n\t\t\tnode.tries++;\n\t\t\tif (node.tries < N_TRIES) {\n\t\t\t\tthis.doNode(nodeId); // it will be placed after all existing jobs, so no need to wait before placing this job\n\t\t\t} else {\n\t\t\t\tnode.fail = true;\n\t\t\t}\n\t\t}\n\t\t\n\t\tthis.checkNextStep();\n\t};\n\n\tNetworkReorganization.prototype.doNode = function(nodeId) {\n\t\tif (!this.zway.devices[nodeId].data.isFailed.value) {\n\t\t\tthis.addLog(this.langFile.reorg_node_start, nodeId);\n\t\t\n\t\t\tvar self = this;\n\t\t\n\t\t\tthis.zway.RequestNodeNeighbourUpdate(nodeId, function() {\n\t\t\t\tself.successCbk(nodeId);\n\t\t\t}, function() {\n\t\t\t\tself.failureCbk(nodeId);\n\t\t\t});\n\t\t} else {\n\t\t\tthis.getNodeById(nodeId).fail = true;\n\t\t\tthis.addLog(this.langFile.reorg_node_skip, nodeId);\n\t\t}\n\t};\n\n\tNetworkReorganization.prototype.getAssociations = function(nodeId) {\n\t\tvar nodes = [];\n\t\t\n\t\t// Association & MultiChannelAssociation\n\t\tfor(var i in this.zway.devices[nodeId].instances) {\n\t\t\tif (this.zway.devices[nodeId].instances[i].Association) {\n\t\t\t\tfor(var g in this.zway.devices[nodeId].instances[i].Association.data) {\n\t\t\t\t\tif (parseInt(g)) {\n\t\t\t\t\t\tnodes = nodes.concat(this.zway.devices[nodeId].instances[i].Association.data[g].nodes.value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (this.zway.devices[nodeId].instances[i].MultiChannelAssociation) {\n\t\t\t\tfor(var g in this.zway.devices[nodeId].instances[i].MultiChannelAssociation.data) {\n\t\t\t\t\tif (parseInt(g)) {\n\t\t\t\t\t\tnodes = nodes.concat(this.zway.devices[nodeId].instances[i].MultiChannelAssociation.data[g].nodesInstances.value.filter(function(e, i) { return i % 2 == 0; }));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (this.zway.devices[nodeId].Wakeup) {\n\t\t\tnodes.push(this.zway.devices[nodeId].Wakeup.data.nodeId.value);\n\t\t}\n\t\t\n\t\treturn nodes.filter(function(e, i, s) {\n\t\t\treturn s.indexOf(e) === i; // unique\n\t\t});\n\t};\n\n\tNetworkReorganization.prototype.assignRoutesToAssociated = function(nodeId) {\n\t\tvar self = this,\n\t\t    associations = this.getAssociations(nodeId);\n\t\t\n\t\t// clear all routes\n\t\tthis.zway.devices[nodeId].DeleteSUCReturnRoute();\n\t\tthis.zway.devices[nodeId].DeleteReturnRoute();\n\t\t\n\t\t// return routes to SUC\n\t\tthis.zway.devices[nodeId].AssignSUCReturnRoute();\n\t\t\n\t\t// return routes to associated devices\n\t\tassociations.forEach(function(association) {\n\t\t\tself.zway.devices[nodeId].AssignReturnRoute(association);\n\t\t});\n\t};\n\t\n\tNetworkReorganization.prototype.checkNextStep = function() {\n\t\tvar self = this;\n\t\t\n\t\tvar finishedMains = true,\n\t\t    finishedFLiRS = true,\n\t\t    finishedSleeping = true,\n\t\t    hasMains = false,\n\t\t    hasFLiRS = false,\n\t\t    hasSleeping = false,\n\t\t    startedMains = false,\n\t\t    startedFLiRS = false,\n\t\t    startedSleeping = false;\n\t\t\n\t\tthis.nodes.forEach(function(node) {\n\t\t\tif (node.isMains) {\n\t\t\t\tfinishedMains &= node.done || node.fail;\n\t\t\t\tstartedMains |= node.done || node.tries > 0;\n\t\t\t\thasMains = true;\n\t\t\t}\n\t\t\tif (node.isFLiRS) {\n\t\t\t\tfinishedFLiRS &= node.done || node.fail;\n\t\t\t\tstartedFLiRS |= node.done || node.tries > 0;\n\t\t\t\thasFLiRS = true;\n\t\t\t}\n\t\t\tif (node.isSleeping) {\n\t\t\t\tfinishedSleeping &= node.done || node.fail;\n\t\t\t\tstartedSleeping |= node.done || node.tries > 0;\n\t\t\t\thasSleeping = true;\n\t\t\t}\n\t\t});\n\t\t\n\t\t// if no devices of that type, skip the block\n\t\tfinishedMains |= !hasMains;\n\t\tfinishedFLiRS |= !hasFLiRS;\n\t\tfinishedSleeping |= !hasSleeping;\n\t\t\n\t\tif (!finishedMains && !startedMains) {\n\t\t\tthis.addLog(this.langFile.reorg_start_mains, 0);\n\t\t\t\n\t\t\tthis.nodes.forEach(function(node) {\n\t\t\t\tif (node.isMains) {\n\t\t\t\t\tself.doNode(node.nodeId);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\tif (finishedMains && !finishedFLiRS && !startedFLiRS) {\n\t\t\tthis.addLog(this.langFile.reorg_start_flirs, 0);\n\t\t\n\t\t\tthis.nodes.forEach(function(node) {\n\t\t\t\tif (node.isFLiRS) {\n\t\t\t\t\tself.doNode(node.nodeId);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tif (finishedMains && finishedFLiRS && !finishedSleeping && !startedSleeping) {\n\t\t\tthis.addLog(this.langFile.reorg_start_battery, 0);\n\t\t\n\t\t\tthis.nodes.forEach(function(node) {\n\t\t\t\tif (node.isSleeping) {\n\t\t\t\t\tself.doNode(node.nodeId);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t\n\t\tif (finishedMains && finishedFLiRS && finishedSleeping) {\n\t\t\tthis.addLog(this.langFile.reorg_finished, 0);\n\t\t}\n\t};\n\n\tNetworkReorganization.prototype.addLog = function(message, nodeId) {\n\t\tthis.log.push({\n\t\t\tupdatetime: Date.now(),\n\t\t\tmessage: message,\n\t\t\tnodeId: nodeId\n\t\t});\n\t\tconsole.log(this.langFile.reorg_title + \": \" + (nodeId ? (this.langFile.reorg_node_title + nodeId + \" \") : \"\") + message);\n\t};\n\t\n\tNetworkReorganization.prototype.getLog = function() {\n\t\treturn this.log;\n\t};\n\t\n\tthis.networkReorganization = new NetworkReorganization(this);\n};\n\n// --------------- Public HTTP API -------------------\n\n\nZWave.prototype.externalAPIAllow = function(name) {\n\tvar _name = !!name ? (\"ZWave.\" + name) : \"ZWaveAPI\";\n\n\tws.allowExternalAccess(_name, this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Run\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Data\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".InspectQueue\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Backup\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Restore\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".CreateZDDX\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".CommunicationStatistics\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".CommunicationHistory\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".PacketLog\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ClearPacketLog\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Zniffer\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Zniffer.SetPromisc\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".RSSIGet\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".TestNode\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".FirmwareUpdate\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMELicense\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMEFirmwareUpgrade\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMEBootloaderUpgrade\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".PostfixUpdate\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Postfix\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".PostfixAdd\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".PostfixGet\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".PostfixRemove\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ExpertConfigGet\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ExpertConfigUpdate\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".CallForAllNIF\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".CheckAllLinks\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".sendZWayReport\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".NetworkReorganization\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".GetReorganizationLog\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".GetStatisticsData\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ClearStatisticsData\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".GetDSKProvisioningList\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".AddDSKProvisioningEntry\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".GetDSKCollection\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".RemoveDSKEntry\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".AddDSKEntry\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".UpdateDSKEntry\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".EncryptionKeys\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\t// -- see below -- // ws.allowExternalAccess(_name + \".JSONtoXML\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n};\n\nZWave.prototype.externalAPIRevoke = function(name) {\n\tvar _name = !!name ? (\"ZWave.\" + name) : \"ZWaveAPI\";\n\n\tws.revokeExternalAccess(_name);\n\tws.revokeExternalAccess(_name + \".Run\");\n\tws.revokeExternalAccess(_name + \".Data\");\n\tws.revokeExternalAccess(_name + \".InspectQueue\");\n\tws.revokeExternalAccess(_name + \".Backup\");\n\tws.revokeExternalAccess(_name + \".Restore\");\n\tws.revokeExternalAccess(_name + \".CreateZDDX\");\n\tws.revokeExternalAccess(_name + \".CommunicationStatistics\");\n\tws.revokeExternalAccess(_name + \".CommunicationHistory\");\n\tws.revokeExternalAccess(_name + \".PacketLog\");\n\tws.revokeExternalAccess(_name + \".ClearPacketLog\");\n\tws.revokeExternalAccess(_name + \".Zniffer\");\n\tws.revokeExternalAccess(_name + \".Zniffer.SetPromisc\");\n\tws.revokeExternalAccess(_name + \".RSSIGet\");\n\tws.revokeExternalAccess(_name + \".TestNode\");\n\tws.revokeExternalAccess(_name + \".FirmwareUpdate\");\n\tws.revokeExternalAccess(_name + \".ZMELicense\");\n\tws.revokeExternalAccess(_name + \".ZMEFirmwareUpgrade\");\n\tws.revokeExternalAccess(_name + \".ZMEBootloaderUpgrade\");\n\tws.revokeExternalAccess(_name + \".PostfixUpdate\");\n\tws.revokeExternalAccess(_name + \".Postfix\");\n\tws.revokeExternalAccess(_name + \".PostfixAdd\");\n\tws.revokeExternalAccess(_name + \".PostfixGet\");\n\tws.revokeExternalAccess(_name + \".PostfixRemove\");\n\tws.revokeExternalAccess(_name + \".ExpertConfigGet\");\n\tws.revokeExternalAccess(_name + \".ExpertConfigUpdate\");\n\tws.revokeExternalAccess(_name + \".CallForAllNIF\");\n\tws.revokeExternalAccess(_name + \".CheckAllLinks\");\n\tws.revokeExternalAccess(_name + \".sendZwayReport\");\n\tws.revokeExternalAccess(_name + \".NetworkReorganization\");\n\tws.revokeExternalAccess(_name + \".GetReorganizationLog\");\n\tws.revokeExternalAccess(_name + \".GetStatisticsData\");\n\tws.revokeExternalAccess(_name + \".ClearStatisticsData\");\n\tws.revokeExternalAccess(_name + \".GetDSKProvisioningList\");\n\tws.revokeExternalAccess(_name + \".AddDSKProvisioningEntry\");\n\tws.revokeExternalAccess(_name + \".GetDSKCollection\");\n\tws.revokeExternalAccess(_name + \".RemoveDSKEntry\");\n\tws.revokeExternalAccess(_name + \".AddDSKEntry\");\n\tws.revokeExternalAccess(_name + \".UpdateDSKEntry\");\n\tws.revokeExternalAccess(_name + \".EncryptionKeys\");\n\t// -- see below -- // ws.revokeExternalAccess(_name + \".JSONtoXML\");\n};\n\nZWave.prototype.defineHandlers = function() {\n\tvar zway = this.zway; // for with() statement in Run and other APIs\n\tvar postfix = this.postfix;\n\tvar self = this;\n\n\tvar ipacket = this.ipacket;\n\tvar opacket = this.opacket;\n\tvar iPacketBuffer = this.iPacketBuffer;\n\tvar oPacketBuffer = this.oPacketBuffer;\n\n\tvar statistics = this.statistics;\n\n\tthis.ZWaveAPI = function() {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Bad ZWaveAPI request \"\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.list = function() {\n\t\ttry {\n\t\t\treturn ZWave.list() || [];\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.Run = function(url) {\n\t\turl = \"with(zway) { \" + url.substring(1) + \" }\";\n\t\ttry {\n\t\t\tvar r = eval(url);\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: r\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.Data = function(url) {\n\t\tvar timestamp = parseInt(url.substring(1), 10) || 0;\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zway.data(timestamp)\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.InspectQueue = function(url) {\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zway.InspectQueue()\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.Backup = function(url, request) {\n\t\tvar now = new Date();\n\n\t\t// create a timestamp in format yyyy-MM-dd-HH-mm\n\t\tvar ts = getHRDateformat(now);\n\n\t\ttry {\n\n\t\t\t// do backup\n\t\t\tvar data = zway.controller.Backup();\n\t\t\tvar filename = \"z-way-backup-\" + ts + \".zbk\"\n\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/x-download\",\n\t\t\t\t\t\"Content-Disposition\": \"attachment; filename=\" + filename\n\t\t\t\t},\n\t\t\t\tbody: data\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.sendZWayReport = function(url, request) {\n\t\tvar lines = '',\n\t\t\tq = request.query,\n\t\t\ttestLines = function(lines) {\n\t\t\t\tvar l = parseInt(lines, 10);\n\t\t\t\treturn l > 0 && l <= 20000 || false;\n\t\t\t},\n\t\t\tlogAvailable = fs.stat('lib/fetchLog.sh'),\n\t\t\treport_url = \"https://service.z-wave.me/report/index.php\",\n\t\t\tret = false,\n\t\t\tformElements = [],\n\t\t\treqObj = request.body ? request.body : request.data,\n\t\t\tdata;\n\n\t\treqObj = reqObj && typeof reqObj !== 'string' ? reqObj : JSON.parse(reqObj);\n\n\t\t//TODO: Implement for Multiple zways\n\t\t/*function createBackup(){\n\t\t\tvar zwayBcp = {}\n\t\t\t// do backup\n\t\t\tglobal.ZWave.list().forEach(function(zwayName) {\n\t\t\t\tvar bcp = \"\",\n\t\t\t\t\tdata = new Uint8Array(global.ZWave[zwayName].zway.controller.Backup());\n\n\t\t\t\tfor(var i = 0; i < data.length; i++) {\n\t\t\t\t\tbcp += String.fromCharCode(data[i]);\n\t\t\t\t}\n\n\t\t\t\tzwayBcp[zwayName] = bcp;\n\t\t\t});\n\n\t\t\treturn zwayBcp;\n\t\t}*/\n\n\t\tfunction createBackup() {\n\t\t\tvar zwayBcp = []\n\n\t\t\t// do backup\n\t\t\tvar bcp = \"\",\n\t\t\t\tdata = new Uint8Array(zway.controller.Backup());\n\n\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\tbcp += String.fromCharCode(data[i]);\n\t\t\t}\n\n\t\t\tzwayBcp = bcp;\n\n\t\t\treturn zwayBcp;\n\t\t}\n\n\t\tif (q && logAvailable) {\n\t\t\tlines = q.lines && !_.isNaN(q.lines) && testLines(q.lines) ? parseInt(q.lines, 10) : lines;\n\t\t}\n\n\t\tif (logAvailable) {\n\t\t\t//grep log and add to config/map\n\t\t\tsystem(\"sh automation/lib/fetchLog.sh getLog \" + lines);\n\n\t\t\tdata = createBackup();\n\n\t\t\t//cleanup log's in config/map directory\n\t\t\tsystem(\"sh automation/lib/fetchLog.sh removeLog\");\n\t\t} else {\n\t\t\tdata = createBackup();\n\t\t}\n\n\t\ttry {\n\t\t\tvar now = new Date();\n\t\t\t// create a timestamp in format yyyy-MM-dd-HH-mm\n\t\t\tvar ts = getHRDateformat(now);\n\t\t\tvar box_type = 'z-way';\n\n\t\t\t// prepare system information\n\t\t\tfor (param in reqObj) {\n\t\t\t\tformElements.push({\n\t\t\t\t\tname: param,\n\t\t\t\t\tvalue: reqObj[param].toString()\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (data) {\n\t\t\t\t// add backup with log\n\t\t\t\tformElements.push({\n\t\t\t\t\tname: 'log_name',\n\t\t\t\t\tvalue: \"report-\" + box_type + \"-backup-log-\" + ts + \".tgz\"\n\t\t\t\t}, {\n\t\t\t\t\tname: 'log_data',\n\t\t\t\t\tvalue: Base64.encode(JSON.stringify(data))\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tres = formRequest.send(formElements, \"POST\", report_url);\n\n\t\t\tif (res.status === -1) { //error e.g. no connection to server\n\t\t\t\tself.addNotification(\"error\", res.statusText, \"module\");\n\t\t\t} else {\n\t\t\t\tif (res.status === 200) {\n\t\t\t\t\tret = true;\n\t\t\t\t\tself.addNotification(\"info\", res.data.message, \"module\");\n\t\t\t\t} else {\n\t\t\t\t\tself.addNotification(\"error\", res.data.message, \"module\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t}\n\t\t}\n\t\treturn ret;\n\t};\n\n\tthis.ZWaveAPI.Restore = function(url, request) {\n\t\tif (request.method === \"POST\" && request.data && request.data && request.data.config_backup) {\n\t\t\tvar full = false;\n\t\t\tif (request.query && request.query.hasOwnProperty(\"restore_chip_info\")) {\n\t\t\t\tvar rci = request.query[\"restore_chip_info\"];\n\t\t\t\tfull = (rci === \"yes\" || rci === \"true\" || rci === \"1\");\n\t\t\t}\n\n\t\t\tvar file = request.data.config_backup;\n\t\t\tif (file instanceof Array) {\n\t\t\t\tfile = file[0];\n\t\t\t}\n\t\t\tif (file.name && file.content && file.length > 0) {\n\t\t\t\t// valid file object detected\n\t\t\t\ttry {\n\t\t\t\t\tzway.controller.Restore(file.content, full);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: null\n\t\t\t\t\t};\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tbody: e.toString()\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid request\"\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.CreateZDDX = function(url, request) {\n\t\tfunction hexByteToStr(n) {\n\t\t\treturn (\"00\" + parseInt(n, 10).toString(16)).slice(-2);\n\t\t}\n\n\t\tfunction intToHexStr(value, size) {\n\t\t\treturn ('00000000' + parseInt(value, 10).toString(16)).slice(-size);\n\t\t}\n\t\tfunction hexWordToStr(n) {\n\t\t\treturn (\"0000\" + parseInt(n, 10).toString(16)).slice(-4);\n\t\t}\n\n\t\tfunction tagAttrValue(name, value) {\n\t\t\treturn {\n\t\t\t\t\"name\": name,\n\t\t\t\t\"attributes\": {\n\t\t\t\t\t\"value\": value\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tfunction tagByte(name, value) {\n\t\t\treturn tagAttrValue(name, hexByteToStr(value));\n\t\t}\n\n\t\tfunction tagWord(name, value) {\n\t\t\treturn tagAttrValue(name, hexWordToStr(value));\n\t\t}\n\n\t\tfunction tagBool(name, value) {\n\t\t\treturn tagAttrValue(name, value ? \"true\" : \"false\");\n\t\t}\n\n\t\tfunction tagText(name, value) {\n\t\t\treturn {\n\t\t\t\t\"name\": name,\n\t\t\t\t\"text\": value\n\t\t\t};\n\t\t}\n\n\t\tfunction tagLangs(name, values) {\n\t\t\tvar\n\t\t\t\tlang,\n\t\t\t\tlangChildren = [];\n\n\t\t\tfor (lang in values) {\n\t\t\t\tlangChildren.push({\n\t\t\t\t\t\"name\": \"lang\",\n\t\t\t\t\t\"attributes\": {\n\t\t\t\t\t\t\"xml:lang\": lang\n\t\t\t\t\t},\n\t\t\t\t\t\"text\": values[lang]\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"name\": name,\n\t\t\t\t\"children\": langChildren\n\t\t\t};\n\t\t}\n\n\t\tfunction inNIF(id, nif, afterMark) {\n\t\t\tvar\n\t\t\t\ti,\n\t\t\t\tmarkFound = false;\n\n\t\t\tid = parseInt(id, 10);\n\t\t\tfor (i in nif) {\n\t\t\t\tif (nif[i] === 0xEF) {\n\t\t\t\t\tmarkFound = true;\n\t\t\t\t}\n\n\t\t\t\tif (!(afterMark ^ markFound) && parseInt(nif[i], 10) === id) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tfunction tagCC(id, version, supported, secure, nif) {\n\t\t\treturn {\n\t\t\t\t\"name\": \"commandClass\",\n\t\t\t\t\"attributes\": {\n\t\t\t\t\t\"id\": hexWordToStr(id),\n\t\t\t\t\t\"version\": version,\n\t\t\t\t\t\"supported\": supported || inNIF(id, nif, false),\n\t\t\t\t\t\"controlled\": !supported || inNIF(id, nif, true),\n\t\t\t\t\t\"secure\": secure,\n\t\t\t\t\t\"inNIF\": (supported && inNIF(id, nif, false)) || (!supported && inNIF(id, nif, true))\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\tvar nodeId = url.split(\"/\")[1],\n\t\t\td = zway.devices[nodeId],\n\t\t\tzddx = new ZXmlDocument();\n\n\t\tzddx.root = {\n\t\t\t\"name\": \"ZWaveDevice\",\n\t\t\t\"attributes\": {\n\t\t\t\t\"xmlns\": \"http://www.pepper1.net/zwavedb/xml-schemata/z-wave\",\n\t\t\t\t\"schemaVersion\": \"2\"\n\t\t\t},\n\t\t\t\"children\": [{\n\t\t\t\t\"name\": \"descriptorVersion\",\n\t\t\t\t\"text\": \"1\"\n\t\t\t}, {\n\t\t\t\t\"name\": \"deviceData\",\n\t\t\t\t\"children\": [\n\t\t\t\t\ttagWord(\"manufacturerId\", d.data.manufacturerId.value),\n\t\t\t\t\ttagWord(\"productType\", d.data.manufacturerProductType.value),\n\t\t\t\t\ttagWord(\"productId\", d.data.manufacturerProductId.value),\n\t\t\t\t\ttagByte(\"libType\", d.data.ZWLib.value),\n\t\t\t\t\ttagByte(\"protoVersion\", d.data.ZWProtocolMajor.value),\n\t\t\t\t\ttagByte(\"protoSubVersion\", d.data.ZWProtocolMinor.value),\n\t\t\t\t\ttagByte(\"appVersion\", d.data.applicationMajor.value),\n\t\t\t\t\ttagByte(\"appSubVersion\", d.data.applicationMinor.value),\n\t\t\t\t\ttagByte(\"basicClass\", d.data.basicType.value),\n\t\t\t\t\ttagByte(\"genericClass\", d.data.genericType.value),\n\t\t\t\t\ttagByte(\"specificClass\", d.data.specificType.value),\n\t\t\t\t\ttagBool(\"optional\", d.data.optional.value),\n\t\t\t\t\ttagBool(\"listening\", d.data.isListening.value),\n\t\t\t\t\ttagBool(\"routing\", d.data.isRouting.value),\n\t\t\t\t\ttagText(\"beamSensor\", d.data.sensor250.value ? \"250\" : (d.data.sensor1000.value ? \"1000\" : \"0\"))\n\t\t\t\t]\n\t\t\t}, {\n\t\t\t\t\"name\": \"deviceDescription\",\n\t\t\t\t\"children\": [\n\t\t\t\t\ttagLangs(\"description\", {\n\t\t\t\t\t\t\"en\": \"\"\n\t\t\t\t\t}),\n\t\t\t\t\ttagLangs(\"wakeupNote\", {\n\t\t\t\t\t\t\"en\": \"\"\n\t\t\t\t\t}),\n\t\t\t\t\ttagLangs(\"inclusionNote\", {\n\t\t\t\t\t\t\"en\": \"\"\n\t\t\t\t\t}),\n\t\t\t\t\ttagText(\"productName\", \"\"),\n\t\t\t\t\ttagText(\"brandName\", \"\"),\n\t\t\t\t\ttagText(\"productVersion\", d.data.applicationMajor.value.toString() + \".\" + d.data.applicationMinor.value.toString())\n\t\t\t\t]\n\t\t\t}, {\n\t\t\t\t\"name\": \"commandClasses\",\n\t\t\t\t\"children\": (function() {\n\t\t\t\t\tvar\n\t\t\t\t\t\tccId, n,\n\t\t\t\t\t\tarr = [],\n\t\t\t\t\t\tccs = d.instances[0].commandClasses;\n\n\t\t\t\t\tfor (ccId in ccs) {\n\t\t\t\t\t\tarr.push(tagCC(ccId, ccs[ccId].data.version.value, ccs[ccId].data.supported.value, ccs[ccId].data.security.value, d.data.nodeInfoFrame.value));\n\t\t\t\t\t}\n\t\t\t\t\tfor (n in d.data.nodeInfoFrame.value) {\n\t\t\t\t\t\tccId = d.data.nodeInfoFrame.value[n];\n\t\t\t\t\t\tif (!ccs[ccId] && ccId !== 0xEF) {\n\t\t\t\t\t\t\tarr.push(tagCC(ccId, 1, false, false, d.data.nodeInfoFrame.value));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn arr;\n\t\t\t\t})()\n\t\t\t}]\n\t\t};\n\n\t\tif (d.instances[0].Association) {\n\t\t\tzddx.root.insertChild({\n\t\t\t\t\"name\": \"assocGroups\",\n\t\t\t\t\"children\": (function(data) {\n\t\t\t\t\tvar\n\t\t\t\t\t\tn,\n\t\t\t\t\t\tAssocs = [];\n\n\t\t\t\t\tfor (n = 1; n <= data.groups.value; n++) {\n\t\t\t\t\t\tAssocs.push({\n\t\t\t\t\t\t\t\"name\": \"assocGroup\",\n\t\t\t\t\t\t\t\"attributes\": {\n\t\t\t\t\t\t\t\t\"number\": n,\n\t\t\t\t\t\t\t\t\"maxNodes\": data[n].max.value\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\ttagLangs(\"description\", {\n\t\t\t\t\t\t\t\t\t\"en\": \"Group \" + n.toString()\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn Assocs;\n\t\t\t\t})(d.instances[0].Association.data)\n\t\t\t});\n\t\t}\n\n\t\tif(d.instances[0].commandClasses\n\t\t\t&& d.instances[0].commandClasses[112]\n\t\t\t&& d.instances[0].commandClasses[112].data.version.value >= 3 ) {\n\t\t\tzddx.root.insertChild({\n\t\t\t\tname: 'configParams',\n\t\t\t\tchildren: (function (data) {\n\t\t\t\t\tvar result = [];\n\t\t\t\t\tfor (var key in data) {\n\t\t\t\t\t\tif (isNaN(+key)) continue;\n\t\t\t\t\t\tvar param = data[key];\n\t\t\t\t\t\tresult.push({\n\t\t\t\t\t\t\tname: 'configParam',\n\t\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\tnumber: key,\n\t\t\t\t\t\t\t\tsize: param.size.value,\n\t\t\t\t\t\t\t\ttype: 'rangemapped',\n\t\t\t\t\t\t\t\tdefault: param.default.value,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t\ttagLangs('name', {en: param.title.value}),\n\t\t\t\t\t\t\t\ttagLangs('description', {en: param.description.value}),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tname: 'value',\n\t\t\t\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\t\t\tfrom: intToHexStr(param.min.value, param.size.value),\n\t\t\t\t\t\t\t\t\t\tto: intToHexStr(param.max.value, param.size.value)\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tchildren: [tagLangs('description', {en: ''}),]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\treturn  result;\n\t\t\t\t})(d.instances[0].commandClasses[112].data)\n\t\t\t})\n\t\t}\n\t\treturn {\n\t\t\t\"status\": 200,\n\t\t\t\"body\": zddx.toString(),\n\t\t\t\"headers\": {\n\t\t\t\t\"Content-Type\": \"application/xml\"\n\t\t\t}\n\t\t};\n\t};\n\n\tthis.CommunicationStatistics = function(zw) {\n\t\tthis.MAX_ARRAY_LENGTH = 30;\n\n\t\tthis.zw = zw;\n\t\tthis.zway = null;\n\t\tthis.communicationStatistics = {};\n\n\t\tthis.init(zw);\n\t}\n\n\tthis.CommunicationStatistics.prototype.init = function(zw) {\n\t\tvar self = this;\n\n\t\tif (!zw.zway) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.zway = zw.zway;\n\t\tthis.zway.controller.data.outgoingPacket.bind(this.handler, this, false);\n\t};\n\n\tthis.CommunicationStatistics.prototype.handler = function(type, self) {\n\t\tif (type === self.zw.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\t\tif (!self.communicationStatistics[this.nodeId.value]) {\n\t\t\tself.communicationStatistics[this.nodeId.value] = [];\n\t\t}\n\t\tself.communicationStatistics[this.nodeId.value].push({\n\t\t\t\"date\": Date.now() / 1000,\n\t\t\t\"delivered\": this.delivered.value,\n\t\t\t\"packetLength\": this.packetLength.value,\n\t\t\t\"deliveryTime\": this.deliveryTime.value\n\t\t});\n\t\tself.communicationStatistics[this.nodeId.value].splice(0, Math.max(self.communicationStatistics[this.nodeId.value].length - self.MAX_ARRAY_LENGTH, 0));\n\t};\n\n\tthis.CommunicationStatistics.prototype.stop = function() {\n\t\tif (!this.zway) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.zway.controller.data.outgoingPacket.unbind(this.handler);\n\n\t\tthis.communicationStatistics = {};\n\n\t\tthis.zway = null;\n\t};\n\n\tthis.CommunicationStatistics.prototype.get = function() {\n\t\treturn this.communicationStatistics;\n\t};\n\n\tthis.ZWaveAPI.CommunicationStatistics = (function(that) {\n\t\tvar cs = new that.CommunicationStatistics(that);\n\t\treturn function() {\n\t\t\treturn cs.get();\n\t\t};\n\t})(this);\n\n\tthis.ZWaveAPI.CommunicationHistory = function(url, request) {\n\t\tvar body = {\n\t\t\t\t\"code\": 200,\n\t\t\t\t\"message\": \"200 OK\",\n\t\t\t\t\"updateTime\": null,\n\t\t\t\t\"data\": []\n\t\t\t},\n\t\t\tpackets = self.parsedPackets.get(),\n\t\t\tfilterObj = null;\n\n\t\tif (request.query && request.query.filter) {\n\t\t\tfilterObj = typeof request.query.filter === 'string' ? JSON.parse(request.query.filter) : request.query.filter;\n\t\t}\n\n\t\tif (!_.isEmpty(packets)) {\n\t\t\tif (!_.isNull(filterObj)) {\n\t\t\t\tif (filterObj.src.value != \"\") {\n\t\t\t\t\tvar filter = packets.filter(function(p) {\n\t\t\t\t\t\t// filter by array of sources\n\t\t\t\t\t\tvar srcs = filterObj.src.value.split(',');\n\n\t\t\t\t\t\tif (parseInt(filterObj.src.show) === 1) {\n\t\t\t\t\t\t\treturn srcs.indexOf(p.src.toString()) > -1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn srcs.indexOf(p.src.toString()) < 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t});\n\t\t\t\t\tpackets = filter;\n\t\t\t\t}\n\n\t\t\t\tif (filterObj.dest.value != \"\") {\n\t\t\t\t\tfilter = packets.filter(function(p) {\n\t\t\t\t\t\t// filter by array of destinations\n\t\t\t\t\t\tvar dests = filterObj.dest.value.split(',');\n\n\t\t\t\t\t\tif (parseInt(filterObj.dest.show) === 1) {\n\t\t\t\t\t\t\treturn dests.indexOf(p.dest.toString()) > -1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn dests.indexOf(p.dest.toString()) < 0;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t});\n\n\t\t\t\t\tpackets = filter;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tbody.updateTime = Math.round(Date.now() / 1000);\n\t\tbody.data = packets;\n\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\tbody: body\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.Zniffer = function() {\n\t\tvar body = {\n\t\t\t\"code\": 200,\n\t\t\t\"message\": \"200 OK\",\n\t\t\t\"updateTime\": null,\n\t\t\t\"data\": []\n\t\t};\n\n\t\t// TODO(!!!) may be report only updates since last body.updateTime ?\n\t\tbody.data = _.filter(self.parsedPackets.get(), function(p) {\n\t\t\treturn p.id > (Date.now() - 10000);\n\t\t});\n\n\t\tbody.updateTime = Math.round(Date.now() / 1000);\n\t\tbody.data.reverse(); // newer on top\n\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: body\n\t\t};\n\t};\n\t\n\tthis.ZWaveAPI.Zniffer.SetPromisc = function(url, request) {\n\t\tvar body = {\n\t\t\t\"code\": 200,\n\t\t\t\"message\": \"200 OK\",\n\t\t\t\"updateTime\": null,\n\t\t\t\"data\": []\n\t\t};\n\t\t\n\t\tvar promiscMode = url.substring(1) === \"true\" || parseInt(url.substring(1), 10);\n\t\tself.zway.SetPromiscuousMode(promiscMode);\n\t\t\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: body\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.PacketLog = function() {\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: {\n\t\t\t\t\"code\": 200,\n\t\t\t\t\"message\": \"200 OK\",\n\t\t\t\t\"updateTime\": Math.round(Date.now() / 1000),\n\t\t\t\tdata: self.originPackets.get()\n\t\t\t}\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.ClearPacketLog = function() {\n\t\tself.originPackets.clear()\n\t\t\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: {\n\t\t\t\t\"code\": 200,\n\t\t\t\t\"message\": \"200 OK\",\n\t\t\t\t\"updateTime\": Math.round(Date.now() / 1000),\n\t\t\t\tdata: self.originPackets.get()\n\t\t\t}\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.RSSIGet = function(url, request) {\n\t\tvar headers = {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody = {\n\t\t\t\t\"code\": 200,\n\t\t\t\t\"message\": \"200 OK\",\n\t\t\t\t\"updateTime\": Math.round(Date.now() / 1000),\n\t\t\t\t\"data\": []\n\t\t\t};\n\n\t\ttry {\n\n\t\t\t//check if controller supports background rssi\n\t\t\tif (zway.controller.data.capabilities.value.indexOf(59) > -1) {\n\t\t\t\tvar par = url.split(\"/\")[1];\n\n\t\t\t\tif (par == \"realtime\") {\n\t\t\t\t\tself.updateRSSIData(null); // request new update to update the UI more often when user is on the page (page is polling this API).\n\t\t\t\t\tbody.data = self.lastRSSIData(); // get last know data\n\t\t\t\t} else {\n\t\t\t\t\tbody.data = self.loadObject('rssidata.json');\n\t\t\t\t}\n\n\t\t\t\tif (!!body.data) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\theaders: headers,\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: body\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tbody.code = 404;\n\t\t\t\t\tbody.message = '404 Not Found';\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\theaders: headers,\n\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\tbody: body\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tbody.code = 501;\n\t\t\t\tbody.message = 'Not implemented: This function is not supported by controller.';\n\n\t\t\t\treturn {\n\t\t\t\t\theaders: headers,\n\t\t\t\t\tstatus: 501,\n\t\t\t\t\tbody: body\n\t\t\t\t};\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\theaders: headers,\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Something went wrong:\" + e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.TestNode = function(url, request) {\n\t\ttry {\n\t\t\tvar nodeId = url.split(\"/\")[1],\n\t\t\t\tN = url.split(\"/\")[2] || 10;\n\n\t\t\tvar delivered = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n\t\t\t\tsent = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tfunction hasFinished() {\n\t\t\t\tif (sent.reduce(function(a, b) {\n\t\t\t\t\t\treturn a + b;\n\t\t\t\t\t}, 0) == 10 * N) {\n\t\t\t\t\tresult = \"done\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var powerlevel = 0; powerlevel < 10; powerlevel++) {\n\t\t\t\t(function(pwrlvl) {\n\t\t\t\t\tvar succesCbk = function() {\n\t\t\t\t\t\tsent[pwrlvl]++;\n\t\t\t\t\t\tdelivered[pwrlvl]++;\n\t\t\t\t\t\thasFinished();\n\t\t\t\t\t};\n\t\t\t\t\tvar failCbk = function() {\n\t\t\t\t\t\tsent[pwrlvl]++;\n\t\t\t\t\t\thasFinished();\n\t\t\t\t\t};\n\n\t\t\t\t\tfor (var n = 0; n < N; n++) {\n\t\t\t\t\t\tzway.SendTestFrame(nodeId, pwrlvl, succesCbk, failCbk);\n\t\t\t\t\t}\n\t\t\t\t})(powerlevel)\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 10 * N * 1000; // wait not more than 10*N seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tthrow (\"Timeout\");\n\t\t\t}\n\n\t\t\treturn delivered.map(function(val, index) {\n\t\t\t\treturn 100 * val / sent[index];\n\t\t\t});\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.FirmwareUpdate = function(url, request) {\n\t\ttry {\n\t\t\tvar deviceId = parseInt(url.substring(1), 10);\n\t\t\tif (!deviceId) {\n\t\t\t\tthrow \"Invalid device id\";\n\t\t\t}\n\n\t\t\tvar fwUpdate = zway.devices[deviceId].FirmwareUpdate;\n\t\t\tif (!fwUpdate) {\n\t\t\t\tthrow \"Device doesn't support FW Update\";\n\t\t\t}\n\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar manufacturerId = fwUpdate.data.manufacturerId.value;\n\t\t\tvar targetId = parseInt(data.targetId);\n\t\t\tvar firmwareId = targetId == 0 ? fwUpdate.data.firmwareId.value : fwUpdate.data[\"firmwareId\" + targetId].value;\n\t\t\t\n\t\t\tif (!manufacturerId && manufacturerId !== 0 || !firmwareId && firmwareId !== 0) {\n\t\t\t\tthrow \"Either manufacturer or firmware id is not present\";\n\t\t\t}\n\n\t\t\tif (targetId === 0 && !fwUpdate.data.upgradeable.value) {\n\t\t\t\tthrow \"Firmware is not upgradeable\";\n\t\t\t}\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\t// update firmware from file\n\t\t\t\tvar fw;\n\t\t\t\tif (data.file.content.substr(0, 1) === \":\") {\n\t\t\t\t\t// this is a .hex file\n\t\t\t\t\tfw = IntelHex2bin(data.file.content);\n\t\t\t\t} else {\n\t\t\t\t\tfw = data.file.content;\n\t\t\t\t}\n\t\t\t\tfwUpdate.Perform(manufacturerId, firmwareId, targetId, fw);\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: \"Initiating update\"\n\t\t\t\t};\n\t\t\t} else if (data.url) {\n\t\t\t\tvar result = {\n\t\t\t\t\tstatus: 'in progress'\n\t\t\t\t};\n\t\t\t\tvar d = Date.now() + 300000; // wait no more than 5 min\n\t\t\t\t// update firmware from url\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tcontentType: \"application/octet-stream\", // enforce binary response,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tsuccess: function(res) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar data = new Uint8Array(res.data);\n\t\t\t\t\t\t\tvar data_str = \"\";\n\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\tdata_str += String.fromCharCode(data[i]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar fw;\n\t\t\t\t\t\t\tif (data_str.substr(0, 1) === \":\") {\n\t\t\t\t\t\t\t\t// this is a .hex file\n\t\t\t\t\t\t\t\tfw = IntelHex2bin(data_str);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfw = data_str;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfwUpdate.Perform(manufacturerId, firmwareId, targetId, fw);\n\n\t\t\t\t\t\t\tresult.status = 'done';\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tresult.error = 'Firmware download successful. Parsing has failed: ' + e.toString();\n\t\t\t\t\t\t\tresult.status = 'fail';\n\t\t\t\t\t\t\tthrow ('Firmware download successful. Parsing has failed: ' + e.toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tresult.error = 'Failed to download firmware: ' + res.statusText;\n\t\t\t\t\t\tresult.status = 'fail';\n\t\t\t\t\t\tthrow ('Failed to download firmware: ' + res.statusText);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\twhile (Date.now() < d && result.status === \"in progress\") {\n\t\t\t\t\tprocessPendingCallbacks();\n\t\t\t\t}\n\n\t\t\t\tresult.status = result.status === 'in progress' ? 'fail' : result.status;\n\n\t\t\t\tif (result.status === 'fail') {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tbody: result.error\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: \"Initiating update\"\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.ZMELicense = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data || !data.license) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\t\t\t\n\t\t\tvar func, lic;\n\t\t\tif (parseFloat(zway.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\tfunc = zway.ZMELicenseSet;\n\t\t\t\tlic = data.license.match(/.{2}/g).map(function(i, v) { return parseInt(i, 16); });\n\t\t\t} else {\n\t\t\t\tfunc = zway.ZMECapabilities;\n\t\t\t\tlic = data.license.split(\",\").map(function(i) { return parseInt(i, 10); });\n\t\t\t}\n\t\t\t\n\t\t\tfunc.call(zway, lic, function() {\n\t\t\t\tresult = \"done\";\n\t\t\t}, function() {\n\t\t\t\tresult = \"failed\";\n\t\t\t});\n\n\t\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.ZMEFirmwareUpgrade = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tif (zway.controller.data.SDK.value === null) {\n\t\t\t\tconsole.log(\"Unknown SDK version - update Z-Way\");\n\t\t\t\tthrow \"Unknown SDK version - update Z-Way\";\n\t\t\t}\n\n\t\t\tvar L = 32,\n\t\t\t    addr,\n\t\t\t    skip1800;\n\n\t\t\tif (parseFloat(zway.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t// ZGM130S/ZG14\n\t\t\t\tskip1800 = false;\n\t\t\t\taddr = 0x3A000;\n\t\t\t} else {\n\t\t\t\t// ZM5101/SD3503/ZM5202\n\t\t\t\tif (zway.controller.data.manufacturerId.value === 0) { // Z-Wave.Me Hub\n\t\t\t\t\tskip1800 = true;\n\t\t\t\t\taddr =  0x7800; // M25PE10\n\t\t\t\t} else {\n\t\t\t\t\tskip1800 =\n\t\t\t\t\t\tzway.controller.data.bootloader.crc.value !== 0x8aaa // bootloader for RaZberry 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzway.controller.data.bootloader.crc.value !== 0x7278 // bootloader for UZB 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzway.controller.data.bootloader.crc.value !== 0x9d04 // bootloader for UZB 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzway.controller.data.bootloader.crc.value !== 0x8b4b // bootloader for Z-Box 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tparseFloat(zway.controller.data.SDK.value.substr(0, 4)) < 6.71; // bootloader for 6.71 SDK\n\t\t\t\t\taddr = skip1800 ? 0x7800: 0x20000; // M25PE40 on old and new SDKs\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\tconsole.log(\"Fetching firmware from file \" + data.file.name);\n\n\t\t\t\tvar buf = new ArrayBuffer(data.file.content.length);\n\t\t\t\tvar bufView = new Uint8Array(buf);\n\t\t\t\tfor (var i = 0; i < data.file.content.length; i++) {\n\t\t\t\t\tbufView[i] = data.file.content.charCodeAt(i);\n\t\t\t\t}\n\n\t\t\t\tvar data = skip1800 ? buf.slice(0x1800) : buf;\n\n\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t}\n\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t}\n\n\t\t\t\tzway.NVMExtWriteLongBuffer(addr - 2, [0, 1], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tzway.SerialAPISoftReset(function() {\n\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\tzway.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t} else if (data.url) {\n\t\t\t\tconsole.log(\"Fetching firmware from \" + data.url);\n\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcontentType: \"application/octet-stream\",\n\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\tvar data = skip1800 ? response.data.slice(0x1800) : response.data;\n\n\t\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr - 2, [0, 1], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\tzway.SerialAPISoftReset(function() {\n\t\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\t\tzway.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tconsole.error(\"Failed to download firmware: \" + res.statusText);\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Wrong request. Failed to apply firmware.\");\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 300 * 1000; // wait not more than 5 minutes\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.ZMEBootloaderUpgrade = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\tconsole.log(\"Fetching bootloader from file \" + data.file.name);\n\t\t\t\t\n\t\t\t\tvar buf = new ArrayBuffer(data.file.content.length);\n\t\t\t\tvar bufView = new Uint8Array(buf);\n\t\t\t\tfor (var i = 0; i < data.file.content.length; i++) {\n\t\t\t\t\tbufView[i] = data.file.content.charCodeAt(i);\n\t\t\t\t}\n\t\t\t\tvar data = buf;\n\n\t\t\t\tif (parseFloat(zway.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t\tvar arr = (new Uint8Array(data.slice(0, 30)));\n\t\t\t\t\tzway.ZMEBootloaderLoadFlash(data.slice(0, 5), function() {\n\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\tzway.stop(); // to force re-start Z-Way\n\t\t\t\t\t}, function() {\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar L = 32,\n\t\t\t\t\t\tseg = 6, // Функция бутлодера принимает номер сегмента\n\t\t\t\t\t\taddr = seg * 0x800; // ==12k\n\n\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t}\n\t\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t}\n\n\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr - 2, [0, 0], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t//Вызываем перезапись bootloder\n\t\t\t\t\t\t\tzway.ZMEBootloaderFlash(seg, function() {\n\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\tzway.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (data.url) {\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcontentType: \"application/octet-stream\",\n\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\tif (parseFloat(zway.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t\t\t\tzway.ZMEBootloaderLoadFlash(data, function() {\n\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\tzway.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar L = 32,\n\t\t\t\t\t\t\t\tseg = 6, // Функция бутлодера принимает номер сегмента\n\t\t\t\t\t\t\t\taddr = seg * 0x800, // ==12k\n\t\t\t\t\t\t\t\tdata = response.data;\n\n\t\t\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tzway.NVMExtWriteLongBuffer(addr - 2, [0, 0], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t//Вызываем перезапись bootloder\n\t\t\t\t\t\t\t\t\tzway.ZMEBootloaderFlash(seg, function() {\n\t\t\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\t\t\tzway.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tconsole.error(\"Failed to download bootloader: \" + res.statusText);\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Wrong request. Failed to apply bootloader.\");\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 60 * 1000; // wait not more than 60 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.Postfix = function(url, request) {\n\n\t\tvar show = request.query ? request.query : null;\n\n\t\tif (!!self.postfix) {\n\n\t\t\tpfix = self.postfix;\n\n\t\t\tif (show === 'false') {\n\t\t\t\tpfix = self.postfix.fixes ? self.postfix.fixes : self.postfix;\n\n\t\t\t\tpfix = pfix.map(function(fix) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tp_id: fix.p_id,\n\t\t\t\t\t\tproduct: fix.product\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: pfix\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: 'Cannot load postfix.'\n\t\t\t};\n\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.PostfixUpdate = function(url, request) {\n\t\tvar success,\n\t\t\tdelay = Date.now() + 10000; // wait not more than 10 seconds\n\n\t\t// update postfix JSON\n\t\thttp.request({\n\t\t\turl: \"https://manuals.zwave.eu/backend/make.php?mode=ui_postfix\",\n\t\t\tasync: true,\n\t\t\tsuccess: function(res) {\n\t\t\t\tif (res.data) {\n\n\t\t\t\t\trd = JSON.parse(res.data);\n\n\t\t\t\t\tif (rd.fixes && rd.fixes.length > 0 && rd.last_update && rd.last_update > postfix.last_update) {\n\t\t\t\t\t\tsaveObject('postfix.json', rd, true);\n\t\t\t\t\t\tsuccess = 1;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsuccess = 2;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log('Error has occured during updating the fixes list');\n\t\t\t\t\tsuccess = 0;\n\t\t\t\t}\n\t\t\t},\n\t\t\terror: function() {\n\t\t\t\tconsole.log('Error has occured during updating the fixes list');\n\t\t\t\tsuccess = 0;\n\t\t\t}\n\t\t});\n\n\t\twhile (!success && Date.now() < delay) {\n\t\t\tprocessPendingCallbacks();\n\t\t}\n\n\t\tswitch (success) {\n\t\t\tcase 1:\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tinstanceObj = _.filter(self.controller.instances, function(instance){\n\t\t\t\t\t\treturn instance.id === self.id;\n\t\t\t\t\t})[0];\n\n\t\t\t\t\tself.controller.reconfigureInstance(self.id, instanceObj);\n\t\t\t\t\t//self.controller.reinitializeModule('ZWave', 'modules/');\n\t\t\t\t}, 3000);\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: 'ZWave will be reinitialized in 3, 2, 1 ... \\nReload the page after 15-20 sec to check if fixes are up to date.'\n\t\t\t\t};\n\t\t\tcase 2:\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: 'List of fixes is already up to date ... '\n\t\t\t\t};\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 500,\n\t\t\t\t\tbody: 'Something went wrong ... '\n\t\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.PostfixGet = function(url) {\n\t\tvar p_id = url.substring(1),\n\t\t\tfixes = postfix.fixes,\n\t\t\tfix = fixes.filter(function(fix) {\n\t\t\t\treturn fix.p_id === p_id;\n\t\t\t});\n\n\t\tif (!_.isEmpty(fix)) {\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: fix[0]\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\tstatus: 404,\n\t\t\t\tbody: \"Postfix with p_id: \" + p_id + \" not found\"\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZWaveAPI.PostfixAdd = function(url, request) {\n\n\t\tif (request.method === \"POST\" && request.body) {\n\n\t\t\ttry {\n\t\t\t\tvar reqObj = parseToObject(request.body);\n\t\t\t} catch (e) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 400,\n\t\t\t\t\tbody: e.toString()\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tvar custom_postfix = loadObject(\"custompostfix.json\");\n\n\t\t\tif (custom_postfix === null) {\n\n\t\t\t\treqObj.id = 1;\n\n\t\t\t\tcustom_postfix = {\n\t\t\t\t\t\"last_update\": Math.floor(Date.now() / 1000),\n\t\t\t\t\t\"fixes\": [reqObj]\n\t\t\t\t};\n\n\t\t\t} else {\n\n\t\t\t\tvar fixes = custom_postfix.fixes,\n\t\t\t\t\tfix = fixes.filter(function(fix) {\n\t\t\t\t\t\treturn fix.p_id === reqObj.p_id;\n\t\t\t\t\t});\n\n\t\t\t\tif (_.isEmpty(fix)) {\n\t\t\t\t\tvar id = Math.max.apply(Math, custom_postfix.fixes.map(function(fix) {\n\t\t\t\t\t\treturn fix.id;\n\t\t\t\t\t}));\n\t\t\t\t\treqObj.id = id + 1;\n\n\t\t\t\t\tcustom_postfix.fixes.push(reqObj);\n\n\t\t\t\t} else {\n\n\t\t\t\t\tvar tempFixes = fixes;\n\n\t\t\t\t\tfor (var p in tempFixes) {\n\t\t\t\t\t\tif (tempFixes[p].p_id === reqObj.p_id) {\n\t\t\t\t\t\t\ttempFixes[p] = _.assign(tempFixes[p], reqObj);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcustom_postfix.fixes = tempFixes;\n\t\t\t\t}\n\n\t\t\t\tcustom_postfix.last_update = Math.floor(Date.now() / 1000);\n\n\t\t\t}\n\n\t\t\tsaveObject(\"custompostfix.json\", custom_postfix, true);\n\n\t\t\tsetTimeout(function() {\n\t\t\t\tinstanceObj = _.filter(self.controller.instances, function(instance){\n\t\t\t\t\treturn instance.id === self.id;\n\t\t\t\t})[0];\n\n\t\t\t\tself.controller.reconfigureInstance(self.id, instanceObj);\n\t\t\t\t//self.controller.reinitializeModule('ZWave', 'modules/');\n\t\t\t}, 3000);\n\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: 'ZWave will be reinitialized in 3, 2, 1 ... \\nReload the page after 15-20 sec to check if fixes are up to date.'\n\t\t\t};\n\n\t\t}\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid request\"\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.PostfixRemove = function(url, request) {\n\t\tif (request.method === \"POST\" && request.body) {\n\t\t\tvar custom_postfix = loadObject(\"custompostfix.json\"),\n\t\t\t\treqObj = parseToObject(request.body);\n\n\t\t\tif (!!custom_postfix) {\n\n\t\t\t\tvar fixes = custom_postfix.fixes,\n\t\t\t\t\tfix = fixes.filter(function(fix) {\n\t\t\t\t\t\treturn fix.p_id === reqObj.p_id;\n\t\t\t\t\t});\n\n\t\t\t\tif (!_.isEmpty(fix)) {\n\t\t\t\t\tfixes = _.reject(fixes, function(fix) {\n\t\t\t\t\t\treturn fix.p_id === reqObj.p_id;\n\t\t\t\t\t});\n\n\t\t\t\t\tcustom_postfix.fixes = fixes;\n\n\t\t\t\t\tsaveObject(\"custompostfix.json\", custom_postfix, true);\n\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tinstanceObj = _.filter(self.controller.instances, function(instance){\n\t\t\t\t\t\t\treturn instance.id === self.id;\n\t\t\t\t\t\t})[0];\n\n\t\t\t\t\t\tself.controller.reconfigureInstance(self.id, instanceObj);\n\t\t\t\t\t\t//self.controller.reinitializeModule('ZWave', 'modules/');\n\t\t\t\t\t}, 3000);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: 'Postfix with p_id: ' + reqObj.p_id + ' removed.\\nZWave will be reinitialized in 3, 2, 1 ... \\nReload the page after 15-20 sec to check if fixes are up to date.'\n\t\t\t\t\t};\n\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\tbody: 'Postfix with p_id: ' + reqObj.p_id + ' not found or already deleted'\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 404,\n\t\t\t\t\tbody: 'Custompostfix does not yet exist'\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid request\"\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.ExpertConfigGet = function() {\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: self.expert_config\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.ExpertConfigUpdate = function(url, request) {\n\t\tvar reqObj = {};\n\n\t\tif (request.method === \"POST\" && request.body) {\n\t\t\treqObj = parseToObject(request.body);\n\n\t\t\tif (Object.keys(reqObj).length > 0) {\n\n\t\t\t\tself.expert_config = _.assign(self.expert_config, _.pick(reqObj,\n\t\t\t\t\t'debug',\n\t\t\t\t\t'network_name',\n\t\t\t\t\t'date_format',\n\t\t\t\t\t'time_format',\n\t\t\t\t\t'time_zone',\n\t\t\t\t\t'notes',\n\t\t\t\t\t'ssid_name',\n\t\t\t\t\t'currentDateTime',\n\t\t\t\t\t'rss',\n\t\t\t\t\t'node_positions',\n\t\t\t\t\t'routemap_img'\n\t\t\t\t));\n\n\t\t\t\tself.saveObject('expertconfig.json', self.expert_config, true);\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: \"Done\"\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid request\"\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.CallForAllNIF = function(url, request) {\n\t\tvar req = request && request.body ? request.body : request && request.data ? request.data : undefined,\n\t\t\treq = parseToObject(req),\n\t\t\tdelay = req && req.delay ? req.delay : null,\n\t\t\ttimeout = !!delay ? parseInt(delay.toString(), 10) * 1000 : 10000,\n\t\t\ttimer = null,\n\t\t\tnow = Date.now();\n\n\t\ttry {\n\t\t\tvar devices = Object.keys(zway.devices);\n\t\t\tvar ret = {\n\t\t\t\tresult: [],\n\t\t\t\truntime: 0\n\t\t\t};\n\t\t\tvar dTS = '';\n\n\t\t\tif (devices.length > 0) {\n\n\t\t\t\t// do not send NIF to itself\n\t\t\t\tdevices.forEach(function(nodeId) {\n\t\t\t\t\tvar request = \"in progress\",\n\t\t\t\t\t\tentry = {\n\t\t\t\t\t\t\tnodeId: nodeId,\n\t\t\t\t\t\t\tresult: \"\",\n\t\t\t\t\t\t\truntime: 0,\n\t\t\t\t\t\t\tisFLiRS: false,\n\t\t\t\t\t\t\thasBattery: false\n\t\t\t\t\t\t},\n\t\t\t\t\t\tstart = Date.now(),\n\t\t\t\t\t\tpendingDelay = start + timeout;\n\n\t\t\t\t\tif (zway.devices[nodeId] && nodeId != zway.controller.data.nodeId.value) {\n\n\t\t\t\t\t\tvar isListening = zway.devices[nodeId].data.isListening.value;\n\t\t\t\t\t\tvar isFLiRS = !isListening && (zway.devices[nodeId].data.sensor250.value || zway.devices[nodeId].data.sensor1000.value);\n\t\t\t\t\t\tvar hasWakeup = 0x84 in zway.devices[nodeId].instances[0].commandClasses;\n\n\t\t\t\t\t\tconsole.log('Send NIF to node #' + nodeId + ' ...');\n\t\t\t\t\t\tzway.RequestNodeInformation(\n\t\t\t\t\t\t\tnodeId,\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\trequest = \"done\";\n\t\t\t\t\t\t\t\tentry.result = request;\n\t\t\t\t\t\t\t\tentry.runtime = (Date.now() - start) / 1000;\n\t\t\t\t\t\t\t\tentry.isFLiRS = isFLiRS;\n\t\t\t\t\t\t\t\tentry.hasBattery = hasWakeup;\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\trequest = \"failed\";\n\t\t\t\t\t\t\t\tentry.result = request;\n\t\t\t\t\t\t\t\tentry.runtime = (Date.now() - start) / 1000;\n\t\t\t\t\t\t\t\tentry.isFLiRS = isFLiRS;\n\t\t\t\t\t\t\t\tentry.hasBattery = hasWakeup;\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\twhile (request === \"in progress\" && Date.now() < pendingDelay && !isFLiRS) {\n\t\t\t\t\t\t\tprocessPendingCallbacks();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (request === \"in progress\") {\n\t\t\t\t\t\t\tentry.result = hasWakeup ? \"waiting for wakeup\" : \"failed\";\n\t\t\t\t\t\t\tentry.runtime = (Date.now() - start) / 1000;\n\t\t\t\t\t\t\tentry.isFLiRS = isFLiRS;\n\t\t\t\t\t\t\tentry.hasBattery = hasWakeup;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tret.result.push(entry);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tret.runtime = Math.floor((Date.now() - now) / 1000);\n\t\t\tret.updateTime = Math.floor((Date.now()) / 1000);\n\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: ret\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t}\n\t\t}\n\n\t\treturn reply;\n\n\t};\n\n\tthis.ZWaveAPI.CheckAllLinks = function(url, request) {\n\t\tvar req = request && request.body ? request.body : request && request.data ? request.data : undefined,\n\t\t\treq = parseToObject(req),\n\t\t\tdelay = req && req.delay ? req.delay : null,\n\t\t\ttimeout = !!delay && parseInt(delay.toString(), 10) >= 1 ? parseInt(delay.toString(), 10) * 1000 : 2000,\n\t\t\ttimer = null,\n\t\t\tnodeId = req && req.nodeId ? req.nodeId : null;\n\n\t\ttry {\n\t\t\tif (!!nodeId && zway.devices[nodeId] && nodeId != zway.controller.data.nodeId.value) { // do not test against itself\n\t\t\t\tvar neighbours = zway.devices[nodeId].data.neighbours.value;\n\t\t\t\tvar supported = zway.devices[nodeId].instances[0].commandClasses[115] ? true : false;\n\t\t\t\tvar ret = {\n\t\t\t\t\truntime: neighbours.length * (timeout / 1000),\n\t\t\t\t\tlink_test: 'TestNodeSet',\n\t\t\t\t\tsrcNodeId: nodeId,\n\t\t\t\t\tdstNodeIds: neighbours,\n\t\t\t\t\ttest: []\n\t\t\t\t};\n\t\t\t\tif (supported) {\n\t\t\t\t\tneighbours.forEach(function(neighbour) {\n\t\t\t\t\t\tvar start = Date.now();\n\t\t\t\t\t\tvar item = {};\n\t\t\t\t\t\tvar powerLvl = zway.devices[nodeId].instances[0].commandClasses[115];\n\n\t\t\t\t\t\tconsole.log('# Send TestNodeSet from #' + nodeId + ' to #' + neighbour);\n\t\t\t\t\t\tpowerLvl.TestNodeSet(neighbour, 6, 20);\n\n\t\t\t\t\t\t// wait 2 sec or more\n\t\t\t\t\t\twhile (Date.now() < (start + timeout)) {\n\t\t\t\t\t\t\tprocessPendingCallbacks();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (powerLvl.data[neighbour]) {\n\t\t\t\t\t\t\titem[neighbour] = {\n\t\t\t\t\t\t\t\ttotalFrames: powerLvl.data[neighbour].totalFrames.value,\n\t\t\t\t\t\t\t\tacknowledgedFrames: powerLvl.data[neighbour].acknowledgedFrames.value\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tret.test.push(item);\n\n\t\t\t\t\t});\n\n\t\t\t\t\tret.updateTime = Math.floor((Date.now()) / 1000);\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: ret\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 404,\n\t\t\t\t\t\tbody: 'Not supported for this device.'\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 404,\n\t\t\t\t\tbody: 'Node not found.'\n\t\t\t\t};\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\n\t\treturn reply;\n\t};\n\n\tthis.ZWaveAPI.NetworkReorganization = function(url, request) {\n\t\tvar reply = {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: null\n\t\t\t};\n\t\t\n\t\tself.networkReorganization.start();\n\n\t\treply.body = {\n\t\t\tdata: self.networkReorganization.getLog()\n\t\t};\n\n\t\treturn reply;\n\t};\n\n\tthis.ZWaveAPI.GetReorganizationLog = function(url, request) {\n\t\tvar reply = {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: null\n\t\t\t};\n\n\t\treply.body = {\n\t\t\tdata: self.networkReorganization.getLog()\n\t\t};\n\n\t\treturn reply;\n\t}\n\n\tthis.ZWaveAPI.GetStatisticsData = function() {\n\t\tself.updateNetStats();\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: statistics\n\t\t};\n\t};\n\n\tthis.ZWaveAPI.ClearStatisticsData = function() {\n\t\tself.clearNetStats();\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: statistics\n\t\t};\n\t};\n\n\t/*\n\t * show DSK z-way provisioning list\n\t */\n\tthis.ZWaveAPI.GetDSKProvisioningList = function(url, request) {\n\t\tvar reply = {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: null,\n\t\t\terror: null,\n\t\t\tmessage: null\n\t\t};\n\n\t\ttry {\n\t\t\treply.body = self.getDSKProvisioningList();\n\t\t} catch (e) {\n\t\t\t_.extend(reply, {\n\t\t\t\tstatus: 500,\n\t\t\t\terror: 'Something went wrong. ERROR: ' + e.toString()\n\t\t\t});\n\t\t}\n\n\t\treturn reply;\n\t};\n\n\t/*\n\t * add DSK to z-way provisioning list\n\t */\n\tthis.ZWaveAPI.AddDSKProvisioningEntry = function(url, request) {\n\t\t// prepare request data\n\t\tvar req = request && request.body ? parseToObject(request.body) : (request && request.data ? parseToObject(request.data) : undefined),\n\t\t\treply = {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: null,\n\t\t\t\terror: null,\n\t\t\t\tmessage: null\n\t\t\t}\n\n\t\ttry {\n\t\t\t// get dskProvisioningList\n\t\t\tdskProvisioningList = self.getDSKProvisioningList();\n\t\t\t// add DSK\n\t\t\tif (dskProvisioningList.indexOf(req.dsk) < 0) {\n\t\t\t\tdskProvisioningList.push(req.dsk);\n\n\t\t\t\t// save dskProvisioningList\n\t\t\t\tself.saveDSKProvisioningList(dskProvisioningList);\n\n\t\t\t\treply.body = [req.dsk];\n\t\t\t} else {\n\t\t\t\treply.status = 409;\n\t\t\t\treply.message = 'Conflict - DSK entry already exists';\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.status = 500;\n\t\t\treply.message = 'Something went wrong. ERROR: ' + e.toString();\n\t\t}\n\n\t\treturn reply;\n\t};\n\n\t/*\n\t * show all prepared QR code DSK entries or one specific by it's id\n\t * this.dskCollection list is used\n\t */\n\tthis.ZWaveAPI.GetDSKCollection = function(url, request) {\n\t\tfunction setIncluded(DSKCollection) {\n\t\t\tvar changed = false;\n\t\t\t_.forEach(zway.devices, function (device) {\n\t\t\t\tif (device && device.instances && device.instances[0] && device.instances[0].commandClasses['159']) {\n\t\t\t\t\tvar publicKeyVerified = device.instances[0].commandClasses['159'].publicKeyVerified && device.instances[0].commandClasses['159'].publicKeyVerified.value;\n\t\t\t\t\tif (publicKeyVerified) {\n\t\t\t\t\t\tvar dsk = transformPublicKeyToDSK(publicKeyVerified);\n\t\t\t\t\t\tvar dskEntry = DSKCollection.find(function (item) {\n\t\t\t\t\t\t\treturn item.DSK === dsk;\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (dskEntry && dskEntry.state !== 'included') {\n\t\t\t\t\t\t\tdskEntry.state = 'included';\n\t\t\t\t\t\t\tchanged = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tif (changed) {\n\t\t\t\tself.saveObject(\"dskCollection\", DSKCollection, true);\n\t\t\t}\n\t\t}\n\n\t\tvar req = request && request.query ? parseToObject(request.query) : undefined,\n\t\t\tid = req && req.id ? req.id : false;\n\t\tvar DSKCollection = self.getDSKCollection(id);\n\t\tif (id === false) {\n\t\t\tsetIncluded(DSKCollection);\n\t\t}\n\n\t\tvar reply = {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: DSKCollection,\n\t\t\terror: null,\n\t\t\tmessage: null\n\t\t};\n\n\t\treturn reply;\n\t};\n\n\t/*\n\t * remove all or one specific by it's id prepared QR code DSK entries\n\t * this.dskCollection list is used\n\t * this will also remove DSK entries from z-way provisioning list\n\t */\n\tthis.ZWaveAPI.RemoveDSKEntry = function(url, request) {\n\t\t// prepare request data\n\t\tvar req = request && request.query ? parseToObject(request.query) : undefined,\n\t\t\tsuccess = false,\n\t\t\treply = {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: null,\n\t\t\t\terror: null,\n\t\t\t\tmessage: null\n\t\t\t}\n\n\t\ttry {\n\t\t\tif (req['all'] === 'true' || req['all'] === true) {\n\n\t\t\t\t// remove all DSK entry\n\t\t\t\tself.dskCollection = []\n\n\t\t\t\t// save dskProvisioningList\n\t\t\t\tself.saveDSKProvisioningList([]);\n\n\t\t\t\t// save dsk collection\n\t\t\t\tself.saveObject(\"dskCollection\", self.dskCollection, true);\n\n\t\t\t\tsuccess = true;\n\t\t\t} else {\n\t\t\t\tsuccess = self.removeDSKEntry(parseInt(req.id, 10));\n\t\t\t}\n\n\t\t\tif (success) {\n\t\t\t\treply.body = req['all'] ? self.dskCollection : req.id;\n\t\t\t} else {\n\t\t\t\treply.status = 404;\n\t\t\t\treply.message = 'Not found - DSK entry does not exist';\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.status = 500;\n\t\t\treply.message = 'Something went wrong. ERROR: ' + e.toString();\n\t\t}\n\n\t\treturn reply;\n\t};\n\n\t/*\n\t * add S2 or Smart Start QR code DSK entries\n\t * this.dskCollection list is used\n\t * this will also add DSK entries to z-way provisioning list\n\t */\n\tthis.ZWaveAPI.AddDSKEntry = function(url, request) {\n\t\t// prepare request data\n\t\tvar req = request && request.body ? parseToObject(request.body) : (request && request.data ? parseToObject(request.data) : undefined),\n\t\t\treply = {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: null,\n\t\t\t\terror: null,\n\t\t\t\tmessage: null\n\t\t\t},\n\t\t\tsuccess = false;\n\n\t\t/*try {*/\n\t\t\tsuccess = self.addDSKEntry(req.dsk);\n\n\t\t\tswitch (success) {\n\t\t\t\tcase 200:\n\t\t\t\t\treply.body = typeof req.dsk === 'string' ? { dsk: req.dsk } : req.dsk;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 500:\n\t\t\t\t\treply.status = 500;\n\t\t\t\t\treply.message = 'Something went wrong. Cannot add DSK entry.';\n\t\t\t\t\tbreak;\n\t\t\t\tcase 409:\n\t\t\t\t\treply.status = 409;\n\t\t\t\t\treply.message = 'Conflict - DSK entry already exists';\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t/*if (_.findIndex(self.dskCollection, function(qrObject) {\n\t\t\t\t\treturn qrObject.ZW_QR === req.dsk;\n\t\t\t\t}) < 0) {\n\t\t\t\tsuccess = self.addDSKEntry(req.dsk);\n\t\t\t\tif (success) {\n\t\t\t\t\treply.body = typeof req.dsk === 'string' ? {\n\t\t\t\t\t\tdsk: req.dsk\n\t\t\t\t\t} : req.dsk;\n\t\t\t\t} else {\n\t\t\t\t\treply.status = 404;\n\t\t\t\t\treply.message = 'Cannot add DSK entry';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.status = 409;\n\t\t\t\treply.message = 'Conflict - DSK entry already exists';\n\t\t\t}*/\n\n\t\t/*} catch (e) {\n\t\t\treply.status = 500;\n\t\t\treply.message = 'Something went wrong. ERROR: ' + e.toString();\n\t\t}\n*/\n\t\treturn reply;\n\t};\n\n\t/*\n\t * update S2 or Smart Start QR code DSK entries\n\t * this.dskCollection list is used\n\t * this will also change DSK entries within z-way provisioning list\n\t */\n\tthis.ZWaveAPI.UpdateDSKEntry = function(url, request) {\n\t\t// prepare request data\n\t\tvar req = request && request.body ? parseToObject(request.body) : (request && request.data ? parseToObject(request.data) : undefined),\n\t\t\treply = {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: null,\n\t\t\t\terror: null,\n\t\t\t\tmessage: null\n\t\t\t}\n\n\t\ttry {\n\t\t\tif (_.findIndex(self.dskCollection, function(qrObject) {\n\t\t\t\t\treturn qrObject.id === req.id;\n\t\t\t\t}) > -1) {\n\t\t\t\tvar success = self.updateDSKEntry(req);\n\n\t\t\t\tif (success) {\n\t\t\t\t\treply.body = req;\n\t\t\t\t} else {\n\t\t\t\t\treply.status = 500;\n\t\t\t\t\treply.message = 'Something went wrong.';\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treply.status = 404;\n\t\t\t\treply.message = 'Not found - DSK entry does not exist';\n\t\t\t}\n\t\t} catch (e) {\n\t\t\treply.status = 500;\n\t\t\treply.message = 'Something went wrong. ERROR: ' + e.toString();\n\t\t}\n\n\t\treturn reply;\n\t};\n\n\tthis.ZWaveAPI.EncryptionKeys = function () {\n\t\tvar filename = ('00000000' + (zway.controller.data.homeId.value + (zway.controller.data.homeId.value < 0 ? 0x100000000 : 0)).toString(16)).slice(-8)\n\t\tvar reply = {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/plain\", // application/x-download octet-stream\n\t\t\t\t\"Content-Disposition\": \"attachment; filename=\" + filename.toUpperCase() + \".txt\",\n\t\t\t},\n\t\t\tbody: null,\n\t\t\terror: null,\n\t\t\tmessage: null\n\t\t};\n\t\tvar networkKeys = [zway.devices[zway.controller.data.nodeId.value].data.networkKey.value];\n\t\tvar keys = zway.devices[zway.controller.data.nodeId.value].data.networkKeys;\n\t\tif (keys) {\n\t\t\tnetworkKeys.push(keys.S2Unauthenticated.value, keys.S2Authenticated.value, keys.S2Access.value);\n\t\t}\n\t\tif (keys.S2AuthenticatedLR) {\n\t\t\tnetworkKeys.push(keys.S2AuthenticatedLR.value, keys.S2AccessLR.value)\n\t\t}\n\n\t\treply.body = networkKeys.map(function (key, index) {\n\t\t\treturn (index ? '9F' : '98') + ';' + (key ? key : new Array(16).fill(0))\n\t\t\t\t.map(function (e) {return (+e).toString(16).padStart(2, '0').toUpperCase()}).join('') + ';1';\n\t\t}).join('\\r\\n');\n\n\t\treturn reply;\n\t}\n\t/*\n\t// -- not used -- //\n\tthis.ZWaveAPI.JSONtoXML = function(url, request) {\n\t\tfunction hexByteToStr(n) {\n\t\t\treturn (\"00\" + parseInt(n).toString(16)).slice(-2);\n\t\t}\n\n\t\tfunction hexWordToStr(n) {\n\t\t\treturn (\"0000\" + parseInt(n).toString(16)).slice(-4);\n\t\t}\n\n\t\tfunction nic(name, id) {\n\t\t\treturn {\n\t\t\t\t\"name\": name,\n\t\t\t\t\"attributes\": {\n\t\t\t\t\t\"id\": id,\n\t\t\t\t},\n\t\t\t\t\"children\": []\n\t\t\t};\n\t\t}\n\n\t\tfunction tagDH(name, invalidateTime, updateTime, type, value) {\n\t\t\tswitch (type) {\n\t\t\t\tcase \"int[]\":\n\t\t\t\tcase \"float[]\":\n\t\t\t\tcase \"binary\":\n\t\t\t\t\tvalue = \"[\" + value.toString() + \"]\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"string[]\":\n\t\t\t\t\tvalue = \"[\" + value.map(function(el) { return \"&quot;\" + el + \"&quot;\"; }).toString() + \"]\"\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\t\"name\": \"data\",\n\t\t\t\t\"attributes\": {\n\t\t\t\t\t\"name\": name,\n\t\t\t\t\t\"invalidateTime\": invalidateTime,\n\t\t\t\t\t\"updateTime\": updateTime,\n\t\t\t\t\t\"type\": type,\n\t\t\t\t\t\"value\": value\n\t\t\t\t},\n\t\t\t\t\"children\": []\n\t\t\t};\n\t\t}\n\n\t\tfunction treeDH(name, data) {\n\t\t\tvar tag = tagDH(name, data.invalidateTime, data.updateTime, data.type, data.value);\n\t\t\tfor (var key in data) {\n\t\t\t\tif ([\"value\", \"type\", \"invalidateTime\", \"updateTime\"].indexOf(key) != -1)\n\t\t\t\t\tcontinue;\n\t\t\t\ttag.children.push(treeDH(key, data[key]));\n\t\t\t}\n\t\t\treturn tag;\n\t\t}\n\n\t\tz = fs.loadJSON(url.split(\"/\")[1]);\n\t\tvar x = new ZXmlDocument();\n\n\t\tx.root = {\n\t\t\t\"name\": \"devicesData\",\n\t\t\t\"children\": []\n\t\t};\n\n\t\tx.root.insertChild({\n\t\t\t\"name\": \"controller\",\n\t\t\t\"children\": []\n\t\t});\n\n\t\tx.root.insertChild(treeDH(\"controller.data\", z.controller.data));\n\n\t\tfor (var nodeId in z.devices) {\n\t\t\tvar device = nic(\"device\", nodeId);\n\t\t\tdevice.children.push(treeDH(\"devices.\" + nodeId + \".data\", z.devices[nodeId].data));\n\t\t\tfor (var instanceId in z.devices[nodeId].instances) {\n\t\t\t\tvar instance = nic(\"instance\", instanceId);\n\t\t\t\tinstance.children.push(treeDH(\"devices.\" + nodeId + \".insances.\" + instanceId + \".data\", z.devices[nodeId].instances[instanceId].data));\n\t\t\t\tfor (var ccId in z.devices[nodeId].instances[instanceId].commandClasses) {\n\t\t\t\t\tvar cc = nic(\"commandClass\", hexWordToStr(ccId));\n\t\t\t\t\tcc.children.push(treeDH(\"devices.\" + nodeId + \".insances.\" + instanceId + \".commandClasses.\" + ccId + \".data\", z.devices[nodeId].instances[instanceId].commandClasses[ccId].data));\n\t\t\t\t\tinstance.children.push(cc);\n\t\t\t\t}\n\t\t\t\tdevice.children.push(instance);\n\t\t\t}\n\t\t\tx.root.insertChild(device);\n\t\t}\n\n\t\treturn {\n\t\t\t\"status\": 200,\n\t\t\t\"body\": x.toString(),\n\t\t\t\"headers\": {\n\t\t\t\t\"Content-Type\": \"application/xml\"\n\t\t\t}\n\t\t};\n\t};\n\t*/\n};\n\n\n// ------------- Data Binding --------------\n\nZWave.prototype._dataBind = function(dataBindings, zwayName, nodeId, instanceId, commandClassId, path, func, type) {\n\tif (zwayName === this.config.name) {\n\t\tthis.dataBind(dataBindings, this.zway, nodeId, instanceId, commandClassId, path, func, type);\n\t}\n}\nZWave.prototype.dataBind = function(dataBindings, zway, nodeId, instanceId, commandClassId, path, func, type) {\n\t// three prototypes:\n\t//  (dataBindings, zway, nodeId, instanceId, commandClassId, path, func, type)\n\t//  (dataBindings, zway, nodeId,                             path, func)\n\t//  (dataBindings, zway,                                     path, func) // bind to controller data\n\n\tvar pathArr = [],\n\t\tdata = null,\n\t\tctrlBind = is_function(instanceId),\n\t\tdevBind = is_function(commandClassId);\n\n\tif (ctrlBind) {\n\t\tpath = nodeId;\n\t\tfunc = instanceId;\n\t\tnodeId = undefined;\n\t\tinstanceId = undefined;\n\t\tcommandClassId = undefined;\n\t\tdata = zway.controller.data;\n\t} else if (devBind) {\n\t\tpath = instanceId;\n\t\tfunc = commandClassId;\n\t\tinstanceId = undefined;\n\t\tcommandClassId = undefined;\n\t\tdata = zway.devices[nodeId].data;\n\t} else {\n\t\tdata = zway.devices[nodeId].instances[instanceId].commandClasses[commandClassId].data;\n\t}\n\n\tif (path) {\n\t\tpathArr = path.split(\".\");\n\t}\n\n\tif (!func) {\n\t\tconsole.log(\"Function passed to dataBind is undefined\");\n\t\treturn;\n\t}\n\n\twhile (pathArr.length) {\n\t\tdata = data[pathArr.shift()];\n\t\tif (!data) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (data) {\n\t\tif (ctrlBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zway\": zway,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, false)\n\t\t\t});\n\t\t} else if (devBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zway\": zway,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, nodeId, false)\n\t\t\t});\n\t\t} else {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zway\": zway,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"instanceId\": instanceId,\n\t\t\t\t\"commandClassId\": commandClassId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, null, type === \"child\")\n\t\t\t});\n\t\t\tif (type === \"value\") {\n\t\t\t\tfunc.call(data, this.ZWAY_DATA_CHANGE_TYPE.Updated);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconsole.log(\"Can not find data path:\", nodeId, instanceId, commandClassId, path);\n\t}\n};\n\nZWave.prototype.dataUnbind = function(dataBindings) {\n\tdataBindings.forEach(function(item) {\n\t\tvar ctrlBind = !(\"nodeId\" in item),\n\t\t\tdevBind = !(\"instanceId\" in item);\n\n\t\tif (item.zway && item.zway.isRunning() && (ctrlBind || (item.zway.devices[item.nodeId] && (devBind || (item.zway.devices[item.nodeId].instances[item.instanceId] && item.zway.devices[item.nodeId].instances[item.instanceId].commandClasses[item.commandClassId]))))) {\n\t\t\tvar data = ctrlBind ? item.zway.controller.data : (devBind ? item.zway.devices[item.nodeId].data : item.zway.devices[item.nodeId].instances[item.instanceId].commandClasses[item.commandClassId].data),\n\t\t\t\tpathArr = item.path ? item.path.split(\".\") : [];\n\n\t\t\twhile (pathArr.length) {\n\t\t\t\tdata = data[pathArr.shift()];\n\t\t\t\tif (!data) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data) {\n\t\t\t\tdata.unbind(item.func);\n\t\t\t} else {\n\t\t\t\tconsole.log(\"Can not find data path:\", item.nodeId, item.instanceId, item.commandClassId, item.path);\n\t\t\t}\n\t\t}\n\t});\n\tdataBindings = null;\n};\n\n// ------------- Update time every day -----\n\nZWave.prototype.timeUpdaterStart = function() {\n\tvar self = this;\n\t\n\tthis.controller.emit(\"cron.addTask\", \"ZWaveTimeUpdater.poll\", {\n\t\tminute: 0,\n\t\thour: 3,\n\t\tweekDay: null,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\t// add event listener\n\tthis.timeUpdater = function() {\n\t\tvar devices = Object.keys(self.zway.devices);\n\t\tdevices.forEach(function(nodeId) {\n\t\t\tif (nodeId == self.zway.controller.data.nodeId.value) return; // not a strict === since nodeId is a string index, but number in DH\n\t\t\t\n\t\t\tif (self.zway.devices[nodeId].TimeParameters)\n\t\t\t\tself.zway.devices[nodeId].TimeParameters.Set();\n\t\t\tif (self.zway.devices[nodeId].Clock)\n\t\t\t\tself.zway.devices[nodeId].Clock.Set();\n\t\t});\n\t};\n\n\tthis.controller.on(\"ZWaveTimeUpdater.poll\", this.timeUpdater);\n};\n\nZWave.prototype.timeUpdaterStop = function() {\n\tthis.controller.emit(\"cron.removeTask\", \"ZWaveTimeUpdater.poll\");\n\n\tif (this.timeUpdater)\n\t\tthis.controller.off(\"ZWaveTimeUpdater.poll\", this.timeUpdater);\n}\n\n// ------------- Dead Detection ------------\n\nZWave.prototype.deadDetectionStart = function() {\n\tvar self = this;\n\n\tthis.deadDetectionDataBindings = [];\n\n\t// Bind to all future Devices creation and enumerate existing\n\tthis.deadDetectionBinding = this.zway.bind(function(type, nodeId) {\n\t\tif (type === self.ZWAY_DEVICE_CHANGE_TYPES[\"DeviceAdded\"]) {\n\t\t\tself.deadDetectionAttach(nodeId);\n\t\t}\n\t}, this.ZWAY_DEVICE_CHANGE_TYPES[\"DeviceAdded\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"EnumerateExisting\"]);\n\n\t// for battery devices we will check for wakeups once a day\n\t// check periodically if nodes are failed to mark their vDevs as failed too\n\tthis.controller.emit(\"cron.addTask\", \"deadDetectionCheckBatteryDevice.poll\", {\n\t\tminute: 0,\n\t\thour: 0,\n\t\tweekDay: null,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\t// add event listener\n\tthis.deadDetectionCheckBatteryDevicesPoll = function() {\n\t\tself.deadDetectionCheckBatteryDevices();\n\t};\n\n\tthis.controller.on(\"deadDetectionCheckBatteryDevice.poll\", this.deadDetectionCheckBatteryDevicesPoll);\n};\n\nZWave.prototype.deadDetectionStop = function() {\n\tthis.controller.emit(\"cron.removeTask\", \"deadDetectionCheckBatteryDevice.poll\");\n\n\tif (this.deadDetectionCheckBatteryDevicesPoll)\n\t\tthis.controller.off(\"deadDetectionCheckBatteryDevice.poll\", this.deadDetectionCheckBatteryDevicesPoll);\n\n\t// releasing bindings\n\ttry {\n\t\tif (this.deadDetectionDataBindings) {\n\t\t\tthis.dataUnbind(this.deadDetectionDataBindings);\n\t\t}\n\t} catch (e) {\n\t\t// Z-Way already gone, skip deallocation\n\t\t//this.zway = null;\n\t}\n};\n\nZWave.prototype.deadDetectionAttach = function(nodeId) {\n\tvar self = this;\n\tthis.dataBind(this.deadDetectionDataBindings, this.zway, nodeId, \"isFailed\", function(type, arg) { // arg is nodeId (see dataBind)\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"PhantomUpdate\"])) {\n\t\t\tself.deadDetectionCheckDevice(arg);\n\t\t}\n\t});\n\tthis.dataBind(this.deadDetectionDataBindings, this.zway, nodeId, \"failureCount\", function(type, arg) { // arg is nodeId (see dataBind)\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"PhantomUpdate\"])) {\n\t\t\tself.deadDetectionCheckDevice(arg);\n\t\t}\n\t});\n\tif (this.zway.devices[nodeId].Wakeup) {\n\t\tthis.dataBind(this.deadDetectionDataBindings, this.zway, nodeId, 0, this.CC[\"Wakeup\"], \"lastWakeup\", function(type) { // don't use arg, but instead outer scope\n\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) return;\n\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"PhantomUpdate\"])) {\n\t\t\t\tself.controller.vDevFailedDetection(nodeId, false);\n\t\t\t}\n\t\t});\n\t}\n};\n\nZWave.prototype.deadDetectionCheckDevice = function(nodeId) {\n\tvar langFile = this.loadModuleLang();\n\tvar devName = this.zway.devices[nodeId].data.givenName.value;\n\n\tif (this.zway.devices[nodeId].data.isFailed.value) {\n\t\tif (this.zway.devices[nodeId].data.failureCount.value === 2) {\n\t\t\tthis.controller.vDevFailedDetection(nodeId, true);\n\t\t\tthis.addNotification(\"error\", langFile.err_connct + devName + \" (\" + nodeId.toString(10) + \")\", \"connection\");\n\t\t}\n\t} else {\n\t\tthis.controller.vDevFailedDetection(nodeId, false);\n\t\tthis.addNotification(\"notification\", langFile.dev_btl + devName + \" (\" + nodeId.toString(10) + \")\", \"connection\");\n\t}\n};\n\nZWave.prototype.deadDetectionCheckBatteryDevices = function() {\n\tvar self = this;\n\tObject.keys(this.zway.devices).forEach(function(nodeId) {\n\t\tself.deadDetectionCheckBatteryDevice(nodeId);\n\t});\n};\n\nZWave.prototype.deadDetectionCheckBatteryDevice = function(nodeId) {\n\tvar devData = this.zway.devices[nodeId].data,\n\t\twakeupData = this.zway.devices[nodeId].Wakeup && this.zway.devices[nodeId].Wakeup.data,\n\t\tisFailedNode = devData.isFailed.value || false,\n\t\tnow = Math.floor(Date.now() / 1000);\n\n\tif (nodeId === this.zway.controller.data.nodeId.value) return;\n\n\tif (wakeupData && devData.basicType.value !== 1) {\n\t\t// handle only sleeping nodes with Wakeup CC excluding Portable Controllers\n\t\tvar wakeupInterval = wakeupData.interval.value,\n\t\t\tlastReceive = parseInt(devData.lastReceived.updateTime, 10) || 0,\n\t\t\tlastSend = parseInt(devData.lastSend.updateTime, 10) || 0,\n\t\t\tlastCommunication = (lastSend > lastReceive) ? lastSend : lastReceive;\n\t\tif (\n\t\t\twakeupData.interval.value > 0 && // Wakeup Interval is not zero\n\t\t\tthis.zway.controller.data.nodeId.value === wakeupData.nodeId.value && // controller is the destination for Wakeup Notification\n\t\t\tlastCommunication + 3 * wakeupData.interval.value < now // communication not happens within the last three Wakeup Intervals\n\t\t) {\n\t\t\tthis.controller.vDevFailedDetection(nodeId, true);\n\t\t} else {\n\t\t\tthis.controller.vDevFailedDetection(nodeId, isFailedNode);\n\t\t}\n\t} else {\n\t\tthis.controller.vDevFailedDetection(nodeId, isFailedNode);\n\t}\n};\n\n// ----------------- Devices Creator ---------------\n\n\nZWave.prototype.gateDevicesStart = function() {\n\n\tvar self = this,\n\t\tfixesDone = [];\n\n\tthis.gateDataBinding = [];\n\n\t// Bind to all future CommandClasses changes\n\tthis.gateBinding = this.zway.bind(function(type, nodeId, instanceId, commandClassId) {\n\t\tif (type === self.ZWAY_DEVICE_CHANGE_TYPES[\"CommandAdded\"]) {\n\t\t\t// Ignore Static PC Controllers\n\t\t\tif (2 === self.zway.devices[nodeId].data.basicType.value && 1 === self.zway.devices[nodeId].data.specificType.value) {\n\t\t\t\t// console.log(\"Device\", nodeId, \"is a Static PC Controller, ignoring\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"interviewDone\", function(type) {\n\t\t\t\tif (this.value === true && type !== self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\n\t\t\t\t\tvar create = true,\n\t\t\t\t\t\tchangeVDev = {},\n\t\t\t\t\t\tdeviceData = self.zway.devices[nodeId].data,\n\t\t\t\t\t\tdeviceInstances = self.zway.devices[nodeId].instances,\n\t\t\t\t\t\tdeviceCC = deviceInstances[instanceId].commandClasses[commandClassId],\n\t\t\t\t\t\tc = self.zway.controller,\n\t\t\t\t\t\tmId = deviceData.manufacturerId.value ? deviceData.manufacturerId.value : null,\n\t\t\t\t\t\tmPT = deviceData.manufacturerProductType.value ? deviceData.manufacturerProductType.value : null,\n\t\t\t\t\t\tmPId = deviceData.manufacturerProductId.value ? deviceData.manufacturerProductId.value : null,\n\t\t\t\t\t\tappMajor = deviceData.applicationMajor.value ? deviceData.applicationMajor.value : null,\n\t\t\t\t\t\tappMinor = deviceData.applicationMinor.value ? deviceData.applicationMinor.value : null,\n\t\t\t\t\t\thasS2 = deviceInstances[instanceId].commandClasses[159],\n\t\t\t\t\t\tgivenName = null,\n\t\t\t\t\t\tsmartStartEntryPreset = null,\n\t\t\t\t\t\tdevId,\n\t\t\t\t\t\tappMajorId,\n\t\t\t\t\t\tappMajorMinorId,\n\t\t\t\t\t\tpostFix,\n\t\t\t\t\t\tfixes = self.postfix.fixes ? self.postfix.fixes : self.postfix;\n\n\t\t\t\t\t// try to get fix by manufacturerProductId and application Version\n\t\t\t\t\tif (!!mId && !!mPT && !!mPId && !!self.postfix) {\n\n\t\t\t\t\t\tdevId = mId + '.' + mPT + '.' + mPId;\n\t\t\t\t\t\tappMajorId = devId + '.' + appMajor;\n\t\t\t\t\t\tappMajorMinorId = devId + '.' + appMajor + '.' + appMinor;\n\t\t\t\t\t\tpostFix = fixes.filter(function(fix) {\n\t\t\t\t\t\t\treturn \tfix.p_id === mId.toString() || //search by manufacturerId\n\t\t\t\t\t\t\t\tfix.p_id === devId || //search by manufacturerProductId\n\t\t\t\t\t\t\t\tfix.p_id === appMajorId || //search by applicationMajor\n\t\t\t\t\t\t\t\tfix.p_id === appMajorMinorId; //search by applicationMajor and applicationMinor\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\t\t\t\t\t// --- postfix functions\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\n\t\t\t\t\t// add SwitchController support by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... instance ID\n\t\t\t\t\t// commandClass ... Command Class ID\n\t\t\t\t\t// minBtnNr ... starting button number\n\t\t\t\t\t// maxBtnNr ... maximum button number\n\t\t\t\t\t// type ... 'S' for 'scene' and 'B' for 'button' or 'switchControl'\n\t\t\t\t\tfunction scenesSupport(instId, commandClass, minBtnNr, maxBtnNr, type) {\n\t\t\t\t\t\tvar trapArray = [],\n\t\t\t\t\t\t\tcommandClass = commandClass || null;\n\n\t\t\t\t\t\ttrapArray = self.controller.instances.filter(function(instance) {\n\t\t\t\t\t\t\treturn instance.moduleId === 'SwitchControlGenerator';\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (instId === instanceId && commandClassId === commandClass && deviceCC && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\tmaxBtnNr = (deviceCC.data.maxScenes && deviceCC.data.maxScenes.value && deviceCC.data.maxScenes.value <= maxBtnNr ? deviceCC.data.maxScenes.value : maxBtnNr) || 0\n\n\t\t\t\t\t\t\tif (trapArray[0].params.generated.indexOf('ZWayVDev_zway_Remote_' + nodeId + '-' + instanceId + '-0-1') === -1) {\n\t\t\t\t\t\t\t\tfor (i = minBtnNr; i <= maxBtnNr; i++) {\n\t\t\t\t\t\t\t\t\tthis.controller.emit('SwitchControlGenerator.register', 'ZWay', self.config.name, nodeId, instanceId, '0', i, type);\n\t\t\t\t\t\t\t\t\tconsole.logJS(i, minBtnNr, maxBtnNr);\n\n\t\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\t\tconsole.log('#######################', 'ADD SWITCHCONTROLGENERATOR SUPPORT TO #' + nodeId, '###############################');\n\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Add support for instance ' + instId + ':');\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'CC:', commandClass);\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Set maximum number of buttons / secnes to :', maxBtnNr);\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Add virtual devices as type button (B) or scene (S):', type);\n\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\tconsole.log('############################################################################################################');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// set device config by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... instance ID\n\t\t\t\t\t// parameter ... id of the parameter that should be changed. Can be 0 ... 0xff\n\t\t\t\t\t// value ... new value. Can be 0 ... 0xffffffff\n\t\t\t\t\t// size ... 0 for auto or 1, 2, 4 (Byte)\n\t\t\t\t\tfunction setConfig(instId, parameter, value, size) {\n\t\t\t\t\t\tvar parameter = Number.isInteger(parseInt(parameter)) ? parseInt(parameter) : null,\n\t\t\t\t\t\t\tvalue = Number.isInteger(parseInt(value)) ? parseInt(value) : null,\n\t\t\t\t\t\t\tsize = parseInt(size) || null;\n\n\t\t\t\t\t\tif (instId === instanceId && parameter !== null && !!value !== null && size !== null) {\n\t\t\t\t\t\t\t// set config after inclusion only and if it doesn't exist or isn't equal\n\t\t\t\t\t\t\tif (commandClassId === 112 && deviceCC && c.data.lastIncludedDevice.value === nodeId && (!deviceCC.data[parameter] || (deviceCC.data[parameter] && deviceCC.data[parameter].val.value !== value))) {\n\t\t\t\t\t\t\t\tdeviceCC.Set(parameter, value, size);\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'CHANGE CONFIGURATION OF #' + nodeId, '###############################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change configuration of instance ' + instId + ':');\n\t\t\t\t\t\t\t\tconsole.log('###', 'parameter:', parameter);\n\t\t\t\t\t\t\t\tconsole.log('###', 'value:', value);\n\t\t\t\t\t\t\t\tconsole.log('###', 'size:', size);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change CC entries by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... instance ID\n\t\t\t\t\t// commandClass ... Command Class ID\n\t\t\t\t\t// dataType ... data type object that should be changed -e.g. security, version, interviewDone\n\t\t\t\t\t// key ... of this data type object\n\t\t\t\t\t// value ... new value\n\t\t\t\t\tfunction setCCData(instId, commandClass, dataType, key, value) {\n\t\t\t\t\t\tvar commandClass = parseInt(commandClass, 10);\n\n\t\t\t\t\t\tif (commandClassId === commandClass &&\n\t\t\t\t\t\t\tdeviceInstances[instId].commandClasses[commandClass] &&\n\t\t\t\t\t\t\tc.data.lastIncludedDevice.value === nodeId) {\n\n\t\t\t\t\t\t\t// set value\n\t\t\t\t\t\t\tif (typeof value !== 'undefined' &&\n\t\t\t\t\t\t\t\tdeviceInstances[instId].commandClasses[commandClass].data[dataType] &&\n\t\t\t\t\t\t\t\tdeviceInstances[instId].commandClasses[commandClass].data[dataType][key] !== value) {\n\n\t\t\t\t\t\t\t\tdeviceInstances[instId].commandClasses[commandClass].data[dataType][key] = value;\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'SET COMMANDCLASS DATA OF:', devId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change CC entry of instance ' + instId + ':');\n\t\t\t\t\t\t\t\tconsole.log('###', 'CC:', commandClass);\n\t\t\t\t\t\t\t\tconsole.log('###', 'data type object that has changed:', dataType);\n\t\t\t\t\t\t\t\tconsole.log('###', 'new value for ' + key + ':', value);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('##############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change device entries by entering (runs once after inclusion):\n\t\t\t\t\t// dataType ... data type object that should be changed -e.g. security, version, interviewDone\n\t\t\t\t\t// key ... of this data type object\n\t\t\t\t\t// value ... new value\n\t\t\t\t\tfunction setDeviceData(dataType, key, value) {\n\t\t\t\t\t\tif (c.data.lastIncludedDevice.value === nodeId) {\n\n\t\t\t\t\t\t\t// set value\n\t\t\t\t\t\t\tif (typeof value !== 'undefined' &&\n\t\t\t\t\t\t\t\tdeviceData[dataType] &&\n\t\t\t\t\t\t\t\tdeviceData[dataType][key] !== value) {\n\n\t\t\t\t\t\t\t\tdeviceData[dataType][key] = value;\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'SET DEVICE DATA OF:', devId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change Device entry:');\n\t\t\t\t\t\t\t\tconsole.log('###', 'data type object that has changed:', dataType);\n\t\t\t\t\t\t\t\tconsole.log('###', 'new value for ' + key + ':', value);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('##############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change the node name (runs once after inclusion):\n\t\t\t\t\tfunction renameNode(nodeName) {\n\n\t\t\t\t\t\tif (nodeName !== deviceData.givenName.value) {\n\n\t\t\t\t\t\t\t// do something\n\t\t\t\t\t\t\tdeviceData.givenName.value = nodeName && nodeName !== '' && !!nodeName ? nodeName : deviceData.givenName.value;\n\n\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\tconsole.log('#######################', 'Apply postfix #' + nodeId, '################################');\n\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\tconsole.log('###', 'Change node name to: ', nodeName);\n\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\tconsole.log('######################################################################################');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\t\t\t\t\t// --- END\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\n\t\t\t\t\tif (postFix) {\n\t\t\t\t\t\tif (postFix.length > 0) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// works of course only during inclusion - after restart hidden elements are visible again\n\t\t\t\t\t\t\t\tif (!!nodeId && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\tvar intDone = deviceCC.data.interviewDone.value;\n\t\t\t\t\t\t\t\t\tintDelay = Date.now() + 5 * 1000; // wait not more than 5 seconds for single interview\n\n\t\t\t\t\t\t\t\t\t// wait till interview is done\n\t\t\t\t\t\t\t\t\twhile (Date.now() < intDelay && intDone === false) {\n\t\t\t\t\t\t\t\t\t\tintDone = deviceCC.data.interviewDone.value;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (intDone === false) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t// call preInteview functions from postfix.json\n\t\t\t\t\t\t\t\t\t\t\tpostFix.forEach(function(fix) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!!fix.preInterview && fix.preInterview && fix.preInterview.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tfix.preInterview.forEach(function(func) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teval(func);\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('##############', 'INTERVIEW-HAS-FAILED-----PREFIX-HAS-FAILED:', '#' + nodeId, '#######################');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###', 'ERROR:', e.toString());\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('######################################################################################################');\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// call postInterview functions from postfix.json\n\t\t\t\t\t\t\t\tpostFix.forEach(function(fix) {\n\t\t\t\t\t\t\t\t\tif (!!fix.postInterview && fix.postInterview && fix.postInterview.length > 0) {\n\t\t\t\t\t\t\t\t\t\tfix.postInterview.forEach(function(entry) {\n\t\t\t\t\t\t\t\t\t\t\tvar splittedEntry = entry.split(','),\n\t\t\t\t\t\t\t\t\t\t\t\tdevICC = instanceId + '-' + commandClassId;\n\n\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tswitch (splittedEntry[0]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'rename':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'hide':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'deactivate':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'icon':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'probeType':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1 && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) / postFix type / value - fallback true for hide / deactivate\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId][splittedEntry[0]] = splittedEntry[2] ? splittedEntry[2] : true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'discreteState':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1 && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]['discreteState']) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['discreteState'] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) / postFix type / scene + keyAttribute / value - fallback undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['discreteState'][splittedEntry[2]] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcnt: splittedEntry[3] ? splittedEntry[3] : undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taction: splittedEntry[4] ? splittedEntry[4] : undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: splittedEntry[5] ? splittedEntry[5] : undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'noVDev':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) without creation\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].noVDev = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'renameNode':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trenameNode(splittedEntry[1]);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'emulateOff':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[2]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].emulateOff = splittedEntry[2];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'configVDev':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// configVDev, i, cfg#, type, func1, func2, title\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[2] && splittedEntry[3] && splittedEntry[4] && splittedEntry[5]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1] + '-112';\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]['configVDev']) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['configVDev'] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['configVDev'][splittedEntry[2]] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: splittedEntry[3],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tp2v: splittedEntry[4],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tv2p: splittedEntry[5],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: splittedEntry[6] || ('Config #' + splittedEntry[2])\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'tilt':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].tilt = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'notificationStatus':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].notificationStatus = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teval(entry);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'PRE-OR-POSTFIX-ERROR:', '#' + nodeId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'ERROR:', e.toString());\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('#################################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar ccId = nodeId + '-' + instanceId + '-' + commandClassId;\n\n\n\t\t\t\t\tif (hasS2 && hasS2.data.publicKey && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t// console.log('########################################################################################');\n\t\t\t\t\t\tvar dsk = transformPublicKeyToDSK(hasS2.data.publicKey.value);\n\t\t\t\t\t\tvar dskEntryIndex = _.findIndex(self.dskCollection, function(entry) {\n\t\t\t\t\t\t\treturn entry['DSK'] === dsk;\n\t\t\t\t\t\t});\n\t\t\t\t\t\tvar dskEntry = self.dskCollection[dskEntryIndex] || null;\n\n\t\t\t\t\t\tif (dskEntry && dskEntry.state !== 'included') {\n\n\t\t\t\t\t\t\t// update state and nodeId\n\t\t\t\t\t\t\tdskEntry.state = 'included';\n\t\t\t\t\t\t\tdskEntry.nodeId = nodeId;\n\t\t\t\t\t\t\tdskEntry.addedAt = Date.now();\n\n\t\t\t\t\t\t\t// grep givenName from dskEntry\n\t\t\t\t\t\t\tgivenName = dskEntry.givenName? dskEntry.givenName : null; // filterIndex\n\n\t\t\t\t\t\t\t// replace old DSK entry\n\t\t\t\t\t\t\tself.dskCollection[dskEntryIndex] = dskEntry;\n\t\t\t\t\t\t\tsmartStartEntryPreset = dskEntry;\n\n\t\t\t\t\t\t\t// save dsk collection\n\t\t\t\t\t\t\tself.saveObject(\"dskCollection\", self.dskCollection, true);\n\n\t\t\t\t\t\t\t// console.log('###');\n\t\t\t\t\t\t\t// console.log('########################################################################################');\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsmartStartEntryPreset = dskEntry || null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!changeVDev[ccId] || (changeVDev[ccId] && !changeVDev[ccId].noVDev)) {\n\t\t\t\t\t\tself.parseAddCommandClass(nodeId, instanceId, commandClassId, false, changeVDev, smartStartEntryPreset);\n\t\t\t\t\t} else if (changeVDev[ccId] && changeVDev[ccId].noVDev) {\n\t\t\t\t\t\tvar devId = \"ZWayVDev_\" + self.config.name + \"_\" + nodeId + '-' + ccId;\n\t\t\t\t\t\t// console output\n\t\t\t\t\t\tconsole.log('#######################', 'Apply postfix for:', devId, '################################');\n\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\tconsole.log('###', 'not created');\n\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\tconsole.log('########################################################################################');\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!deviceData.givenName.value || deviceData.givenName.value == '') {\n\t\t\t\t\t\t// set givenName\n\t\t\t\t\t\tdeviceData.givenName.value = givenName? givenName : self.nodeNameByType(nodeId, deviceData);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tself.parseDelCommandClass(nodeId, instanceId, commandClassId);\n\t\t\t\t}\n\t\t\t}, \"value\");\n\t\t} else {\n\t\t\tself.parseDelCommandClass(nodeId, instanceId, commandClassId);\n\t\t}\n\t}, this.ZWAY_DEVICE_CHANGE_TYPES[\"CommandAdded\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"CommandRemoved\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"EnumerateExisting\"]);\n\n\tself.dataBind(self.gateDataBinding, self.zway, \"lastExcludedDevice\", function(type) {\n\t\tvar _id = this.value,\n\t\t\t_toRemove = self.controller.devices.filter(function(el) {\n\t\t\t\treturn el.id.indexOf(\"ZWayVDev_\" + self.config.name + \"_\" + _id + '-') === 0;\n\t\t\t}).map(function(el) {\n\t\t\t\treturn el.id;\n\t\t\t}).concat(\n\t\t\t\tObject.keys(self.controller.vdevInfo).filter(function(__id) {\n\t\t\t\t\treturn __id.indexOf(\"ZWayVDev_\" + self.config.name + \"_\" + _id + '-') === 0;\n\t\t\t\t})\n\t\t\t);\n\n\t\t_toRemove.forEach(function(name) {\n\t\t\tself.controller.devices.remove(name);\n\t\t\tself.controller.devices.cleanup(name);\n\t\t});\n\n\t\t// update state of DSK entry if node is smart start device\n\t\tif (_id) {\n\t\t\tvar dskEntryIndex = _.findIndex(self.dskCollection, function(entry) {\n\t\t\t\treturn entry.nodeId === _id;\n\t\t\t});\n\t\t\tvar dskEntry = self.dskCollection[dskEntryIndex];\n\n\t\t\tif (dskEntry) {\n\n\t\t\t\t// update state and nodeId\n\t\t\t\tdskEntry.state = 'pending';\n\t\t\t\tdskEntry.nodeId = null;\n\t\t\t\tdskEntry.addedAt = null;\n\n\t\t\t\t// replace old DSK entry\n\t\t\t\tself.dskCollection[dskEntryIndex] = dskEntry;\n\n\t\t\t\t// save dsk collection\n\t\t\t\tself.saveObject(\"dskCollection\", self.dskCollection, true);\n\t\t\t}\n\t\t}\n\t}, \"\");\n};\n\nZWave.prototype.gateDevicesStop = function() {\n\tvar self = this;\n\n\t// delete devices\n\tthis.controller.devices.map(function(el) {\n\t\treturn el.id;\n\t}).filter(function(el) {\n\t\treturn el.indexOf(\"ZWayVDev_\" + self.config.name + \"_\") === 0;\n\t}).forEach(function(el) {\n\t\ttry {\n\t\t\tself.controller.devices.remove(el);\n\t\t} catch (e) {\n\t\t\t// do nothing - this is to prevent Stop abort to make sure we release zway context in C\n\t\t}\n\t});\n\n\t// releasing bindings\n\ttry {\n\t\tif (this.gateDataBinding) {\n\t\t\tthis.dataUnbind(this.gateDataBinding);\n\t\t}\n\t\tif (this.zway) {\n\t\t\tthis.zway.unbind(this.gateBinding);\n\t\t}\n\t} catch (e) {\n\t\t// Z-Way already gone, skip deallocation\n\t\t//this.zway = null;\n\t}\n};\n\nZWave.prototype.addVDevInfo = function(info, nodeId, smartStartEntryPreset) {\n\t_.extend(info, {\n\t\ttechnology: \"Z-Wave\",\n\t\tbindingName: this.config.name,\n\t\tnodeId: nodeId,\n\t\tmanufacturer: this.zway.devices[nodeId].data.vendorString.value || \"\",\n\t\tproduct: this.zway.devices[nodeId].data.productString.value || \"\",\n\t\tfirmware: (this.zway.devices[nodeId].data.applicationMajor.value + \".\" + this.zway.devices[nodeId].data.applicationMinor.value) || \"\",\n\t\tlocation: smartStartEntryPreset && _.isNumber(smartStartEntryPreset.location) ? smartStartEntryPreset.location : 0,\n\t});\n}\n\nZWave.prototype.compileTitle = function(nodeId, instanceId, smartStartEntryPreset, title, type, addVendor) { // accepts more arguments, see code\n\tvar sortArgs = [];\n\n\t// if there is a given name preset, use it first\n\tif (smartStartEntryPreset && smartStartEntryPreset.givenName) {\n\t\tsortArgs.push(smartStartEntryPreset.givenName);\n\t}\n\t\n\t// add vendor name\n\tif (addVendor === undefined || addVendor === true) {\n\t\tvar vendorName = this.zway.devices[nodeId].data.vendorString.value;\n\t\tif (vendorName) {\n\t\t\tsortArgs.push(vendorName);\n\t\t};\n\t}\n\n\tsortArgs.push(title);\n\t\n\t// add probeType\n\tif (type) {\n\t\tsortArgs.push(type);\n\t}\n\n\t// add id\n\tsortArgs.push(\"(\" + nodeId + (instanceId ? \".\" + instanceId : \"\") + \")\");\n\n\treturn sortArgs.join(' ');\n};\n\nZWave.prototype.applyPostfix = function(defaultObj, changeObj, nodeId, instanceId, smartStartEntryPreset, title, type, addVendor) {\n\tthis.addVDevInfo(defaultObj, nodeId, smartStartEntryPreset);\n\t\n\tdefaultObj.metrics.title = this.compileTitle(nodeId, instanceId, smartStartEntryPreset, title, type, addVendor);\n\t\n\tif (changeObj) {\n\t\tif (changeObj.noVDev) return false;\n\t\t\n\t\tif (changeObj.probeType)\n\t\t\tdefaultObj.probeType = changeObj.probeType;\n\t\tif (changeObj.icon)\n\t\t\tdefaultObj.metrics.icon = changeObj.icon;\n\t\tif (changeObj.rename)\n\t\t\tdefaultObj.metrics.title = this.compileTitle(nodeId, instanceId, smartStartEntryPreset, changeObj.rename, undefined, false);\n\t\tdefaultObj.visibility = changeObj.hide ? false : true;\n\t\tdefaultObj.permanently_hidden = changeObj.deactivate ? true : false;\n\t\n\t\tif (changeObj.discreteState && !_.isEmpty(changeObj.discreteState) && defaultObj.metrics.discreteStates) {\n\t\t\tdefaultObj.metrics.discreteStates = changeObj.discreteState;\n\t\t}\n\t}\n\treturn true;\n};\n\nZWave.prototype.parseAddCommandClass = function(nodeId, instanceId, commandClassId, scaleAdded, changeVDev, smartStartEntryPreset) {\n\tnodeId = parseInt(nodeId, 10);\n\tinstanceId = parseInt(instanceId, 10);\n\tcommandClassId = parseInt(commandClassId, 10);\n\n\t// avoid errors during binding stop and device exclusion\n\tif (!this.zway || !this.zway.devices[nodeId]) {\n\t\treturn;\n\t}\n\n\tvar self = this,\n\t\tinstance = this.zway.devices[nodeId].instances[instanceId],\n\t\tinstanceCommandClasses = Object.keys(instance.commandClasses).map(function(x) {\n\t\t\treturn parseInt(x);\n\t\t}),\n\t\tcc = instance.commandClasses[commandClassId],\n\t\tsepar = \"-\",\n\t\tvDevIdPrefix = \"ZWayVDev_\" + this.config.name + \"_\",\n\t\tvDevIdNI = nodeId + separ + instanceId,\n\t\tvDevIdC = commandClassId,\n\t\tvDevId = vDevIdPrefix + vDevIdNI + separ + vDevIdC,\n\t\tchangeDevId = vDevIdNI + separ + vDevIdC,\n\t\tdefaults;\n\t// vDev is not in this scope, but in {} scope for each type of device to allow reuse it without closures\n\n\ttry {\n\t\tif (!cc) {\n\t\t\treturn; // do not handle destroyed Command Classes\n\t\t}\n\t\t\n\t\tif (!cc.data.supported.value) {\n\t\t\treturn; // do not handle unsupported Command Classes\n\t\t}\n\n\t\t/*\n\t\t// Ignore SwitchBinary if SwitchMultilevel exists\n\t\tif (this.CC[\"SwitchBinary\"] === commandClassId && in_array(instanceCommandClasses, this.CC[\"SwitchMultilevel\"]) && instance.commandClasses[this.CC[\"SwitchMultilevel\"]].data.supported.value) {\n\t\t\t// console.log(\"Ignoring SwitchBinary due to SwitchMultilevel existence\");\n\t\t\treturn;\n\t\t}\n\t\tif (this.CC[\"SwitchMultilevel\"] === commandClassId && this.controller.devices.get(vDevIdPrefix + vDevIdNI + separ + this.CC[\"SwitchBinary\"])) {\n\t\t\t// console.log(\"Removing SwitchBinary due to SwitchMultilevel existence\");\n\t\t\tthis.controller.devices.remove(vDevIdPrefix + vDevIdNI + separ + this.CC[\"SwitchBinary\"]);\n\t\t}\n\t\t*/\n\n\n\n\t\tif (this.CC[\"SwitchBinary\"] === commandClassId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar icon = \"switch\";\n\t\t\tvar probeType = \"switch\";\n\n\t\t\tswitch (this.zway.devices[nodeId].data.specificType.value) {\n\t\t\t\tcase 0x01:\n\t\t\t\t\tprobeType = \"power_switch_binary\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x03:\n\t\t\t\t\tprobeType = \"scene_switch_binary\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x04:\n\t\t\t\t\tprobeType = \"power_strip\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x05:\n\t\t\t\t\ticon = \"siren\";\n\t\t\t\t\tprobeType = \"siren\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x06:\n\t\t\t\t\ticon = \"valve\";\n\t\t\t\t\tprobeType = \"valve\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tprobeType = \"switch\";\n\t\t\t\t\tbreak;\n\t\t\t};\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Switch')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\tcc.Set(true);\n\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\tcc.Set(false);\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', this.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\tthis.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"level\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"SwitchMultilevel\"] === commandClassId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar icon;\n\t\t\tvar title;\n\t\t\tvar probeType = 'multilevel';\n\t\t\tif (this.zway.devices[nodeId].data.genericType.value === 0x11 && _.contains([0x03, 0x05, 0x06, 0x07], this.zway.devices[nodeId].data.specificType.value)) {\n\t\t\t\ticon = 'blinds'; // or alternatively window\n\t\t\t\tprobeType = 'motor';\n\t\t\t\ttitle = 'Blind';\n\t\t\t} else if (this.zway.devices[nodeId].data.genericType.value === 0x11 && this.zway.devices[nodeId].data.specificType.value == 0x08) {\n\t\t\t\ticon = 'fan';\n\t\t\t\ttitle = 'Fan';\n\t\t\t} else {\n\t\t\t\ticon = 'multilevel';\n\t\t\t\ttitle = 'Dimmer';\n\t\t\t}\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, title)) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Blinds\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (newVal > 99) {\n\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal === 255) {\n\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t} else if (newVal > 99) {\n\t\t\t\t\t\t\tif (newVal === 100) {\n\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tnewVal = null;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"stop\" === command) { // Commands for Blinds\n\t\t\t\t\t\tcc.StopLevelChange();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\tcc.StartLevelChange(0);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\tcc.StartLevelChange(1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.Set(newVal, args.duration);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.Set(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"level\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"SwitchColor\"] === commandClassId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar\n\t\t\t\tCOLOR_SOFT_WHITE = 0,\n\t\t\t\tCOLOR_COLD_WHITE = 1,\n\t\t\t\tCOLOR_RED = 2,\n\t\t\t\tCOLOR_GREEN = 3,\n\t\t\t\tCOLOR_BLUE = 4;\n\n\t\t\tvar haveRGB = cc.data && cc.data[COLOR_RED] && cc.data[COLOR_GREEN] && cc.data[COLOR_BLUE] && true;\n\n\t\t\tif (haveRGB && !self.controller.devices.get(vDevId + separ + \"rgb\")) {\n\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: \"switchRGBW\",\n\t\t\t\t\tprobeType: 'switchColor_rgb',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\tcolor: {\n\t\t\t\t\t\t\tr: cc.data[COLOR_RED].level.value,\n\t\t\t\t\t\t\tg: cc.data[COLOR_GREEN].level.value,\n\t\t\t\t\t\t\tb: cc.data[COLOR_BLUE].level.value\n\t\t\t\t\t\t},\n\t\t\t\t\t\tlevel: 'off',\n\t\t\t\t\t\toldColor: {},\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId + separ + \"rgb\"], nodeId, instanceId, smartStartEntryPreset, 'Color')) return;\n\n\t\t\t\tvar vDev_rgb = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId + separ + \"rgb\",\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\tvar color = {\n\t\t\t\t\t\t\t\tr: 0,\n\t\t\t\t\t\t\t\tg: 0,\n\t\t\t\t\t\t\t\tb: 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toldColor = vDev_rgb.get('metrics:oldColor');\n\t\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\t\tif (!_.isEmpty(oldColor)) {\n\t\t\t\t\t\t\t\tcolor = oldColor;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcolor.r = color.g = color.b = 255;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (command === \"off\") {\n\t\t\t\t\t\t\tcolor.r = color.g = color.b = 0;\n\t\t\t\t\t\t} else if (command === \"exact\") {\n\t\t\t\t\t\t\tcolor.r = parseInt(args.red, 10);\n\t\t\t\t\t\t\tcolor.g = parseInt(args.green, 10);\n\t\t\t\t\t\t\tcolor.b = parseInt(args.blue, 10);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:oldColor\", color);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcc.SetMultiple([COLOR_RED, COLOR_GREEN, COLOR_BLUE], [color.r, color.g, color.b]);\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: this.id\n\t\t\t\t});\n\n\t\t\t\tfunction handleColor(type, arg) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar isOn = cc.data && (cc.data[COLOR_RED].level.value || cc.data[COLOR_GREEN].level.value || cc.data[COLOR_BLUE].level.value);\n\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + 'rgb');\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvar color = {\n\t\t\t\t\t\t\t\tr: cc.data[COLOR_RED].level.value,\n\t\t\t\t\t\t\t\tg: cc.data[COLOR_GREEN].level.value,\n\t\t\t\t\t\t\t\tb: cc.data[COLOR_BLUE].level.value\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:color\", color);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:level\", isOn ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}\n\n\t\t\t\tif (vDev_rgb) {\n\t\t\t\t\tvDev_rgb.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, COLOR_RED + \".level\", handleColor, \"value\");\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, COLOR_GREEN + \".level\", handleColor, \"value\");\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, COLOR_BLUE + \".level\", handleColor, \"value\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(colorId) {\n\n\t\t\t\t\tcolorId = parseInt(colorId, 10);\n\t\t\t\t\tif (!isNaN(colorId) && !self.controller.devices.get(vDevId + separ + colorId) && (!haveRGB || (colorId !== COLOR_RED && colorId !== COLOR_GREEN && colorId !== COLOR_BLUE))) {\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + colorId;\n\n\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\t\tprobeType: '',\n\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\t\t\tlevel: 'off',\n\t\t\t\t\t\t\t\toldLevel: 0,\n\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, cc.data[colorId].capabilityString.value)) return;\n\n\t\t\t\t\t\tswitch (colorId) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'switchColor_soft_white';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'switchColor_cold_white';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'switchColor_red';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'switchColor_green';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'switchColor_blue';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + colorId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t\tvar newVal,\n\t\t\t\t\t\t\t\t\tlevel = this.get('metrics:level'),\n\t\t\t\t\t\t\t\t\toldLevel = this.get('metrics:oldLevel');\n\n\t\t\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\t\t\tif (!_.isEmpty(oldLevel)) {\n\t\t\t\t\t\t\t\t\t\tnewVal = oldLevel;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t\t\t\t} else if (\"max\" === command) {\n\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.ceil(level * 255 / 99) + 10;\n\t\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (newVal > 255) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.ceil(level * 255 / 99) - 10;\n\t\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.ceil(parseInt(args.level, 10) * 255 / 99);\n\t\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t\t} else if (newVal > 255) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\t\t\t\tif (\"exactSmooth\" === command) {\n\t\t\t\t\t\t\t\t\t\tcc.Set(colorId, newVal, args.duration);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tcc.Set(colorId, newVal);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, colorId + \".level\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + colorId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvar value = Math.ceil(this.value * 99 / 255);\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", value);\n\t\t\t\t\t\t\t\t\t\tif (this.value > 0) {\n\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:oldLevel\", value);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (this.CC[\"SoundSwitch\"] === commandClassId) {\n\t\t\tif (cc.data) {\n\t\t\t\t// tones\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'scene',\n\t\t\t\t\t\tlevel: 'on',\n\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tfor(var toneId = 0; toneId <= cc.data.tonesNumber.value; toneId++) {\n\t\t\t\t\t(function(toneId) {\n\t\t\t\t\t\tif ((toneId == 0 || cc.data[toneId]) && !self.controller.devices.get(vDevId + separ + toneId)) {\n\t\t\t\t\t\t\tvar cVDId = changeDevId + separ + toneId;\n\n\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, toneId ? cc.data[toneId].toneName.value : 'Mute')) return;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\tdeviceId: vDevId + separ + toneId,\n\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\t\t\t\t\tcc.TonePlaySet(toneId);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, toneId + \".toneName\", function(type) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + toneId);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"tonesNumber\", function(type) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + \"0\");\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})(toneId);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.controller.devices.get(vDevId)) {\n\t\t\t\t\t// volume\n\t\t\t\t\tdefaults = {\n\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\tprobeType: 'volume',\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Volume')) return;\n\n\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t\t\t} else if (\"max\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (newVal > 99) {\n\t\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"exact\" === command) {\n\t\t\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t} else if (newVal === 255) {\n\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t} else if (newVal > 99) {\n\t\t\t\t\t\t\t\t\tif (newVal === 100) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewVal = null;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\t\t\tcc.ConfigurationGet();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\t\t\tcc.ConfigurationSet(0, newVal);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"defaultVolume\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"SensorBinary\"] === commandClassId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\ticon: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(vDevId + separ + sensorTypeId)) {\n\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[sensorTypeId].sensorTypeString.value;\n\t\t\t\t\t\t// aivs // Motion icon for Sensor Binary by default\n\t\t\t\t\t\tdefaults.metrics.icon = \"motion\";\n\t\t\t\t\t\tdefaults.probeType = \"general_purpose\";\n\n\t\t\t\t\t\tif (sensorTypeId === 2) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"smoke\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 3 || sensorTypeId === 4) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 6) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"alarm_flood\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 7) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"cooling\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 8) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"tamper\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 10) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"door\";\n\t\t\t\t\t\t\tdefaults.probeType = \"door-window\";\n\t\t\t\t\t\t} else if (sensorTypeId === 12) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"motion\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + sensorTypeId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tif (changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\tvDev.__emulateOff_timeout = parseInt(changeVDev[cVDId].emulateOff, 10);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, sensorTypeId + \".level\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\t\tif (vDev.__emulateOff_timeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (this.value) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (vDev.get(\"metrics:level\") !== \"on\" || !vDev.__emulateOff_timer) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer && clearTimeout(vDev.__emulateOff_timer);\n\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer = 0;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}, vDev.__emulateOff_timeout);\n\t\t\t\t\t\t\t\t\t\t\t\t} // off from the sensor is ignored\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\n\t\t\t\t\t\t\tif (changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\t// on start we need to kick the timer\n\t\t\t\t\t\t\t\tif (vDev.get(\"metrics:level\") === \"on\") {\n\t\t\t\t\t\t\t\t\tself.zway.devices[nodeId].instances[instanceId].commandClasses[commandClassId].data[sensorTypeId].level.value = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddCommandClass(nodeId, instanceId, commandClassId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"SensorMultilevel\"] === commandClassId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(vDevId + separ + sensorTypeId)) {\n\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[sensorTypeId].sensorTypeString.value;\n\t\t\t\t\t\tdefaults.metrics.scaleTitle = cc.data[sensorTypeId].scaleString.value;\n\n\t\t\t\t\t\tif (sensorTypeId === 1) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"temperature\";\n\t\t\t\t\t\t} else if (sensorTypeId === 3) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"luminosity\";\n\t\t\t\t\t\t} else if (sensorTypeId === 4 || sensorTypeId === 15 || sensorTypeId === 16) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"energy\";\n\t\t\t\t\t\t} else if (sensorTypeId === 5) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"humidity\";\n\t\t\t\t\t\t} else if (sensorTypeId === 9) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"barometer\";\n\t\t\t\t\t\t} else if (sensorTypeId === 12) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"rain\";\n\t\t\t\t\t\t} else if (sensorTypeId === 17) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co2\";\n\t\t\t\t\t\t} else if (sensorTypeId === 25) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"seismic\";\n\t\t\t\t\t\t} else if (sensorTypeId === 27) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"ultraviolet\";\n\t\t\t\t\t\t} else if (sensorTypeId === 40) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co\";\n\t\t\t\t\t\t} else if (sensorTypeId === 52) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_x\";\n\t\t\t\t\t\t} else if (sensorTypeId === 53) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_y\";\n\t\t\t\t\t\t} else if (sensorTypeId === 54) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_z\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + sensorTypeId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, sensorTypeId + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddCommandClass(nodeId, instanceId, commandClassId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"Meter\"] === commandClassId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorMultilevel',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'meter',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(scaleId) {\n\n\t\t\t\t\tscaleId = parseInt(scaleId, 10);\n\t\t\t\t\tif (!isNaN(scaleId) && !self.controller.devices.get(vDevId + separ + scaleId)) {\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + scaleId;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[scaleId].sensorTypeString.value;\n\t\t\t\t\t\tdefaults.metrics.scaleTitle = cc.data[scaleId].scaleString.value;\n\n\t\t\t\t\t\t// Check sensor type, can be: Electric, Gas, Water\n\t\t\t\t\t\tswitch (cc.data[scaleId].sensorType.value) {\n\t\t\t\t\t\t\t// Electric meter\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tswitch (scaleId) {\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_kilowatt_hour';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_kilovolt_ampere_hour';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_watt';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_pulse_count';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_voltage';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_ampere';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_power_factor';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t// Gas meter\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tswitch (scaleId) {\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterGas_cubic_meters';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterGas_cubic_feet';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterGas_pulse_count';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t// Water meter\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tswitch (scaleId) {\n\t\t\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_cubic_meters';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_cubic_feet';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_us_gallons';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'meterWater_pulse_count';\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Meter', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + scaleId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(scaleId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, scaleId + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + scaleId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddCommandClass(nodeId, instanceId, commandClassId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"MeterPulse\"] === commandClassId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorMultilevel',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'meterElectric_pulse_count',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'meter',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.controller.devices.get(vDevId)) {\n\t\t\t\tvar cVDId = changeDevId;\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Meter Pulse')) return;\n\n\t\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"val\", function(type) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}, \"value\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"Battery\"] === commandClassId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'battery',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'Battery',\n\t\t\t\t\tscaleTitle: '%',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'battery',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Battery')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"last\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? 0 : this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"DoorLock\"] === commandClassId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\tisFailed: false\n\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Door Lock')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\tcc.Set(0);\n\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\tcc.Set(255);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"mode\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? \"close\" : \"open\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"BarrierOperator\"] === commandClassId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Garage Door')) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\tcc.Set(255);\n\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\tcc.Set(0);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"state\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? \"open\" : \"close\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"ThermostatMode\"] === commandClassId) {\n\t\t\tvar\n\t\t\t\tMODE_OFF  = 0,\n\t\t\t\tMODE_HEAT = 1,\n\t\t\t\tMODE_COOL = 2;\n\n\t\t\tvar\n\t\t\t\twithModeOff  = !!instance.ThermostatMode.data[MODE_OFF],\n\t\t\t\twithModeHeat = !!instance.ThermostatMode.data[MODE_HEAT],\n\t\t\t\twithModeCool = !!instance.ThermostatMode.data[MODE_COOL];\n\n\t\t\tif (withModeOff && (withModeHeat || withModeCool)) {\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\tprobeType: 'thermostat_mode',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Thermostat operation')) return;\n\n\t\t\t\tvar m_vDev = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\tvar lastMode = withModeHeat ? MODE_HEAT : MODE_COOL;\n\n\t\t\t\t\t\t\t// modes are not always same in ThermostatSetPoint and in ThermostatMode, but here they are same\n\t\t\t\t\t\t\tif (withModeHeat && withModeCool && instance.ThermostatSetPoint && instance.ThermostatSetPoint.data[MODE_HEAT] && instance.ThermostatSetPoint.data[MODE_COOL]) {\n\t\t\t\t\t\t\t\tlastMode = instance.ThermostatSetPoint.data[MODE_HEAT].setVal.updateTime > instance.ThermostatSetPoint.data[MODE_COOL].setVal.updateTime ? MODE_HEAT : MODE_COOL;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tinstance.ThermostatMode.Set(lastMode);\n\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\tinstance.ThermostatMode.Set(MODE_OFF);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\n\t\t\t\tif (m_vDev) {\n\t\t\t\t\tm_vDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, this.CC[\"ThermostatMode\"], \"mode\", function(type) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\tm_vDev.set(\"metrics:level\", this.value != MODE_OFF ? \"on\" : \"off\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}, \"value\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"ThermostatSetPoint\"] === commandClassId) {\n\t\t\tvar\n\t\t\t\tMODE_OFF = 0,\n\t\t\t\tMODE_HEAT = 1,\n\t\t\t\tMODE_COOL = 2;\n\n\t\t\tvar\n\t\t\t\twithTempHeat = !!instance.ThermostatSetPoint.data[MODE_HEAT],\n\t\t\t\twithTempCool = !!instance.ThermostatSetPoint.data[MODE_COOL],\n\t\t\t\tmodes = [];\n\n\t\t\twithTempHeat && modes.push(MODE_HEAT);\n\t\t\twithTempCool && modes.push(MODE_COOL);\n\n\t\t\tvar t_vDev = [];\n\t\t\tmodes.forEach(function(mode) {\n\t\t\t\tvar cVDId = changeDevId + separ + mode;\n\t\t\t\t\n\t\t\t\tvar DH = instance.ThermostatSetPoint.data[mode],\n\t\t\t\t\t_vDevId = vDevId + separ + mode;\n\n\t\t\t\tif (!self.controller.devices.get(_vDevId)) {\n\n\t\t\t\t\tdefaults = {\n\t\t\t\t\t\tdeviceType: \"thermostat\",\n\t\t\t\t\t\tprobeType: 'thermostat_set_point',\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\tscaleTitle: DH.scaleString.value,\n\t\t\t\t\t\t\tlevel: DH.val.value,\n\t\t\t\t\t\t\tmin: DH.min && DH.min.value ? DH.min.value : (DH.scale.value === 0 ? 5 : 41),\n\t\t\t\t\t\t\tmax: DH.max && DH.max.value ? DH.max.value : (DH.scale.value === 0 ? 40 : 104),\n\t\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, \"Thermostat \" + (mode === MODE_HEAT ? \"Heat\" : \"Cool\"))) return;\n\n\t\t\t\t\tt_vDev[mode] = self.controller.devices.create({\n\t\t\t\t\t\tdeviceId: _vDevId,\n\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t// first set the setpoint temperature and then apply the mode\n\t\t\t\t\t\t\tif (command === \"exact\") {\n\t\t\t\t\t\t\t\tinstance.ThermostatSetPoint.Set(mode, args.level);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (command === \"on\" || command === \"exact\") {\n\t\t\t\t\t\t\t\tinstance.ThermostatMode && instance.ThermostatMode.data.supported.value && instance.ThermostatMode.Set(mode == MODE_HEAT ? MODE_HEAT : MODE_COOL); // modes are not always same in ThermostatSetPoint and in ThermostatMode, but here they are same\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\tinstance.ThermostatSetPoint.Get(mode);\n\t\t\t\t\t\t\t\tinstance.ThermostatMode && instance.ThermostatMode.data.supported.value && instance.ThermostatMode.Get();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (t_vDev[mode]) {\n\t\t\t\t\t\tt_vDev[mode].set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, self.CC[\"ThermostatSetPoint\"], mode + \".setVal\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\tdelete t_vDev[mode];\n\t\t\t\t\t\t\t\t\tself.controller.devices.remove(_vDevId);\n\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tt_vDev[mode].set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t} else if (this.CC[\"AlarmSensor\"] === commandClassId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: 'alarm',\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\n\t\t\t\t\tvar a_id = vDevId + separ + sensorTypeId + separ + \"A\";\n\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(a_id)) {\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\n\t\t\t\t\t\tswitch (sensorTypeId) {\n\t\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_general_purpose';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_smoke';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_co';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_coo';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_heat';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 5:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_flood';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 6:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_door';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 7:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_burglar';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 8:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_power';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 9:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_system';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 10:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_emergency';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase 11:\n\t\t\t\t\t\t\t\tdefaults.probeType = 'alarmSensor_clock';\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Alarm', cc.data[sensorTypeId].typeString.value)) return;\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar a_vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: a_id,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (a_vDev) {\n\t\t\t\t\t\t\ta_vDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, sensorTypeId + \".sensorState\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId + separ + \"A\");\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddCommandClass(nodeId, instanceId, commandClassId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"Alarm\"] === commandClassId) {\n\t\t\tif (cc.data.version.value < 3) return; // We skip old Alarm CC implementations handling only v3 (Notification)\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: 'alarm',\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(notificationTypeId) {\n\n\t\t\t\t\tnotificationTypeId = parseInt(notificationTypeId, 10);\n\n\t\t\t\t\tif (!isNaN(notificationTypeId)) {\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + notificationTypeId;\n\n\t\t\t\t\t\tfunction setProbeTypeAndIcon(defaults, notificationTypeId, eventTypeId) {\n\t\t\t\t\t\t\t// we handle only few Notification Types\n\t\t\t\t\t\t\tswitch (notificationTypeId) {\n\t\t\t\t\t\t\t\tcase 0x01: // Smoke\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm_smoke';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x02: // CO\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm_co';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x03: // CO2\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm_coo';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x04: // Heat\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'alarm_heat';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x05: // Water\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm_flood';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x06: // Door\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'door';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'alarm_door';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x07: // Home Security (Burglar)\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm_burglar';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t\t\t\tswitch (eventTypeId) {\n\t\t\t\t\t\t\t\t\t\tcase 0x07:\n\t\t\t\t\t\t\t\t\t\tcase 0x08:\n\t\t\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'motion';\n\t\t\t\t\t\t\t\t\t\t\tdefaults.probeType = 'motion';\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x08: // Power\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'alarm_power';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x09: // System\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'alarm_system';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x0a: // Emergency\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'alarm_emergency';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x0b: // Clock\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'alarm_clock';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x0c: // Appliance\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'general_purpose';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x0e: // Siren\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'siren';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x0f: // Water Valve\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'valve';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'general_purpose';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tcase 0x12: // Gas Alarm (V7)\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'gas';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'gas';\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\treturn; // skip this type\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar DOOR_OPEN = 0x16,\n\t\t\t\t\t\t    DOOR_CLOSE = 0x17,\n\t\t\t\t\t\t    PARAM_TILT = 0x01;\n\t\t\t\t\t\tif (notificationTypeId === 0x06 && cc.data[notificationTypeId][DOOR_OPEN]) { // To handle tilt and for backward compatibility due to the special name\n\t\t\t\t\t\t\tsetProbeTypeAndIcon(defaults, notificationTypeId, DOOR_OPEN);\n\n\t\t\t\t\t\t\tvar a_id = vDevId + separ + notificationTypeId + separ + 'Door' + separ + \"A\";\n\n\t\t\t\t\t\t\tif (!self.controller.devices.get(a_id)) {\n\t\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Alarm', cc.data[notificationTypeId][DOOR_OPEN].eventString.value)) return;\n\t\t\t\t\t\t\t\tvar postfix_tilt_requested = changeVDev[cVDId] && changeVDev[cVDId].tilt;\n\n\t\t\t\t\t\t\t\tvar a_vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\t\tdeviceId: a_id,\n\t\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, DOOR_OPEN);\n\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, DOOR_CLOSE);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tvar a_id_tilt = vDevId + separ + notificationTypeId + separ + 'Tilt' + separ + \"A\";\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tvar a_vDev_tilt = null;\n\t\t\t\t\t\t\t\tfunction createTiltVDev(a_id) {\n\t\t\t\t\t\t\t\t\tdefaults.metrics.icon = 'window_tilt';\n\t\t\t\t\t\t\t\t\tdefaults.probeType = 'window_tilt';\n\n\t\t\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Window Tilt')) return undefined;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\treturn self.controller.devices.create({\n\t\t\t\t\t\t\t\t\t\tdeviceId: a_id,\n\t\t\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, DOOR_OPEN);\n\t\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, DOOR_CLOSE);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (Object.keys(self.controller.getVdevInfo(a_id_tilt)).length || postfix_tilt_requested) {\n\t\t\t\t\t\t\t\t\t// add Tilt vDev if it was previously created and saved\n\t\t\t\t\t\t\t\t\ta_vDev_tilt = createTiltVDev(a_id_tilt);\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (a_vDev) {\n\t\t\t\t\t\t\t\t\ta_vDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, notificationTypeId.toString(10) + \".\" + DOOR_OPEN.toString(10), function(type) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + notificationTypeId + separ + 'Door' + separ + \"A\");\n\t\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + notificationTypeId + separ + 'Tilt' + separ + \"A\");\n\t\t\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (this.status.value) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (this.parameters.value[0] == PARAM_TILT) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!a_vDev_tilt) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// create the Tilt vDev on the fly\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev_tilt = createTiltVDev(a_id_tilt);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (a_vDev_tilt) a_vDev_tilt.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (a_vDev_tilt) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev_tilt.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar AC_DISCONNECTED = 0x02,\n\t\t\t\t\t\t    AC_RECONNECTED = 0x03;\n\t\t\t\t\t\tif (notificationTypeId === 0x08 && cc.data[notificationTypeId][AC_DISCONNECTED]) { // For backward compatibility due to the special name\n\t\t\t\t\t\t\tsetProbeTypeAndIcon(defaults, notificationTypeId, AC_DISCONNECTED);\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar a_id = vDevId + separ + notificationTypeId + separ + 'AC' + separ + \"A\";\n\n\t\t\t\t\t\t\tif (!self.controller.devices.get(a_id)) {\n\t\t\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Alarm', cc.data[notificationTypeId][AC_DISCONNECTED].eventString.value)) return;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tvar a_vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\t\t\tdeviceId: a_id,\n\t\t\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, AC_DISCONNECTED);\n\t\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, AC_RECONNECTED);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif (a_vDev) {\n\t\t\t\t\t\t\t\t\t\ta_vDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, notificationTypeId.toString(10) + \".\" + AC_DISCONNECTED.toString(10), function(type) {\n\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + notificationTypeId + separ + 'Power' + separ + \"A\");\n\t\t\t\t\t\t\t\t\t\t\t\t} else if ((!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"]))) {\n\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", this.status.value? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tObject.keys(cc.data[notificationTypeId]).forEach(function(eventTypeId) {\n\t\t\t\t\t\t\teventTypeId = parseInt(eventTypeId, 10);\n\t\t                                        if (!isNaN(eventTypeId)) {\n\t\t\t\t\t\t\t\tif (notificationTypeId === 0x06 && eventTypeId === DOOR_OPEN) return; // it was handled above                         \n\t\t\t\t\t\t\t\tif (notificationTypeId === 0x08 && eventTypeId === AC_DISCONNECTED) return; // it was handled above\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tvar a_id = vDevId + separ + notificationTypeId + separ + eventTypeId + separ + \"A\";\n\n\t\t\t\t\t\t\t\tif (!isNaN(eventTypeId) && !self.controller.devices.get(a_id)) {\n\t\t\t\t\t\t\t\t\tvar cVDId = changeDevId + separ + notificationTypeId + separ + eventTypeId;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tsetProbeTypeAndIcon(defaults, notificationTypeId, eventTypeId);\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tvar isState = true; // default to support older behaviour\n\t\t\t\t\t\t\t\t\tif (cc.data[notificationTypeId][eventTypeId].isState) {\n\t\t\t\t\t\t\t\t\t\tisState = cc.data[notificationTypeId][eventTypeId].isState.value;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tdefaults.deviceType = isState ? \"sensorBinary\" : \"toggleButton\";\n\t\t\t\t\t\t\t\t\tdefaults.visibility = isState ? true : false;\n\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Alarm', cc.data[notificationTypeId][eventTypeId].eventString.value)) return;\n\n\t\t\t\t\t\t\t\t\tvar a_vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\t\t\tdeviceId: a_id,\n\t\t\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\t\t\t\tcc.Get(0, notificationTypeId, eventTypeId);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t\t\tif (a_vDev) {\n\t\t\t\t\t\t\t\t\t\tif (isState && changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\t\t\t\ta_vDev.__emulateOff_timeout = parseInt(changeVDev[cVDId].emulateOff, 10);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\ta_vDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, notificationTypeId.toString(10) + \".\" + eventTypeId.toString(10), function(type) {\n\t\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + notificationTypeId + separ + eventTypeId + separ + \"A\");\n\t\t\t\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (a_vDev.__emulateOff_timeout) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (this.status.value) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (a_vDev.get(\"metrics:level\") !== \"on\" || !a_vDev.__emulateOff_timer) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.__emulateOff_timer && clearTimeout(a_vDev.__emulateOff_timer);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.__emulateOff_timer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.__emulateOff_timer = 0;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}, a_vDev.__emulateOff_timeout);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} // off from the sensor is ignored\n\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", this.status.value ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\tif (isState && changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\t\t\t\t// on start we need to set it to off\n\t\t\t\t\t\t\t\t\t\t\tif (a_vDev.get(\"metrics:level\") === \"on\") {\n\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// create Notification On/Off widget if requested by postfix\n\t\t\t\t\t\t\tvar e_id = vDevId + separ + notificationTypeId + separ + 'Enabled';\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar e_defaults = {\n\t\t\t\t\t\t\t\tdeviceType: 'switchBinary',\n\t\t\t\t\t\t\t\tprobeType: '',\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ticon: 'alarm',\n\t\t\t\t\t\t\t\t\tlevel: 'off',\n\t\t\t\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (!self.controller.devices.get(e_id) && changeVDev[cVDId] && changeVDev[cVDId].notificationStatus) {\n\t\t\t\t\t\t\t\tif (!self.applyPostfix(e_defaults, changeVDev[cVDId], nodeId, instanceId, smartStartEntryPreset, 'Alarm', cc.data[notificationTypeId].typeString.value)) return;\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tvar a_vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\t\tdeviceId: e_id,\n\t\t\t\t\t\t\t\t\tdefaults: e_defaults,\n\t\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\t\tif (command === \"on\" || command === \"off\") {\n\t\t\t\t\t\t\t\t\t\t\tcc.Set(notificationTypeId, command === \"on\" ? true : false);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\t\t\tcc.Get(notificationTypeId, 0);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tif (a_vDev) {\n\t\t\t\t\t\t\t\t\ta_vDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, notificationTypeId.toString(10), function(type) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(e_id);\n\t\t\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\t\t\ta_vDev.set(\"metrics:level\", this.status.value ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddCommandClass(nodeId, instanceId, commandClassId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"CentralScene\"] === commandClassId) {\n\n\t\t\tvar devId = vDevId + separ + 'DS';\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorDiscrete',\n\t\t\t\tprobeType: 'control',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'Control',\n\t\t\t\t\ticon: 'gesture',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\tstate: '',\n\t\t\t\t\t/* GESTURES (state):\n\t\t\t\t\t * hold,\n\t\t\t\t\t * press / tap (cnt),\n\t\t\t\t\t * release,\n\t\t\t\t\t * swipe_up,\n\t\t\t\t\t * swipe_down,\n\t\t\t\t\t * swipe_left,\n\t\t\t\t\t * swipe_right,\n\t\t\t\t\t * swipe_top_left_to_bottom_right,\n\t\t\t\t\t * swipe_top_right_to_bottom_left,\n\t\t\t\t\t * swipe_bottom_left_to_top_right,\n\t\t\t\t\t * swipe_bottom_right_to_top_left\n\t\t\t\t\t */\n\t\t\t\t\tcurrentScene: '',\n\t\t\t\t\tdiscreteStates: {},\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, instanceId, smartStartEntryPreset, 'Control')) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: devId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\n\t\t\t// disable value set on z-way startup\n\t\t\tvar startup = true;\n\n\t\t\tsetTimeout(function() {\n\t\t\t\tstartup = false;\n\t\t\t}, 1000);\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"currentScene\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\t\t\t\t\t\t\tself.controller.devices.remove(devId);\n\t\t\t\t\t\t} else if (!startup && !(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t// output curScene + keyAttr or ''\n\t\t\t\t\t\t\tvar cS = cc.data['currentScene'].value && !!cc.data['currentScene'].value ? cc.data['currentScene'].value : 0,\n\t\t\t\t\t\t\t\tmC = cc.data['maxScenes'].value && !!cc.data['maxScenes'].value ? cc.data['maxScenes'].value : 0,\n\t\t\t\t\t\t\t\tkA = cc.data['keyAttribute'].value && !!cc.data['keyAttribute'].value ? cc.data['keyAttribute'].value : 0,\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\t * CentralScene v3:\n\t\t\t\t\t\t\t\t *\n\t\t\t\t\t\t\t\t * 0x00 Key Pressed 1 time\n\t\t\t\t\t\t\t\t * 0x01 Key Released\n\t\t\t\t\t\t\t\t * 0x02 Key Held Down\n\t\t\t\t\t\t\t\t * 0x03 Key Pressed 2 times\n\t\t\t\t\t\t\t\t * 0x04 Key Pressed 3 times\n\t\t\t\t\t\t\t\t * 0x05 Key Pressed 4 times\n\t\t\t\t\t\t\t\t * 0x06 Key Pressed 5 times\n\t\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t\tkaCnt = kA > 0x02 ? kA - 0x01 : 0x01,\n\t\t\t\t\t\t\t\tcL = cS.toString() + kA.toString(),\n\t\t\t\t\t\t\t\tdS = !_.isEmpty(defaults.metrics.discreteStates) && defaults.metrics.discreteStates[cL] ? defaults.metrics.discreteStates[cL] : undefined,\n\t\t\t\t\t\t\t\tst = '',\n\t\t\t\t\t\t\t\tcnt = dS && dS['cnt'] ? dS['cnt'] : kaCnt,\n\t\t\t\t\t\t\t\ttype = dS && dS['type'] ? dS['type'] : 'B',\n\t\t\t\t\t\t\t\tsetAction = function() {\n\t\t\t\t\t\t\t\t\tswitch (kA) {\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tst = dS && dS['action'] ? dS['action'] : 'release';\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\tst = dS && dS['action'] ? dS['action'] : 'hold';\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tst = dS && dS['action'] ? dS['action'] : 'press';\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t};\n\n\n\t\t\t\t\t\t\tsetAction();\n\n\t\t\t\t\t\t\tvDev.set(\"metrics:state\", st);\n\t\t\t\t\t\t\tvDev.set(\"metrics:currentScene\", cS);\n\t\t\t\t\t\t\tvDev.set(\"metrics:keyAttribute\", kA);\n\t\t\t\t\t\t\tvDev.set(\"metrics:maxScenes\", mC);\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", cL);\n\t\t\t\t\t\t\tvDev.set(\"metrics:cnt\", cnt);\n\t\t\t\t\t\t\tvDev.set(\"metrics:type\", type);\n\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\tvDev.set(\"metrics\", {\n\t\t\t\t\t\t\t\tstate: st,\n\t\t\t\t\t\t\t\tcurrentScene: cS,\n\t\t\t\t\t\t\t\tkeyAttribute: kA,\n\t\t\t\t\t\t\t\tmaxScenes: mC,\n\t\t\t\t\t\t\t\tlevel: cL,\n\t\t\t\t\t\t\t\tcnt: cnt,\n\t\t\t\t\t\t\t\ttype: type\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"Configuration\"] === commandClassId) {\n\t\t\tif (changeVDev[changeDevId]) {\n\t\t\t\tObject.keys(changeVDev[changeDevId]['configVDev']).forEach(function(param) {\n\t\t\t\t\tvar vDevIdParam = vDevId + '-' + param,\n\t\t\t\t\t    vDevConfig = changeVDev[changeDevId]['configVDev'][param];\n\t\t\t\t\t\n\t\t\t\t\tif (!self.controller.devices.get(vDevIdParam)) {\n\t\t\t\t\t\tvar icon, probeType;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (vDevConfig.type == \"switchBinary\") {\n\t\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\t\t\t\tprobeType: \"switch\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: vDevConfig.title,\n\t\t\t\t\t\t\t\t\ticon: \"switch\",\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (vDevConfig.type == \"switchMultilevel\") {\n\t\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\t\t\tprobeType: \"multilevel\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: vDevConfig.title,\n\t\t\t\t\t\t\t\t\ticon: \"multilevel\",\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.addNotification(\"error\", \"Unknown vDev type for config parameter \" + param, \"module\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\teval('vDevConfig.v2p_script = function(command, args, vdev) { \"use strict\";' + vDevConfig.v2p + '};');\n\t\t\t\t\t\teval('vDevConfig.p2v_script = function(value) { \"use strict\";' + vDevConfig.p2v + '};');\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!cc.data[param] || !cc.data[param].size.value) { // make sure the size of the parameter is known, so Set works\n\t\t\t\t\t\t\tcc.Get(param);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevIdParam,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t\tif (\"update\" === command || !cc.data[param] || !cc.data[param].size.value) { // make sure the size of the parameter is known, so Set works\n\t\t\t\t\t\t\t\t\tcc.Get(param);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvar val = vDevConfig.v2p_script(command, args, vDev);\n\t\t\t\t\t\t\t\t\tif (val !== null && val !== undefined) {\n\t\t\t\t\t\t\t\t\t\tcc.Set(param, val);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zway.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, param + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevIdParam);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", vDevConfig.p2v_script(this.value));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (this.CC[\"DeviceResetLocally\"] === commandClassId) {\n\t\t\tself.dataBind(self.gateDataBinding, self.zway, nodeId, instanceId, commandClassId, \"reset\", function(type) {\n\t\t\t\tif (this.value) {\n\t\t\t\t\tvar langFile = self.loadModuleLang();\n\t\t\t\t\tself.addNotification(\"error\", langFile.err_reset + nodeId, \"connection\");\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t} catch (e) {\n\t\tvar langFile = this.loadModuleLang(),\n\t\t\tvalues = nodeId + \"-\" + instanceId + \"-\" + commandClassId + \": \" + e.toString();\n\n\t\tthis.addNotification(\"error\", langFile.err_dev_create + values, \"core\");\n\t\tconsole.log(e.stack);\n\t}\n};\n\nZWave.prototype.parseDelCommandClass = function(nodeId, instanceId, commandClassId) {\n\tnodeId = parseInt(nodeId, 10);\n\tinstanceId = parseInt(instanceId, 10);\n\tcommandClassId = parseInt(commandClassId, 10);\n\n\tvar self = this,\n\t\tsepar = \"-\",\n\t\tvDevIdPrefix = \"ZWayVDev_\" + this.config.name + \"_\",\n\t\tvDevIdNI = nodeId + separ + instanceId,\n\t\tvDevIdC = commandClassId,\n\t\tvDevId = vDevIdPrefix + vDevIdNI + separ + vDevIdC;\n\n\tthis.controller.devices.remove(vDevId);\n};\n\n// ----------------- RSSI functions -----------------\n\nZWave.prototype.lastRSSIData = function() {\n\tvar rssi = this.zway.controller.data.statistics.backgroundRSSI;\n\n\tfunction valueToRSSI(rssi) {\n\t\t// From z-way/ZDefsPublic.h\n\t\tvar\n\t\t\tRSSI_VALID_LOWEST        = -100, // Valid values are in range from -128 dBm, but actual sensitivity is -100 dBm\n\t\t\tRSSI_VALID_HIGHEST       = 124, // to -32 dBm\n\t\t\tRSSI_BELOW_SENSITIVITY   = 125, // No signal detected. The RSSI is too low to measure precisely\n\t\t\tRSSI_MAX_POWER_SATURATED = 126, // Receiver saturated. RSSI too high to measure precisely\n\t\t\tRSSI_NOT_AVAILABLE       = 127; // RSSI measurement not available\n\t\t\n\t\tswitch (rssi) {\n\t\t\tcase RSSI_BELOW_SENSITIVITY:\n\t\t\t\treturn RSSI_VALID_LOWEST - 1;\n\t\t\tcase RSSI_MAX_POWER_SATURATED:\n\t\t\t\treturn RSSI_VALID_HIGHEST + 1;\n\t\t\tcase RSSI_NOT_AVAILABLE:\n\t\t\t\treturn null;\n\t\t\tdefault:\n\t\t\t\treturn rssi - 256;\n\t\t}\n\t}\n\t\n\treturn {\n\t\t\"time\": Math.round(Date.now() / 1000),\n\t\t\"channel1\": valueToRSSI(rssi.channel1.value),\n\t\t\"channel2\": valueToRSSI(rssi.channel2.value),\n\t\t\"channel3\": valueToRSSI(rssi.channel3.value)\n\t};\n};\n\nZWave.prototype.updateRSSIData = function(callback) {\n\tvar self = this;\n\n\tthis.zway.GetBackgroundRSSI(function() {\n\t\tif (callback) {\n\t\t\tcallback(self.lastRSSIData());\n\t\t}\n\t});\n};\n\nZWave.prototype.getDSKProvisioningList = function() {\n\treturn this.zway.controller.data.smartStart.dskProvisioningList.value || [];\n};\n\n\nZWave.prototype.saveDSKProvisioningList = function(dskProvisioningList) {\n\tthis.zway.controller.data.smartStart.dskProvisioningList.value = dskProvisioningList;\n};\n\nZWave.prototype.nodeNameByType = function (nodeId, nodeData) {\n\n\tvar name = 'Device ' + nodeId,\n\t    type = '',\n\t    node = nodeData;\n\n\tif (node){\n\t\tvar isListening = node.isListening.value,\n\t\t    isFLiRS = !isListening && (node.sensor250.value || node.sensor1000.value),\n\t\t    hasWakeup = !isListening && !node.sensor250.value && !node.sensor1000.value;\n\n\t\tif (hasWakeup || isFLiRS) {\n\t\t\ttype = 'Battery';\n\t\t} else if (isListening) {\n\t\t\ttype = 'Mains';\n\t\t}\n\t\tname = type + name;\n\t}\n\n\treturn name;\n};\n"
  },
  {
    "path": "modules/ZWave/lang/de.json",
    "content": "{\n\t\"m_title\":\"Z-Wave Netzwerksteuerung\",\n\t\"m_descr\":\"Diese App bildet die Information zu Ihrem Z-Wave Netzwerk in Ihrer UI ab. Infolgedessen muss dieses während der ganzen Zeit aktiviert sein, in welcher Sie mit dem Z-Wave Geräte arbeiten wollen. In der Verwendung mit diesem Modul kann sehr viel falsch gemacht werden, daher lassen Sie es unberührt, solange es nicht wirklich benötigt wird.\",\n\t\"l_port\":\"Serieller Port der verwendet werden soll:\",\n\t\"l_speed\":\"Serial Port speed in bits/s (automatically updated on speed change)\",\n\t\"l_name\":\"Interner Name\",\n\t\"h_name\":\"Dies sollte ein valider JS key String sein. Achtung! Nur ändern, wenn Sie wissen was Sie tun.\",\n\t\"rl_enableAPI\":\"Aktiviere Z-Wave API\",\n\t\"h_enableAPI\":\"Erlaubt HTTP anfragen zu /ZWaveAPI/* and /ZWave/&lt;internal zway name&gt;/*\",\n\t\"rl_publicAPI\":\"Aktiviere öffentlichen Zugang zur Z-Wave API\",\n\t\"h_publicAPI\":\"Keine authentifiziereung zur Z-Wave API notwendig.\",\n\t\"rl_createVDev\":\"Erzeuge virtuelle Geräte in der Home Automation Engine\",\n\t\"h_createVDev\":\"Wenn diese Einstellung nicht aktiv ist, sind Z-Wave Geräte nur in der Expert UI und über die Z-Wave API sicht- bzw. benutzbar.\",\n\t\"l_enablePacketLog\": \"Packet log\",\n\t\"h_enablePacketLog\":\"Track and save packet log in a file for future analysis. Disable completelly in huge network for better CPU performance. Enable but don't save on slow SD cards since save can hang the server for up to 30 seconds. Required for network diagnostics!\",\n\t\"l_config\":\"Pfad zum Ordner /config\",\n\t\"l_translations\":\"Pfad zum Ordner /dictionaries\",\n\t\"l_zddx\":\"Pfad zur ZDDX Datenbank\",\n\t\"h_change_sth\":\"Achtung! Nur ändern, wenn Sie wissen was Sie tun.\",\n\t\"err_binding_start\":\"Fehler beim Starten der Z-Wave Bindung: \",\n\t\"err_connct\":\"Verbindung verloren zur Z-Wave Geräte-ID: \",\n\t\"err_reset\": \"Benutzer zurückgesetzt Z-Wave-Gerät ID: \",\n\t\"dev_btl\":\"Z-Wave Geräte-ID ist wieder verbunden: \",\n\t\"err_dev_create\":\"vDev konnte mit den folgenden Daten nicht erstellt werden: \",\n\t\"reorg_title\":\"Network reorganization\",\n\t\"reorg_node_title\": \"Node #\",\n\t\"reorg_start\": \"Network reorganization start\",\n\t\"reorg_start_mains\": \"Starting neighbours discovery for mains powered devices\",\n\t\"reorg_start_flirs\": \"Starting neighbours discovery for FLiRS devices\",\n\t\"reorg_start_battery\": \"Starting neighbours discovery for battery devices\",\n\t\"reorg_finished\": \"Network discovery finished\",\n\t\"reorg_node_done\": \"Neighbours update done\",\n\t\"reorg_node_failed\": \"Neighbours update failed\",\n\t\"reorg_node_start\": \"Starting neighbours update\",\n\t\"reorg_node_skip\": \"Skipping neighbours update for a failed device\",\n\t\"main\":\"strombetriebenen Geräte\",\n\t\"flirs\":\"FLiRS Geräte\",\n\t\"battery\":\"batteriebetriebenen Geräte\"\n}"
  },
  {
    "path": "modules/ZWave/lang/en.json",
    "content": "{\n\t\"m_title\":\"Z-Wave Network Access\",\n\t\"m_descr\":\"Z-Way controls one Z-Wave network with up to 232 devices. This app will combine multiple Z-Way entities into one User Interface. Essentially the app is mapping the data of another Z-Way powered Gateway into your gateway. The elements are displayed and can be used like the local ones. Please note that the function of the second gateway remains untouched. This means that this second gateway will not see the elements for your first gateway but can control and access their own elements without and further restrictions: <br><br> Settings: <br><ul><li>You need to set the IP address of the Remote Box including the port number. </li><li>You need to define the polling interval. Once second in a quite good choice.</li> <li>You need to manage the remove device to be included into you UI.</li></ul>\",\n\t\"l_port\":\"Serial port to Z-Wave dongle\",\n\t\"l_speed\":\"Serial port speed in bits/s (automatically updated on speed change)\",\n\t\"l_name\":\"Internal name\",\n\t\"h_name\":\"Should be a valid JS key string. Don't change unless you know what you are doing\",\n\t\"rl_enableAPI\":\"Enable Z-Wave API\",\n\t\"h_enableAPI\":\"Handler HTTP requests to /ZWaveAPI/* and /ZWave/&lt;internal zway name&gt;/*\",\n\t\"rl_publicAPI\":\"Allow public access to Z-Wave API\",\n\t\"h_publicAPI\":\"Do not ask for authentication to access Z-Wave API\",\n\t\"rl_createVDev\":\"Create virtual devices in Home Automation engine\",\n\t\"h_createVDev\":\"Without this Z-Wave devices will be visible only in Expert UI and via Z-Wave API\",\n\t\"l_enablePacketLog\":\"Packet log\",\n\t\"h_enablePacketLog\":\"Track and save packet log in a file for future analysis. Disable completelly in huge network for better CPU performance. Enable but don't save on slow SD cards since save can hang the server for up to 30 seconds. Required for network diagnostics!\",\n\t\"l_config\":\"Path to config folder\",\n\t\"l_translations\":\"Path to dictionaries folder\",\n\t\"l_zddx\":\"Path to ZDDX database\",\n\t\"h_change_sth\":\"Don't change unless you know what you are doing\",\n\t\"err_binding_start\":\"Cannot start Z-Wave binding: \",\n\t\"err_connct\":\"Connection lost to Z-Wave device ID: \",\n\t\"err_reset\": \"User reset to factory defaults Z-Wave device ID: \",\n\t\"dev_btl\":\"Z-Wave device ID is back to life: \",\n\t\"err_dev_create\":\"Cannot create vDev based on: \",\n\t\"reorg_title\":\"Network reorganization\",\n\t\"reorg_node_title\": \"Node #\",\n\t\"reorg_start\": \"Network reorganization start\",\n\t\"reorg_start_mains\": \"Starting neighbours discovery for mains powered devices\",\n\t\"reorg_start_flirs\": \"Starting neighbours discovery for FLiRS devices\",\n\t\"reorg_start_battery\": \"Starting neighbours discovery for battery devices\",\n\t\"reorg_finished\": \"Network discovery finished\",\n\t\"reorg_node_done\": \"Neighbours update done\",\n\t\"reorg_node_failed\": \"Neighbours update failed\",\n\t\"reorg_node_start\": \"Starting neighbours update\",\n\t\"reorg_node_skip\": \"Skipping neighbours update for a failed device\",\n\t\"main\":\"main powered devices\",\n\t\"flirs\":\"FLiRS devices\",\n\t\"battery\":\"battery powered devices\"\n}"
  },
  {
    "path": "modules/ZWave/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Z-Wave движок\",\n\t\"m_descr\":\"Активация Z-Wave движка.\",\n\t\"l_port\":\"Порт для Z-Wave платы/стика\",\n\t\"l_speed\":\"Скорость порта в бит/сек (автоматически обновляется при смене скорости)\",\n\t\"l_name\":\"Внутреннее имя\",\n\t\"h_name\":\"Должно быть допустимой JS строкой. Не изменяйте, если не знаете, что делаете\",\n\t\"rl_enableAPI\":\"Включить Z-Wave API\",\n\t\"h_enableAPI\":\"Обрабатывать HTTP запросы /ZWaveAPI/* и /ZWave/&lt;внутреннее имя zway&gt;/*\",\n\t\"rl_publicAPI\":\"Разрешить доступ к Z-Wave API без аутентификации\",\n\t\"h_publicAPI\":\"Не требовать аутентификации при обработке запросов к Z-Wave API\",\n\t\"rl_createVDev\":\"Создавать виртуальные устройства домашней автоматизации\",\n\t\"h_createVDev\":\"Если отключить, то Z-Wave устройства будут видны только в Экспертном интерфейсе и через Z-Wave API\",\n\t\"l_enablePacketLog\":\"Включить лог пакетов\",\n\t\"h_enablePacketLog\":\"Вести лог и сохранять лог пакетов в файл для дальнейшего анализа. Отключите в больших сетях для лучшей производительности. Включите, но без сохранения, при работе на медленной SD карте, так как это может подвешивать сервер на время до 30 секунд. Необходимо для диагностики сети!\",\n\t\"l_config\":\"Путь к папке с настройками config/\",\n\t\"l_translations\":\"Путь к папке с переводами\",\n\t\"l_zddx\":\"Путь к базе устройств ZDDX\",\n\t\"h_change_sth\":\"Не изменяйте, если не знаете, что делаете\",\n\t\"err_binding_start\":\"Невозможно запустить Z-Wave движок: \",\n\t\"err_connct\":\"Соединение потеряно с Z-Wave устройством ID: \",\n\t\"err_reset\": \"Пользователь сбросил к заводским настройкам устройство ID: \",\n\t\"dev_btl\":\"Z-Wave устройство ID снова доступно: \",\n\t\"err_dev_create\":\"Не возможно создать vDev основанное на: \",\n\t\"reorg_title\":\"Реорганизация сети\",\n\t\"reorg_node_title\": \"Устройство #\",\n\t\"reorg_start\": \"Реорганизация сети началась\",\n\t\"reorg_start_mains\": \"Обновление соседей для устройств на постоянном питании\",\n\t\"reorg_start_flirs\": \"Обновление соседей для FLiRS устройств\",\n\t\"reorg_start_battery\": \"Обновление соседей для устройств на батарейках\",\n\t\"reorg_finished\": \"Реорганизация сети завершена\",\n\t\"reorg_node_done\": \"Обновление соседей успешно\",\n\t\"reorg_node_failed\": \"Ошибка обновления соседей\",\n\t\"reorg_node_start\": \"Начато обновление соседей\",\n\t\"reorg_node_skip\": \"Пропускаю обновление соседей сломанного устройства\",\n\t\"main\":\"main powered devices\",\n\t\"flirs\":\"FLiRS devices\",\n\t\"battery\":\"battery powered devices\"\n}"
  },
  {
    "path": "modules/ZWave/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"peripherals\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://razberry.z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"ZWave\",\n\t\"version\": \"3.0.1\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\t\"type\": \"git\",\n\t\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"name\": \"zway\",\n\t\t\"port\": \"/dev/ttyACM0\",\n\t\t\"speed\": 115200,\n\t\t\"enableAPI\": true,\n\t\t\"publicAPI\": false,\n\t\t\"createVDev\": true,\n\t\t\"enablePacketLog\": \"enable\",\n\t\t\"config\": \"config\",\n\t\t\"translations\": \"translations\",\n\t\t\"ZDDX\": \"ZDDX\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"port\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"speed\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [ 1200, 2400, 1800, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, 921600 ],\n\t\t\t\t\"default\": 115200\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"enablePacketLog\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [ \"enable\", \"runtime\", \"disable\" ],\n\t\t\t\t\"default\": \"enable\"\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"translations\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"ZDDX\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"port\": {\n\t\t\t\t\"label\": \"__l_port__\"\n\t\t\t},\n\t\t\t\"speed\": {\n\t\t\t\t\"label\": \"__l_speed__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [ \"1200 bits/s\", \"2400 bits/s\", \"1800 bits/s\", \"4800 bits/s\", \"7200 bits/s\", \"9600 bits/s\", \"14400 bits/s\", \"19200 bits/s\", \"28800 bits/s\", \"38400 bits/s\", \"57600 bits/s\", \"115200 bits/s\", \"230400 bits/s\", \"460800 bits/s\", \"921600 bits/s\" ],\n\t\t\t\t\"sort\": false\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"label\": \"__l_name__\",\n\t\t\t\t\"helper\": \"__h_name__\"\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_enableAPI__\",\n\t\t\t\t\"helper\": \"__h_enableAPI__\"\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_publicAPI__\",\n\t\t\t\t\"helper\": \"__h_publicAPI__\"\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_createVDev__\",\n\t\t\t\t\"helper\": \"__h_createVDev__\"\n\t\t\t},\n\t\t\t\"enablePacketLog\": {\n\t\t\t\t\"label\": \"__l_enablePacketLog__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [ \"Enable and save in file\", \"Enable, but don't save\", \"Disable\" ],\n\t\t\t\t\"helper\": \"__h_enablePacketLog__\"\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_config__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t},\n\t\t\t\"translations\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_translations__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t},\n\t\t\t\"ZDDX\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_zddx__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modules/ZWave/postfix.json",
    "content": "{\n\t\"last_update\": 1548667483,\n\t\"fixes\": [{\n\t\t\"id\": \"3\",\n\t\t\"p_id\": \"277.256.259\",\n\t\t\"p_sku\": \"POPE009204\",\n\t\t\"product\": \"POPP KFOB\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"renameNode,POPP KFOB\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\",\n\t\t\t\"rename,0-91,POPP KFOB\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"add scene support\",\n\t\t\"created\": \"2017-01-16 15:00:54\"\n\t}, {\n\t\t\"id\": \"5\",\n\t\t\"p_id\": \"316.2.2\",\n\t\t\"p_sku\": \"PHI_PST02-1A-RU\",\n\t\t\"product\": \"Philio PST02-A RU\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"renameNode,Philio PAT021A\",\n\t\t\t\"setConfig(0,7,22,1);\",\n\t\t\t\"setCCData(0,132,'security','value',false);\",\n\t\t\t\"setConfig(0,11,0,1)\",\n\t\t\t\"setConfig(0,12,1,1)\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,20,10,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-06 13:45:10\",\n\t\t\"author\": \"NIRAIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2017-09-06 13:45:10\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name, configuration and set wakeup to unsecureset Parameter 11, 12, 13, 20 \",\n\t\t\"created\": \"2017-09-06 13:45:10\"\n\t}, {\n\t\t\"id\": \"6\",\n\t\t\"p_id\": \"271.3074.4098\",\n\t\t\"p_sku\": \"FIBEFGSD-002\",\n\t\t\"product\": \"Fibaro Smoke Sensor FGSD-002\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-156\",\n\t\t\t\"noVDev,0-113-1-3\",\n\t\t\t\"noVDev,0-113-7\",\n\t\t\t\"noVDev,0-113-8\",\n\t\t\t\"noVDev,0-113-9\",\n\t\t\t\"rename,0-113-4-2,Heat Alarm\",\n\t\t\t\"rename,0-113-1-2,Smoke Alarm\",\n\t\t\t\"renameNode,Fibaro Smoke Sensor FGSD-002\",\n\t\t\t\"icon,0-113-1-2,smoke\",\n\t\t\t\"icon,0-113-4-2,smoke\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"hide Alarm and AlarmSensor widgets, rename widgets and nodechange icons\",\n\t\t\"created\": \"2016-10-25 12:05:15\"\n\t}, {\n\t\t\"id\": \"23\",\n\t\t\"p_id\": \"271.2816.4097\",\n\t\t\"p_sku\": \"FIB_FGFS-101\",\n\t\t\"product\": \"Fibaro Flood Sensor FGFS-101\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Flood Sensor FGFS-101\",\n\t\t\t\"noVDev,0-156-0\",\n\t\t\t\"noVDev,1-48-1\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename node, don't create sensors\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"25\",\n\t\t\"p_id\": \"357.2.2\",\n\t\t\"p_sku\": \"NODECRC360X\",\n\t\t\"product\": \"NodOn Soft Remote\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"renameNode,NodOn Soft Remote\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\",\n\t\t\t\"rename,0-91,NodOn Soft Remote\"\n\t\t],\n\t\t\"author_last_update\": \"2016-12-01 12:07:16\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"NIRRS\",\n\t\t\"tester_last_update\": \"2016-12-01 12:07:16\",\n\t\t\"commentary\": \"NIR: add scene support, rename node; RS: discreteState\",\n\t\t\"created\": \"2017-01-16 15:01:43\"\n\t}, {\n\t\t\"id\": \"28\",\n\t\t\"p_id\": \"357.2.1\",\n\t\t\"p_sku\": \"NODECRC3100\",\n\t\t\"product\": \"NodOn Octan Remote\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"renameNode,NodOn Octan Remote\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\",\n\t\t\t\"rename,0-91,NodOn Octan Remote\"\n\t\t],\n\t\t\"author_last_update\": \"2016-12-14 15:49:07\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"NIRRS\",\n\t\t\"tester_last_update\": \"2016-12-14 15:49:07\",\n\t\t\"commentary\": \"NIR: add scene support, rename node; RS: discreteState\",\n\t\t\"created\": \"2017-01-16 15:03:55\"\n\t}, {\n\t\t\"id\": \"29\",\n\t\t\"p_id\": \"357.2.3\",\n\t\t\"p_sku\": \"NODECWS3101\",\n\t\t\"product\": \"NodOn Wall Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"renameNode,NodOn Wall Switch\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\",\n\t\t\t\"rename,0-91,NodOn Wall Switch\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"add scene support, rename node\",\n\t\t\"created\": \"2017-01-16 15:08:39\"\n\t}, {\n\t\t\"id\": \"30\",\n\t\t\"p_id\": \"2.3.32784\",\n\t\t\"p_sku\": \"DAN_RS-Z\",\n\t\t\"product\": \"Danfoss Temperature Room Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,1,'S');\",\n\t\t\t\"renameNode,Danfoss Temperature Room Sensor\",\n\t\t\t\"if (commandClassId==0x72 && self.zway.devices[nodeId].ThermostatSetPoint.data.version!=2) { self.zway.devices[nodeId].ThermostatSetPoint.data.version = 2; self.zway.devices[nodeId].ThermostatSetPoint.Interview(); }\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"add scene support, rename node, set ThermostatSetPoint version to 2\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"34\",\n\t\t\"p_id\": \"134.2.89\",\n\t\t\"p_sku\": \"AEO_ZW089\",\n\t\t\"product\": \"Aeotec Recessed Door Sensor G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,121,16,4);\",\n\t\t\t\"noVDev,0-113\",\n\t\t\t\"rename,0-48-1,Door/Window Sensor\",\n\t\t\t\"renameNode,Aeotec Recessed Door Sensor G5\",\n\t\t\t\"icon,0-48-1,door\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR,SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"change config,don't create Alarm devices,rename 0-48-1,rename nodechange icon\",\n\t\t\"created\": \"2016-10-26 13:59:33\"\n\t}, {\n\t\t\"id\": \"35\",\n\t\t\"p_id\": \"264.2.13\",\n\t\t\"p_sku\": \"D Link Batterie Motion Sensor\",\n\t\t\"product\": \"D-Link Batterie Motion Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"noVDev,0-48-8\",\n\t\t\t\"setConfig(0,7,30,1);\",\n\t\t\t\"setCCData(0,132,'security','value',false);\",\n\t\t\t\"renameNode,D-Link Motion Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create devices,change config,set wakeup to unsecure,change node name\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"36\",\n\t\t\"p_id\": \"340.256.259\",\n\t\t\"p_sku\": \"POPE009204\",\n\t\t\"product\": \"POPP KFOB\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"renameNode,POPP KFOB\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"add scene support, rename node\",\n\t\t\"created\": \"2016-10-05 08:49:38\"\n\t}, {\n\t\t\"id\": \"40\",\n\t\t\"p_id\": \"340.4.4\",\n\t\t\"p_sku\": \"POPE009402\",\n\t\t\"product\": \"Popp 10 year smoke detector with siren\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"renameNode,Popp 10Y Smoke Detector/Siren\",\n\t\t\t\"rename,0-48-8,Tamper\",\n\t\t\t\"icon,0-48-8,tamper\",\n\t\t\t\"rename,0-48-2,Smoke Alarm\",\n\t\t\t\"rename,0-37,Siren\"\n\t\t],\n\t\t\"author_last_update\": \"2017-04-28 09:58:03\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"SPRS\",\n\t\t\"tester_last_update\": \"2017-04-28 09:58:03\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name, rename devices,change icon\",\n\t\t\"created\": \"2017-07-11 13:37:02\"\n\t}, {\n\t\t\"id\": \"41\",\n\t\t\"p_id\": \"271.2049.4097\",\n\t\t\"p_sku\": \"FIBEFGMS-001-ZW5\",\n\t\t\"product\": \"Fibaro PIR Gen 5 (Magic Eye)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-156\",\n\t\t\t\"noVDev,0-48\",\n\t\t\t\"noVDev,0-49-25\",\n\t\t\t\"noVDev,0-49-52\",\n\t\t\t\"noVDev,0-49-53\",\n\t\t\t\"noVDev,0-49-54\",\n\t\t\t\"noVDev,0-113-7-0\",\n\t\t\t\"rename,0-113-7-8,PIR\",\n\t\t\t\"icon,0-113-7-8,motion\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"icon,0-113-7-3,tamper\",\n\t\t\t\"renameNode,Fibaro PIR G5 (Magic Eye)\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"2016-10-24 15:06:21\",\n\t\t\"commentary\": \"don't create sensor devices, change node name,rename sensors and change their icons\",\n\t\t\"created\": \"2016-10-24 15:06:21\"\n\t}, {\n\t\t\"id\": \"43\",\n\t\t\"p_id\": \"134.2.74\",\n\t\t\"p_sku\": \"AEOEZW074 \",\n\t\t\"product\": \"Aeotec Multisensor G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113-7\",\n\t\t\t\"setConfig(0,3,10,2);\",\n\t\t\t\"setConfig(0,4,1,1);\",\n\t\t\t\"setConfig(0,5,2,1);\",\n\t\t\t\"rename,0-48-1,Motion\",\n\t\t\t\"renameNode,Aeotec Multisensor G5\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"Hide burglar alarm, activate all sensors, set timeout of motion sensor to 10 sec, activate motion sensor,rename node and widget\",\n\t\t\"created\": \"2016-10-24 16:25:28\"\n\t}, {\n\t\t\"id\": \"45\",\n\t\t\"p_id\": \"271.3329.4096\",\n\t\t\"p_sku\": \"FIBEFGGC-001\",\n\t\t\"product\": \"Fibaro Swipe - Gesture Controller\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"setCCData(0,91,'security','value',false);\",\n\t\t\t\"renameNode,Fibaro Swipe - Gesture Controller\",\n\t\t\t\"discreteState,0-91,10,1,swipe_up,G\",\n\t\t\t\"discreteState,0-91,20,1,swipe_down,G\",\n\t\t\t\"discreteState,0-91,30,1,swipe_left,G\",\n\t\t\t\"discreteState,0-91,40,1,swipe_right,G\",\n\t\t\t\"rename,0-91,Fibaro Swipe\"\n\t\t],\n\t\t\"author_last_update\": \"2016-12-16 10:47:17\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"NIRRS\",\n\t\t\"tester_last_update\": \"2016-12-16 10:47:17\",\n\t\t\"commentary\": \"NIR: add scene support, set CentralScene to unsecure, rename node RS: discreteState \",\n\t\t\"created\": \"2017-01-16 15:14:40\"\n\t}, {\n\t\t\"id\": \"47\",\n\t\t\"p_id\": \"271.1793.4097\",\n\t\t\"p_sku\": \"FIBEFGK-101-ZW5FIBEFGK-103-ZW5FIBEFGK-106-ZW5\",\n\t\t\"product\": \"Fibaro Door/Window Sensor G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Door/Window Sensor G5\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"rename,0-113-6,Door/Window Sensor\",\n\t\t\t\"noVDev,0-156-0\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].MultiChannelAssociation.Remove(1,1,0);self.zway.devices[nodeId].Association.Set(1,1);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-03 10:58:01\",\n\t\t\"author\": \"NIR,SP\",\n\t\t\"tester\": \"NIR,SP\",\n\t\t\"tester_last_update\": \"2018-01-03 10:58:01\",\n\t\t\"commentary\": \"set wakeup to unsecure >> removed,rename node,no create 0-156-0,rename Tamper and Sensor,Update - To make security reports work: remove node 1 from MultiChannelAssociation group 1 and add node 1 to Association group 1\",\n\t\t\"created\": \"2017-08-10 12:21:47\"\n\t}, {\n\t\t\"id\": \"48\",\n\t\t\"p_id\": \"277.2.40976\",\n\t\t\"p_sku\": \"POPE010101\",\n\t\t\"product\": \"Popp Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2017-02-10 12:31:06\"\n\t}, {\n\t\t\"id\": \"51\",\n\t\t\"p_id\": \"316.2.30\",\n\t\t\"p_sku\": \"Philio PSG01 Smoke Sensor\",\n\t\t\"product\": \"Philio PSG01 Smoke Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"setConfig(0,7,16,1);\",\n\t\t\t\"setCCData(0,132,'security','value',false);\",\n\t\t\t\"renameNode,Philio PSG01 Smoke Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name, change configuration,set wakeup to unsecure,\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"52\",\n\t\t\"p_id\": \"134.2.100\",\n\t\t\"p_sku\": \"AEOEZW100\",\n\t\t\"product\": \"Aeotec Multisensor Gen 6\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,5,2,1);\",\n\t\t\t\"setConfig(0,3,10,20);\",\n\t\t\t\"noVDev,0-113-7-8\",\n\t\t\t\"rename,0-48-1,PIR\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"renameNode,Aeotec Multisensor Gen 6\"\n\t\t],\n\t\t\"author_last_update\": \"2019-01-04 11:17:19\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"2019-01-04 11:17:19\",\n\t\t\"commentary\": \"don't create Alarm device 113-7-8, change node name, change configuration,rename tamper and motion sensor\",\n\t\t\"created\": \"2017-11-14 10:53:14\"\n\t}, {\n\t\t\"id\": \"53\",\n\t\t\"p_id\": \"134.2.45\",\n\t\t\"p_sku\": \"FOXEFLOOD \",\n\t\t\"product\": \"Water Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"54\",\n\t\t\"p_id\": \"134.4.37\",\n\t\t\"p_sku\": \"FOXEEXTENDER\",\n\t\t\"product\": \"Foxx Project Range Extender\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Foxx Project Range Extender\"],\n\t\t\"author_last_update\": \"2017-06-23 15:30:27\",\n\t\t\"author\": \"NIR RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-23 15:30:27\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-06-23 15:30:27\"\n\t}, {\n\t\t\"id\": \"56\",\n\t\t\"p_id\": \"134.3.99\",\n\t\t\"p_sku\": \"AEOEZW099\",\n\t\t\"product\": \"Aeotec SmartDimmer 6\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,1-50\",\n\t\t\t\"noVDev,2-50\",\n\t\t\t\"renameNode,Aeotec SmartDimmer 6\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create meter devices 1-50 and 2-50,rename node\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"57\",\n\t\t\"p_id\": \"134.3.75\",\n\t\t\"p_sku\": \"FOXESES\",\n\t\t\"product\": \"Foxx Project Smart Switch Gen5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Foxx Project Smart Switch Gen5\",\n\t\t\t\"setConfig(0,101,15,4)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-27 10:36:09\",\n\t\t\"author\": \"RSSP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-27 10:36:09\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-02-27 10:42:27\"\n\t}, {\n\t\t\"id\": \"58\",\n\t\t\"p_id\": \"134.2.29\",\n\t\t\"p_sku\": \"FOXEDWSENS\",\n\t\t\"product\": \"Foxx Project Door/Window SENSOR\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"59\",\n\t\t\"p_id\": \"329.4628.1284\",\n\t\t\"p_sku\": \"WIDEWDS\",\n\t\t\"product\": \"WiDom Universal Double Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,WiDom Switch\"],\n\t\t\"author_last_update\": \"2017-12-19 10:30:20\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-12-19 10:30:20\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-06-01 08:58:24\"\n\t}, {\n\t\t\"id\": \"60\",\n\t\t\"p_id\": \"134.1.38\",\n\t\t\"p_sku\": \"AEO_PANIC\",\n\t\t\"product\": \"Aeotec Panic Button\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Panic Button\"],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2016-12-01 14:58:54\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2016-12-16 11:57:13\"\n\t}, {\n\t\t\"id\": \"61\",\n\t\t\"p_id\": \"351.2050.12546\",\n\t\t\"p_sku\": \"MCOEMH8-FC4\",\n\t\t\"product\": \"MCO Home Fan Coil Thermostat (4-pipe)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Fan Coil Thermostat (4-pipe)\"],\n\t\t\"author_last_update\": \"2017-06-19 16:05:41\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-19 16:05:41\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-06-19 16:05:41\"\n\t}, {\n\t\t\"id\": \"62\",\n\t\t\"p_id\": \"351.2049.12546\",\n\t\t\"p_sku\": \"MCOEMH8-FC\",\n\t\t\"product\": \"MCO Home Fan Coil Thermostat (2-pipe)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Fan Coil Thermostat (2-pipe)\"],\n\t\t\"author_last_update\": \"2017-06-13 11:01:11\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-13 11:01:11\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-06-13 11:01:11\"\n\t}, {\n\t\t\"id\": \"65\",\n\t\t\"p_id\": \"277.272.1\",\n\t\t\"p_sku\": \"ZMEEZUNO\",\n\t\t\"product\": \"Z-Uno\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [],\n\t\t\"author_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"author\": \"\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"67\",\n\t\t\"p_id\": \"65535.3.8\",\n\t\t\"p_sku\": \"TKBETZ67-F\",\n\t\t\"product\": \"TKB Plug Dimmer French\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB Plug Dimmer\",\n\t\t\t\"rename,0-38, Dimmer\"\n\t\t],\n\t\t\"author_last_update\": \"2017-10-27 07:51:47\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-10-27 07:51:47\",\n\t\t\"commentary\": \"rename Node and device\",\n\t\t\"created\": \"2017-10-27 07:51:47\"\n\t}, {\n\t\t\"id\": \"68\",\n\t\t\"p_id\": \"265.8193.262\",\n\t\t\"p_sku\": \"VISEZD2102-5\",\n\t\t\"product\": \"Vision ZD2102 G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-7-3,Tamper\",\n\t\t\t\"renameNode,Vision ZD2102 G5\",\n\t\t\t\"rename,0-113-6,Door/Window Sensor\",\n\t\t\t\"icon,0-113-6,door\",\n\t\t\t\"icon,0-113-7-3,tamper\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename and change icon of devices 0-113-7-3 and 0-113-6,rename node\",\n\t\t\"created\": \"2016-10-26 09:15:00\"\n\t}, {\n\t\t\"id\": \"69\",\n\t\t\"p_id\": \"134.2.112\",\n\t\t\"p_sku\": \"AEOEZW112\",\n\t\t\"product\": \"Aeotec Door Window Sensor 6\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"rename,0-48-1,Door/Window\",\n\t\t\t\"renameNode,Aeotec Door Window Sensor 6\",\n\t\t\t\"setConfig(0,121,2,1);\",\n\t\t\t\"icon,0-48-1,door\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-02 10:50:04\",\n\t\t\"author\": \"NIRSP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"2018-07-02 10:50:04\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name, change configuration,rename device 0-48-1chance icon\",\n\t\t\"created\": \"2016-10-25 15:11:22\"\n\t}, {\n\t\t\"id\": \"70\",\n\t\t\"p_id\": \"271.1792.4096\",\n\t\t\"p_sku\": \"FIB_FGK-107\",\n\t\t\"product\": \"Fibaro Door/Window Sensor G3\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"icon,0-48-1,door\",\n\t\t\t\"rename,0-48-1,Door/Window\",\n\t\t\t\"renameNode,Fibaro Door/Window Sensor G3\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create AlarmSensor devices, change icon and name of 0-48-1,rename node\",\n\t\t\"created\": \"2017-08-11 13:22:54\"\n\t}, {\n\t\t\"id\": \"71\",\n\t\t\"p_id\": \"271.2048.4097\",\n\t\t\"p_sku\": \"Fibaro Motion Series 300\",\n\t\t\"product\": \"Fibaro Motion Series 300\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-156\",\n\t\t\t\"rename,0-48-1,Fibaro PIR\",\n\t\t\t\"renameNode,Fibaro Motion Series 300\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:39\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create AlarmSensor devices,rename device 0-48-1,rename node \",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"72\",\n\t\t\"p_id\": \"265.8220.7169\",\n\t\t\"p_sku\": \"VIS_ZF5201\",\n\t\t\"product\": \"Vision ZF5201 G3\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-48-1,Water\",\n\t\t\t\"icon,0-48-1,water\",\n\t\t\t\"renameNode,Vision ZF5201 G3\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:40\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"change name and icon of 0-48-1,rename node\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"74\",\n\t\t\"p_id\": \"340.256.513\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"Popp Smoke Detector (Secudo)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"rename,0-37,Siren\",\n\t\t\t\"rename,0-48-2,Smoke Alarm\",\n\t\t\t\"renameNode,Popp Smoke Detector/Siren\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 07:55:22\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name,rename devices 0-37 and 0-48-2\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"75\",\n\t\t\"p_id\": \"410.3.3\",\n\t\t\"p_sku\": \"SENE1110\",\n\t\t\"product\": \"Sensative Strip\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Sensative Strip\",\n\t\t\t\"icon,0-113-6,door\",\n\t\t\t\"noVDev,0-48-1\",\n\t\t\t\"noVDev,0-113-7-4\",\n\t\t\t\"rename,0-113-6,Door/Window Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:40\",\n\t\t\"author\": \"NIR, SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"2016-10-26 12:18:14\",\n\t\t\"commentary\": \"change icon and name of 0-113-6,rename node\",\n\t\t\"created\": \"2016-10-26 12:18:14\"\n\t}, {\n\t\t\"id\": \"76\",\n\t\t\"p_id\": \"340.4.3\",\n\t\t\"p_sku\": \"POPE004407\",\n\t\t\"product\": \"Popp CO Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"rename,0-48-8,CO Tamper\",\n\t\t\t\"rename,0-48-3,CO Alarm\",\n\t\t\t\"renameNode,Popp CO Sensor\",\n\t\t\t\"icon,0-48-3,smoke\",\n\t\t\t\"noVDev,0-49-40\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-27 14:11:12\",\n\t\t\"author\": \"NIR,SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name,change name of 0-48-8 and 0-48-3don't create Value 0-48-40change icon 0-48-3\",\n\t\t\"created\": \"2016-10-27 14:11:12\"\n\t}, {\n\t\t\"id\": \"77\",\n\t\t\"p_id\": \"261.8193.261\",\n\t\t\"p_sku\": \"VISEZD2105EU-5\",\n\t\t\"product\": \"Vision ZD2105EU-5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-6,Door\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"icon,0-113-7-3,tamper\",\n\t\t\t\"renameNode,Vision ZD2105EU-5\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:40\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename 0-113-6 and 0-113-7-3,change icon of 0-113-7-3,rename node\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"80\",\n\t\t\"p_id\": \"271.3841.4096\",\n\t\t\"p_sku\": \"FIBEFGPB-101-X\",\n\t\t\"product\": \"Fibaro The Button - all colors\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setCCData(0,91,'security','value',false);\",\n\t\t\t\"renameNode,Fibaro The Button\",\n\t\t\t\"noVDev,0-113-7-2\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,14,3,press,B\",\n\t\t\t\"discreteState,0-91,15,4,press,B\",\n\t\t\t\"discreteState,0-91,16,5,press,B\",\n\t\t\t\"hide,0-156-0\",\n\t\t\t\"rename,0-91,The Button\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-10 14:36:58\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"NIRRS\",\n\t\t\"tester_last_update\": \"2016-11-28 16:54:44\",\n\t\t\"commentary\": \"NIR: set secure Communication for centralscene class to secure:false, renameNode; RS: noVDev, add different discrete values to discrete sensor\",\n\t\t\"created\": \"2017-01-16 15:16:37\"\n\t}, {\n\t\t\"id\": \"88\",\n\t\t\"p_id\": \"271.1027.4096\",\n\t\t\"p_sku\": \"FIBEFGS-213\",\n\t\t\"product\": \"Fibaro Single Switch 2\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Single Switch 2\",\n\t\t\t\"noVDev,0-50-0\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,1-50-2,Current consumption\",\n\t\t\t\"rename,1-50-0,Total consumption\",\n\t\t\t\"discreteState,0-91,10,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,1,press,B\",\n\t\t\t\"discreteState,0-91,14,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,1,press,B\",\n\t\t\t\"discreteState,0-91,24,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-01-31 15:13:37\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-01-31 15:13:37\",\n\t\t\"commentary\": \"rename Node, rename widgtes, Fix Discret State\",\n\t\t\"created\": \"2017-06-27 10:42:05\"\n\t}, {\n\t\t\"id\": \"89\",\n\t\t\"p_id\": \"340.5.1\",\n\t\t\"p_sku\": \"POPE012501\",\n\t\t\"product\": \"Popp Electric Strike Lock Control\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Strike Lock\",\n\t\t\t\"hide,0-113-6\",\n\t\t\t\"hide,0-48-10\"\n\t\t],\n\t\t\"author_last_update\": \"2016-11-09 12:22:19\",\n\t\t\"author\": \"NIR, SP, RS\",\n\t\t\"tester\": \"SP, RS\",\n\t\t\"tester_last_update\": \"2016-11-09 12:22:19\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2016-11-09 12:22:57\"\n\t}, {\n\t\t\"id\": \"90\",\n\t\t\"p_id\": \"271.515.4096\",\n\t\t\"p_sku\": \"FIBEFGS-223\",\n\t\t\"product\": \"Fibaro Double Switch 2\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Fibaro Double Switch 2\",\n\t\t\t\"rename,0-50-2,Current consumption all\",\n\t\t\t\"rename,1-50-0,Total consumption S1\",\n\t\t\t\"rename,0-50-0,Total consumption all\",\n\t\t\t\"rename,2-50-0,Total consumption S2\",\n\t\t\t\"rename,1-50-2,Current consumption S1\",\n\t\t\t\"rename,2-50-2,Current consumption S2\",\n\t\t\t\"discreteState,0-91,10,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,1,press,B\",\n\t\t\t\"discreteState,0-91,14,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,1,press,B\",\n\t\t\t\"discreteState,0-91,24,2,press,B\",\n\t\t\t\"rename,0-37,Switch all on/off\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:40\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-27 09:37:48\",\n\t\t\"commentary\": \"rename energy Meters, rename Node, fix discreteState\",\n\t\t\"created\": \"2017-02-02 15:47:56\"\n\t}, {\n\t\t\"id\": \"91\",\n\t\t\"p_id\": \"357.1.3\",\n\t\t\"p_sku\": \"NODEMSP3101 / NODEMSP3111\",\n\t\t\"product\": \"NodOn Micro Smart Plug Type E / F\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,NodOn Micro Smart Plug\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"hide,0-113-9-1\",\n\t\t\t\"hide,0-113-8-254\",\n\t\t\t\"hide,0-113-9-254\",\n\t\t\t\"rename,0-37,Switch\",\n\t\t\t\"rename,0-50-0,Electric Meter kWh\",\n\t\t\t\"rename,0-50-2,Electric Meter W\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-22 08:58:29\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-22 08:58:29\",\n\t\t\"commentary\": \"RS: renameNode, hide, rename\",\n\t\t\"created\": \"2018-01-12 15:40:51\"\n\t}, {\n\t\t\"id\": \"95\",\n\t\t\"p_id\": \"134.2.120\",\n\t\t\"p_sku\": \"AEOEZW120\",\n\t\t\"product\": \"Aeotec Door/Window Sensor Gen5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Door/Window Sensor\",\n\t\t\t\"rename,0-113-6,Door/Window\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"hide,0-48-1\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:40\",\n\t\t\"author\": \"NIRSP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-27 09:36:34\",\n\t\t\"commentary\": \"renameNode, rename, hide\",\n\t\t\"created\": \"2017-06-27 09:36:34\"\n\t}, {\n\t\t\"id\": \"96\",\n\t\t\"p_id\": \"340.4.8\",\n\t\t\"p_sku\": \"POPE700052\",\n\t\t\"product\": \"POPP Flood / Water Leakage Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"icon,0-48-6,humidity\",\n\t\t\t\"rename,0-48-6,Popp Water\",\n\t\t\t\"renameNode,POPP Flood / Water Leakage Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-16 14:26:19\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-16 14:26:19\",\n\t\t\"commentary\": \"RS: renameNode, rename, icon\",\n\t\t\"created\": \"2018-02-16 14:26:19\"\n\t}, {\n\t\t\"id\": \"99\",\n\t\t\"p_id\": \"271.2817.4098\",\n\t\t\"p_sku\": \"FIBEFGFS-101-ZW5\",\n\t\t\"product\": \"Fibaro Leakage Sensor G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-5-2,Water\",\n\t\t\t\"icon,0-113-5-2,water\",\n\t\t\t\"renameNode,Fibaro Leakage Sensor G5\",\n\t\t\t\"noVDev,0-113-5-0\",\n\t\t\t\"noVDev,0-113-7-0\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"icon,0-113-7-3,tamper\",\n\t\t\t\"noVDev,0-156\",\n\t\t\t\"rename,0-49-1,Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-26 14:42:53\",\n\t\t\"author\": \"RS, NIR\",\n\t\t\"tester\": \"RS, NIR\",\n\t\t\"tester_last_update\": \"2016-10-26 00:00:00\",\n\t\t\"commentary\": \"don't create Alarm/Sensor devices,rename node,rename widget and change icon\",\n\t\t\"created\": \"2016-10-26 14:43:45\"\n\t}, {\n\t\t\"id\": \"100\",\n\t\t\"p_id\": \"265.8194.517\",\n\t\t\"p_sku\": \"VISEZP3102-5\",\n\t\t\"product\": \"Vision PIR - Sensor Gen5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-7-8,Motion\",\n\t\t\t\"renameNode, Vision PIR - Sensor Gen 5\",\n\t\t\t\"icon,0-113-7-8,motion\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"icon,0-113-7-3,tamper\",\n\t\t\t\"rename,0-49-1,Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-26 14:47:59\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2016-10-26 14:24:31\"\n\t}, {\n\t\t\"id\": \"101\",\n\t\t\"p_id\": \"271.3074.4098.3.3\",\n\t\t\"p_sku\": \"FIBEFGSD-002\",\n\t\t\"product\": \"Fibaro Smoke Sensor FGSD-002 ZW5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-156\",\n\t\t\t\"noVDev,0-113-1-3\",\n\t\t\t\"noVDev,0-113-7\",\n\t\t\t\"noVDev,0-113-8\",\n\t\t\t\"noVDev,0-113-9\",\n\t\t\t\"rename,0-113-4-2,Heat Alarm\",\n\t\t\t\"rename,0-113-1-2,Smoke Alarm\",\n\t\t\t\"renameNode,Fibaro Smoke Sensor FGSD-002\",\n\t\t\t\"icon,0-113-1-2,smoke\",\n\t\t\t\"icon,0-113-4-2,smoke\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-27 09:21:30\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"hide Alarm and AlarmSensor widgets, rename widgets and nodechange icons\",\n\t\t\"created\": \"2016-11-29 11:39:44\"\n\t}, {\n\t\t\"id\": \"102\",\n\t\t\"p_id\": \"96.1.2\",\n\t\t\"p_sku\": \"EVR_SP814\",\n\t\t\"product\": \"Everspring Motion Detector\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Evererspring Motion Detector\",\n\t\t\t\"rename,0-48-1,Motion\"\n\t\t],\n\t\t\"author_last_update\": \"2016-11-01 10:40:54\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2016-11-01 10:40:54\"\n\t}, {\n\t\t\"id\": \"103\",\n\t\t\"p_id\": \"520.256.4\",\n\t\t\"p_sku\": \"HNKERGB01\",\n\t\t\"product\": \"RGB Bulb\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,RGB Bulb\"],\n\t\t\"author_last_update\": \"2016-11-03 11:19:53\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2016-11-21 10:03:58\"\n\t}, {\n\t\t\"id\": \"104\",\n\t\t\"p_id\": \"358.256.256\",\n\t\t\"p_sku\": \"SWI_ZCS1\",\n\t\t\"product\": \"Swiid Cord Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Swiid Cord Switch\",\n\t\t\t\"rename,0-37,Switch\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-18 15:33:31\",\n\t\t\"author\": \"SP, RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-09-18 15:33:31\",\n\t\t\"commentary\": \"RS: rename deviceID\",\n\t\t\"created\": \"2017-09-18 15:33:31\"\n\t}, {\n\t\t\"id\": \"105\",\n\t\t\"p_id\": \"271.1538.4097\",\n\t\t\"p_sku\": \"FIBEFGWP E/F-102-ZW5\",\n\t\t\"product\": \"Fibaro Wall Plug FGWPx-102 ZW5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Wall Plug FGWPx-102 ZW5\"],\n\t\t\"author_last_update\": \"2016-11-14 13:57:40\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-01-31 14:44:37\",\n\t\t\"commentary\": \"SP: rename Node\",\n\t\t\"created\": \"2016-12-21 15:05:17\"\n\t}, {\n\t\t\"id\": \"106\",\n\t\t\"p_id\": \"305.2.2\",\n\t\t\"p_sku\": \"ZIP_Bulb\",\n\t\t\"product\": \"RGBW light bulb\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Zipato RGBW bulb\"],\n\t\t\"author_last_update\": \"2016-11-15 11:07:42\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2016-11-15 11:07:42\",\n\t\t\"commentary\": \"renameNode\",\n\t\t\"created\": \"2016-12-14 13:35:11\"\n\t}, {\n\t\t\"id\": \"107\",\n\t\t\"p_id\": \"280.3.1\",\n\t\t\"p_sku\": \"TKBETZ37\",\n\t\t\"product\": \"Z-Wave two channel switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB-TZ37 two channel switch\",\n\t\t\t\"hide,0-37\"\n\t\t],\n\t\t\"author_last_update\": \"2016-11-17 13:47:21\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Switch 0 and rename Node\",\n\t\t\"created\": \"2016-11-17 13:47:21\"\n\t}, {\n\t\t\"id\": \"109\",\n\t\t\"p_id\": \"134.4.117\",\n\t\t\"p_sku\": \"AEOEZW117\",\n\t\t\"product\": \"Aeotec Range Extender 6\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Range Extender 6\"],\n\t\t\"author_last_update\": \"2018-04-10 14:14:53\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP RS\",\n\t\t\"tester_last_update\": \"2018-04-10 14:14:53\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-10-09 14:17:15\"\n\t}, {\n\t\t\"id\": \"110\",\n\t\t\"p_id\": \"280.2056.2056\",\n\t\t\"p_sku\": \"TKBETZ35-S\",\n\t\t\"product\": \"TKBHOME single/dual dimmer switch TZ35S/D\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB single/dual dimmer switch TZ35 S/D\"],\n\t\t\"author_last_update\": \"2016-11-18 08:26:22\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-18 14:08:38\"\n\t}, {\n\t\t\"id\": \"111\",\n\t\t\"p_id\": \"280.258.4128\",\n\t\t\"p_sku\": \"TKBETZ36-S\",\n\t\t\"product\": \"TKBHOME single/dual wall switch TZ36S/D\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, TKBsingle/dual switch TZ36S/D\"],\n\t\t\"author_last_update\": \"2016-11-18 11:18:48\",\n\t\t\"author\": \"\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-18 14:09:17\"\n\t}, {\n\t\t\"id\": \"112\",\n\t\t\"p_id\": \"280.3.3\",\n\t\t\"p_sku\": \"TKBETZ56-D\",\n\t\t\"product\": \"TKBHome single/dual wall switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB single/dual switch\"],\n\t\t\"author_last_update\": \"2016-11-21 11:46:13\",\n\t\t\"author\": \"\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-22 12:27:24\"\n\t}, {\n\t\t\"id\": \"113\",\n\t\t\"p_id\": \"280.785.515\",\n\t\t\"p_sku\": \"TKBETZ57\",\n\t\t\"product\": \"TKBHome two channel switch TZX7\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB two channel switch TZX7\",\n\t\t\t\"rename,0-37,Switch all on/off\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-17 12:16:19\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"2018-04-17 12:16:19\",\n\t\t\"commentary\": \"rename Noderename Switch all\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"114\",\n\t\t\"p_id\": \"280.3.4\",\n\t\t\"p_sku\": \"TKBETZ55-D\",\n\t\t\"product\": \"TKBHOME single/dual dimmer switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, TKB single/dual dimmer switc\"],\n\t\t\"author_last_update\": \"2016-11-21 15:42:11\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-22 12:28:33\"\n\t}, {\n\t\t\"id\": \"115\",\n\t\t\"p_id\": \"277.4096.768\",\n\t\t\"p_sku\": \"ZME_RC2\",\n\t\t\"product\": \"Z-Wave.me Scene Controller\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"enameNode,Z-Wave.me Scene Controlle\"],\n\t\t\"author_last_update\": \"2016-11-23 10:13:16\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2016-11-23 10:13:16\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-23 10:13:16\"\n\t}, {\n\t\t\"id\": \"116\",\n\t\t\"p_id\": \"345.1.82\",\n\t\t\"p_sku\": \"GOAEZMNHSD1\",\n\t\t\"product\": \"Qubino DIN Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino DIN Dimmer\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"hide,0-113-8-254\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-20 11:20:51\",\n\t\t\"author\": \"SP ; RS\",\n\t\t\"tester\": \"SP ; RS\",\n\t\t\"tester_last_update\": \"2018-07-20 11:20:51\",\n\t\t\"commentary\": \"SP: renameNode, Association.Set RS: hide, rename\",\n\t\t\"created\": \"2018-07-20 11:20:51\"\n\t}, {\n\t\t\"id\": \"117\",\n\t\t\"p_id\": \"345.1.83\",\n\t\t\"p_sku\": \"GOAEZMNHVD1\",\n\t\t\"product\": \"Qubino Dimmerinsert 0-10V\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Flush Dimmer 0-10V\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\",\n\t\t\t\"setConfig(0,250,1,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-17 15:25:55\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-17 15:25:55\",\n\t\t\"commentary\": \"RS: renameNode SP Set Parameter 250 and Assoc 1\",\n\t\t\"created\": \"2017-06-15 11:55:51\"\n\t}, {\n\t\t\"id\": \"118\",\n\t\t\"p_id\": \"65535.3.5\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"Heltun Floor Heating Thermostat HE-ZW-THERM-FL1\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heltun Heating Thermostat\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\"\n\t\t],\n\t\t\"author_last_update\": \"2016-11-28 14:03:00\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node, rename electric meter\",\n\t\t\"created\": \"2016-11-28 14:03:00\"\n\t}, {\n\t\t\"id\": \"120\",\n\t\t\"p_id\": \"271.770.4096\",\n\t\t\"p_sku\": \"FIBEFGR-222\",\n\t\t\"product\": \"Fibaro Roller Shutter 2\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Roller Shutter 2\"],\n\t\t\"author_last_update\": \"2016-12-14 09:29:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2016-12-14 09:29:48\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-12-14 09:29:48\"\n\t}, {\n\t\t\"id\": \"121\",\n\t\t\"p_id\": \"316.9.34\",\n\t\t\"p_sku\": \"PHIEPSR04\",\n\t\t\"product\": \"Philio PSR04 Smart Color Button\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,1,'S');\",\n\t\t\t\"renameNode,Philio PSR04 Smart Color Button\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\"\n\t\t],\n\t\t\"author_last_update\": \"2016-12-15 11:16:51\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"NIRRS\",\n\t\t\"tester_last_update\": \"2016-12-15 11:16:51\",\n\t\t\"commentary\": \"NIR: add scene support, rename nodeRS: discreteState\",\n\t\t\"created\": \"2016-12-15 13:42:12\"\n\t}, {\n\t\t\"id\": \"122\",\n\t\t\"p_id\": \"21076.1.34064\",\n\t\t\"p_sku\": \"REMEZRC90\",\n\t\t\"product\": \"Remotec Scene Master\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,8,'S');\",\n\t\t\t\"renameNode,Remotec Scene Master\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\",\n\t\t\t\"discreteState,0-91,50,1,press,B\",\n\t\t\t\"discreteState,0-91,51,1,release,B\",\n\t\t\t\"discreteState,0-91,52,1,hold,B\",\n\t\t\t\"discreteState,0-91,53,2,press,B\",\n\t\t\t\"discreteState,0-91,60,1,press,B\",\n\t\t\t\"discreteState,0-91,61,1,release,B\",\n\t\t\t\"discreteState,0-91,62,1,hold,B\",\n\t\t\t\"discreteState,0-91,63,2,press,B\",\n\t\t\t\"discreteState,0-91,70,1,press,B\",\n\t\t\t\"discreteState,0-91,71,1,release,B\",\n\t\t\t\"discreteState,0-91,72,1,hold,B\",\n\t\t\t\"discreteState,0-91,73,2,press,B\",\n\t\t\t\"discreteState,0-91,80,1,press,B\",\n\t\t\t\"discreteState,0-91,81,1,release,B\",\n\t\t\t\"discreteState,0-91,82,1,hold,B\",\n\t\t\t\"discreteState,0-91,83,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2016-12-15 14:02:15\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"NIRRS\",\n\t\t\"tester_last_update\": \"2016-12-15 14:02:15\",\n\t\t\"commentary\": \"NIR: add scene support, RS: discreteState, renameNode\",\n\t\t\"created\": \"2016-12-16 11:38:39\"\n\t}, {\n\t\t\"id\": \"123\",\n\t\t\"p_id\": \"134.1.88\",\n\t\t\"p_sku\": \"AEO_ZW088\",\n\t\t\"product\": \"Aeotec Key Fob\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Key Fob\"],\n\t\t\"author_last_update\": \"2016-12-16 11:26:46\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2016-12-16 11:26:46\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2016-12-16 11:26:46\"\n\t}, {\n\t\t\"id\": \"125\",\n\t\t\"p_id\": \"345.7.82\",\n\t\t\"p_sku\": \"GOAEZMNHTD1\",\n\t\t\"product\": \"Qubino Smart Meter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Smart Meter\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current electricity\",\n\t\t\t\"rename,0-50-1,Total energy consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-0,Active energy consumption\",\n\t\t\t\"rename,1-50-4,Current voltage\",\n\t\t\t\"rename,1-50-5,Current electricity\",\n\t\t\t\"rename,1-50-1,Total energy consumption\",\n\t\t\t\"rename,1-50-2,Current consumption\",\n\t\t\t\"rename,1-50-0,Active energy consumption\",\n\t\t\t\"hide,1-37\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-05 13:08:45\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-05 13:08:45\",\n\t\t\"commentary\": \"rename widgets, rename Node, hide element\",\n\t\t\"created\": \"2018-05-17 13:11:54\"\n\t}, {\n\t\t\"id\": \"126\",\n\t\t\"p_id\": \"345.5.82\",\n\t\t\"p_sku\": \"GOAEZMNHKD1\",\n\t\t\"product\": \"Qubino Flush Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Flush Thermostat\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"rename,0-50-2,current consumption\",\n\t\t\t\"setConfig(0,40,1,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-27 08:37:30\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-27 08:37:30\",\n\t\t\"commentary\": \"rename note, rename electrical meter\",\n\t\t\"created\": \"2016-12-22 14:11:05\"\n\t}, {\n\t\t\"id\": \"127\",\n\t\t\"p_id\": \"345.5.81\",\n\t\t\"p_sku\": \"GOAEZMNHID1\",\n\t\t\"product\": \"Qubino On/Off thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino On/Off thermostat\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"setConfig(0,40,1,1)\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-19 14:32:47\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-19 14:32:47\",\n\t\t\"commentary\": \"rename Node, rename Energie Meter, reset Assoziation group 1\",\n\t\t\"created\": \"2016-12-22 11:47:44\"\n\t}, {\n\t\t\"id\": \"129\",\n\t\t\"p_id\": \"316.1.41\",\n\t\t\"p_sku\": \"PHIEPAN16 / PHIRPAN16-RU\",\n\t\t\"product\": \"PAN16 Smart Energy Plug In Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,12,1,1);\",\n\t\t\t\"renameNode,Philio PAN16 Smart Energy Plug In Switch\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-10 14:37:53\",\n\t\t\"author\": \"AIVS RS\",\n\t\t\"tester\": \"AIVS RS\",\n\t\t\"tester_last_update\": \"2018-04-10 14:37:53\",\n\t\t\"commentary\": \"AIVS: setConfig, renameNodeRS: changed name\",\n\t\t\"created\": \"2017-09-06 13:49:42\"\n\t}, {\n\t\t\"id\": \"130\",\n\t\t\"p_id\": \"328.3.1\",\n\t\t\"p_sku\": \"EURESPIRIT\",\n\t\t\"product\": \"Eurotronic Spirit\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Eurotronic Spirit\",\n\t\t\t\"rename,0-64,Eurotronic Thermostat operation\",\n\t\t\t\"rename,0-67-1,Eurotronic Thermostat Heat\",\n\t\t\t\"rename,0-49-1,Eurotronic Thermostat Temperature\",\n\t\t\t\"noVDev,0-113-9-4\",\n\t\t\t\"hide,0-113-8-10\",\n\t\t\t\"hide,0-113-8-11\",\n\t\t\t\"hide,0-113-9-3\",\n\t\t\t\"hide,0-38\",\n\t\t\t\"setConfig(0,6,5,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2020-10-12 14:00:00\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-01-12 15:46:22\",\n\t\t\"commentary\": \"RS: rename node, rename devices, noVDev devices, hide devices\",\n\t\t\"created\": \"2017-06-26 13:34:52\"\n\t}, {\n\t\t\"id\": \"131\",\n\t\t\"p_id\": \"96.4.1\",\n\t\t\"p_sku\": \"EVR_AN145EVR_AN157\",\n\t\t\"product\": \"Everspring Lamp Holder\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"enameNode,Everspring Lamp Holde\"],\n\t\t\"author_last_update\": \"2018-02-05 13:55:47\",\n\t\t\"author\": \"SPRS\",\n\t\t\"tester\": \"SPRS\",\n\t\t\"tester_last_update\": \"2018-02-05 13:55:47\",\n\t\t\"commentary\": \"SP/RS: renameNode\",\n\t\t\"created\": \"2018-02-05 13:55:47\"\n\t}, {\n\t\t\"id\": \"132\",\n\t\t\"p_id\": \"134.3.96\",\n\t\t\"p_sku\": \"AEOEZW096\",\n\t\t\"product\": \"Aeotec Smart Switch 6\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Smart Switch 6\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"setConfig(0,80,2,1)\",\n\t\t\t\"setConfig(0,101,15,4);\",\n\t\t\t\"setConfig(0,111,15,4)\",\n\t\t\t\"noVDev,0-51\",\n\t\t\t\"noVDev,0-38\"\n\t\t],\n\t\t\"author_last_update\": \"2017-08-08 10:58:46\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-01-16 12:05:13\",\n\t\t\"commentary\": \"rename Node, rename Energie Meter, delete RGBW and dimmer, ste Parameter 80,101,111\",\n\t\t\"created\": \"2017-08-08 10:58:46\"\n\t}, {\n\t\t\"id\": \"133\",\n\t\t\"p_id\": \"21076.1.33664\",\n\t\t\"p_sku\": \"REM_ZRC100\",\n\t\t\"product\": \"Remotec Universal Remote Control\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,16,'S');\",\n\t\t\t\"renameNode,Universal Remote Control\"\n\t\t],\n\t\t\"author_last_update\": \"2017-01-17 14:47:04\",\n\t\t\"author\": \"NIR\",\n\t\t\"tester\": \"NIR\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"add scene support\",\n\t\t\"created\": \"2017-01-17 14:49:01\"\n\t}, {\n\t\t\"id\": \"134\",\n\t\t\"p_id\": \"316.2.80\",\n\t\t\"p_sku\": \"PHIEPSP05-D\",\n\t\t\"product\": \"Philio Motionsensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio Motionsensor\",\n\t\t\t\"noVDev,0-113-7\",\n\t\t\t\"setConfig(0,7,22,1)\",\n\t\t\t\"setConfig(0,11,0,1)\",\n\t\t\t\"setConfig(0,12,1,1)\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,20,10,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-06 13:35:39\",\n\t\t\"author\": \"SPRSAIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2017-09-06 13:35:39\",\n\t\t\"commentary\": \"SP: rename Node, delete Burglar, set parameter 7, 11, 12, 13, 20\",\n\t\t\"created\": \"2017-09-27 14:27:06\"\n\t}, {\n    \t\t\"id\": \"135\",\n    \t\t\"p_id\": \"271.258.16384\",\n   \t\t\"p_sku\": \"FIBEFGD-212\",\n    \t\t\"product\": \"Fibaro Dimmer 2\",\n    \t\t\"apply_postfix\": \"1\",\n    \t\t\"preInterview\": [],\n    \t\t\"postInterview\": [\n      \t\t\"renameNode,Fibaro Dimmer 2\",\n          \t\t\"noVDev,1-49-4\",\n          \t\t\"noVDev,1-50-0\",\n     \t\t\t\"hide,1-113-9-1\",\n      \t\t\t\"hide,1-113-8-9\",\n      \t\t\t\"hide,1-113-8-8\",\n      \t\t\t\"hide,1-113-8-6\",\n      \t\t\t\"hide,1-113-8-5\",\n      \t\t\t\"hide,1-113-8-4\",\n      \t\t\t\"hide,1-113-4-2\",\n      \t\t\t\"rename,1-49-4,Current consumption\",\n      \t\t\t\"rename,1-50-0,Total consumption\",\n      \t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1);}\"\n    \t\t],\n    \t\t\"author_last_update\": \"2022-10-11 11:36:59\",\n    \t\t\"author\": \"SP,AIVS,SMR\",\n    \t\t\"tester\": \"SMR\",\n    \t\t\"tester_last_update\": \"2022-10-11 11:36:59\",\n    \t\t\"commentary\": \"SP: deactivate instance one and two, rename Energy Meters, rename NodesAIVS: noVDev,0-50 \",\n    \t\t\"created\": \"2017-09-28 11:30:49\"\n  \t}, {\n\t\t\"id\": \"136\",\n\t\t\"p_id\": \"134.3.78\",\n\t\t\"p_sku\": \"AEO_HDS\",\n\t\t\"product\": \"Aeotec Heavy Duty Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Heavy Duty Switch\",\n\t\t\t\"setConfig(0,101,15,4);\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-12 15:08:12\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-12 15:08:12\",\n\t\t\"commentary\": \"RS: renameNodeSP: set Parameter 101 value 15\",\n\t\t\"created\": \"2017-01-23 13:36:39\"\n\t}, {\n\t\t\"id\": \"137\",\n\t\t\"p_id\": \"351.1793.20738\",\n\t\t\"p_sku\": \"MCOEMH7-WH\",\n\t\t\"product\": \"MCOHome Thermostat MH7-WH-EU\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, MCOHOME Thermostat MH7-WH\"],\n\t\t\"author_last_update\": \"2017-01-24 11:20:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-01-24 11:20:48\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-06-27 12:05:46\"\n\t}, {\n\t\t\"id\": \"138\",\n\t\t\"p_id\": \"134.2.130\",\n\t\t\"p_sku\": \"AEOEZW130\",\n\t\t\"product\": \"Aeotec WallMote Quad\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec WallMote Quad\",\n\t\t\t\"noVDev,0-113\",\n\t\t\t\"noVDev,1-91\",\n\t\t\t\"noVDev,2-91\",\n\t\t\t\"noVDev,3-91\",\n\t\t\t\"noVDev,4-91\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-01-25 14:41:27\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-01-25 14:41:27\",\n\t\t\"commentary\": \"RS: renameNode, noVDev, discreteState\",\n\t\t\"created\": \"2017-01-26 13:27:00\"\n\t}, {\n\t\t\"id\": \"139\",\n\t\t\"p_id\": \"340.4352.2\",\n\t\t\"p_sku\": \"POP_123597\",\n\t\t\"product\": \"POPP Zwischenstecker Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Dimmer Plug\"],\n\t\t\"author_last_update\": \"2017-01-25 14:26:15\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-01-25 14:26:15\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-01-25 14:26:15\"\n\t}, {\n\t\t\"id\": \"140\",\n\t\t\"p_id\": \"134.2.129\",\n\t\t\"p_sku\": \"AEOEZW129\",\n\t\t\"product\": \"Aeotec WallMote Dual\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec WallMote Dual\",\n\t\t\t\"noVDev,0-113\",\n\t\t\t\"noVDev,1-91\",\n\t\t\t\"noVDev,2-91\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-01-27 09:47:20\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-01-27 09:47:20\",\n\t\t\"commentary\": \"RS: renameNode, noVDev, discreteState\",\n\t\t\"created\": \"2017-01-27 09:47:20\"\n\t}, {\n\t\t\"id\": \"141\",\n\t\t\"p_id\": \"280.3.8\",\n\t\t\"p_sku\": \"TKBETZ67-G\",\n\t\t\"product\": \"TKB Plug Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB Plug Dimmer\"],\n\t\t\"author_last_update\": \"2018-04-17 14:14:09\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-04-17 14:14:09\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-01-27 15:47:32\"\n\t}, {\n\t\t\"id\": \"142\",\n\t\t\"p_id\": \"271.4097.4096\",\n\t\t\"p_sku\": \"FIBEFGKF-601\",\n\t\t\"product\": \"Fibaro Keyfob\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Keyfob\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,50,1,press,B\",\n\t\t\t\"discreteState,0-91,51,1,release,B\",\n\t\t\t\"discreteState,0-91,52,1,hold,B\",\n\t\t\t\"discreteState,0-91,60,1,press,B\",\n\t\t\t\"discreteState,0-91,61,1,release,B\",\n\t\t\t\"discreteState,0-91,62,1,hold,B\",\n\t\t\t\"setConfig(0, 21, 15, 1);\",\n\t\t\t\"setConfig(0, 22, 15, 1);\",\n\t\t\t\"setConfig(0, 23, 15, 1);\",\n\t\t\t\"setConfig(0, 24, 15, 1);\",\n\t\t\t\"setConfig(0, 25, 15, 1);\",\n\t\t\t\"setConfig(0, 26, 15, 1);\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,14,3,press,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,24,3,press,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,34,3,press,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\",\n\t\t\t\"discreteState,0-91,44,3,press,B\",\n\t\t\t\"discreteState,0-91,53,2,press,B\",\n\t\t\t\"discreteState,0-91,54,3,press,B\",\n\t\t\t\"discreteState,0-91,63,2,press,B\",\n\t\t\t\"discreteState,0-91,64,3,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-02-01 12:25:00\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-02-01 12:25:00\",\n\t\t\"commentary\": \"RS: renameNode, discreteState, setConfig\",\n\t\t\"created\": \"2017-02-01 12:25:31\"\n\t}, {\n\t\t\"id\": \"143\",\n\t\t\"p_id\": \"271.1536.4096\",\n\t\t\"p_sku\": \"FIBEFGWP E/F-102\",\n\t\t\"product\": \"Fibaro Wall Plug FGWPx-102\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Wall Plug FGWPx-102\"],\n\t\t\"author_last_update\": \"2017-01-31 14:43:36\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-01-31 14:43:36\",\n\t\t\"commentary\": \"RS: rename Node\",\n\t\t\"created\": \"2017-01-31 14:43:36\"\n\t}, {\n\t\t\"id\": \"144\",\n\t\t\"p_id\": \"271.1281.4098\",\n\t\t\"p_sku\": \"FIB_FGBS-001\",\n\t\t\"product\": \"Fibaro Universalsensor mit Bin\\u00e4reingang\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Universal Sensor\",\n\t\t\t\"rename,1-48-1,FIBARO IN1\",\n\t\t\t\"rename,2-48-1,FIBARO IN2\",\n\t\t\t\"noVDev,0-48-1\",\n\t\t\t\"icon,1-48-1,switch\",\n\t\t\t\"icon,2-48-1,switch\"\n\t\t],\n\t\t\"author_last_update\": \"2017-01-31 15:30:18\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-01-31 15:30:18\",\n\t\t\"commentary\": \"rename Node and Widgets, change icons\",\n\t\t\"created\": \"2017-03-23 09:15:41\"\n\t}, {\n\t\t\"id\": \"145\",\n\t\t\"p_id\": \"340.3.1\",\n\t\t\"p_sku\": \"POPE009105\",\n\t\t\"product\": \"Popp Wall Plug Switch \",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Wall Plug Switch\"],\n\t\t\"author_last_update\": \"2017-02-02 16:01:42\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-09-08 12:06:52\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-02-02 16:01:42\"\n\t}, {\n\t\t\"id\": \"146\",\n\t\t\"p_id\": \"340.3.1298\",\n\t\t\"p_sku\": \"POPE009501\",\n\t\t\"product\": \"Popp Flow Stop\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Flow Stop\"],\n\t\t\"author_last_update\": \"2017-02-06 11:56:52\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-02-06 11:56:52\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-02-06 11:56:52\"\n\t}, {\n\t\t\"id\": \"147\",\n\t\t\"p_id\": \"345.2.83\",\n\t\t\"p_sku\": \"GOAEZMNHND1\",\n\t\t\"product\": \"Qubino Relay Insert 1*2,3 kW\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,2-113\",\n\t\t\t\"noVDev,0-113\",\n\t\t\t\"noVDev,2-48\",\n\t\t\t\"noVDev,0-48\",\n\t\t\t\"rename,0-37,Switch all on/off\",\n\t\t\t\"renameNode,Qubino Flush 1D Relay\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2019-01-25 10:45:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-25 10:45:08\",\n\t\t\"commentary\": \"renameNode, noVDev general purpose, noVDev burglar, rename device, set Assoc 1\",\n\t\t\"created\": \"2017-11-10 13:50:53\"\n\t}, {\n\t\t\"id\": \"148\",\n\t\t\"p_id\": \"265.8195.774\",\n\t\t\"p_sku\": \"VISEZS5101-5\",\n\t\t\"product\": \"Vision Shock Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Vision Shock Sensor\",\n\t\t\t\"rename,0-113-7-2,Vibration\",\n\t\t\t\"rename,0-113-7-3,Tamper\"\n\t\t],\n\t\t\"author_last_update\": \"2017-02-16 12:28:38\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-02-16 12:28:38\",\n\t\t\"commentary\": \"rename node and device\",\n\t\t\"created\": \"2017-02-16 12:28:38\"\n\t}, {\n\t\t\"id\": \"149\",\n\t\t\"p_id\": \"2.277.40976\",\n\t\t\"p_sku\": \"POPE010101\",\n\t\t\"product\": \"Popp Radiator Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Radiator Thermostat\",\n\t\t\t\"rename,0-67-1,Popp Thermostat Heat\",\n\t\t\t\"rename,0-49-1,Popp Thermostat Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2017-02-20 11:56:08\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-02-20 11:56:08\",\n\t\t\"commentary\": \"RS: renaming\",\n\t\t\"created\": \"2017-02-20 11:56:08\"\n\t}, {\n\t\t\"id\": \"150\",\n\t\t\"p_id\": \"362.3.98\",\n\t\t\"p_sku\": \"AEOEZW098\",\n\t\t\"product\": \"AEOTEC LED BULB\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,AEOTEC LED BULB\"],\n\t\t\"author_last_update\": \"2017-02-23 09:45:56\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-02-23 09:45:56\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-02-23 09:45:56\"\n\t}, {\n\t\t\"id\": \"151\",\n\t\t\"p_id\": \"345.1.84\",\n\t\t\"p_sku\": \"GOAEZMNHWD1\",\n\t\t\"product\": \"Qubino RGBW Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino RGBW Dimmer\"],\n\t\t\"author_last_update\": \"2017-02-27 13:55:19\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-02-27 13:55:19\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-02-27 13:55:19\"\n\t}, {\n\t\t\"id\": \"152\",\n\t\t\"p_id\": \"265.8201.2312\",\n\t\t\"p_sku\": \"VISEZM1602-5\",\n\t\t\"product\": \"Vision DC/AC Power Siren\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Vison DC/AC Power Siren\",\n\t\t\t\"rename,0-37,Siren\",\n\t\t\t\"rename,0-113-7-3,Tamper\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-02 09:15:49\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-03-02 09:15:49\",\n\t\t\"commentary\": \"rename device\",\n\t\t\"created\": \"2017-03-20 11:08:46\"\n\t}, {\n\t\t\"id\": \"153\",\n\t\t\"p_id\": \"2.5.4\",\n\t\t\"p_sku\": \"DAN_LC-13\",\n\t\t\"product\": \"Danfoss Radiator Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Danfoss Radiator Thermostat\",\n\t\t\t\"rename,0-67-1,Thermostat Heat\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 10:14:29\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 10:14:29\",\n\t\t\"commentary\": \"RS: renameNode, renamedeviceID\",\n\t\t\"created\": \"2017-03-16 10:32:23\"\n\t}, {\n\t\t\"id\": \"154\",\n\t\t\"p_id\": \"271.2304.4096\",\n\t\t\"p_sku\": \"FIB_FGRGB-101\",\n\t\t\"product\": \"Fibaro RGBW Module\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro RGBW Controller\"],\n\t\t\"author_last_update\": \"2017-03-16 10:35:06\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 10:35:06\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-03-16 10:35:06\"\n\t}, {\n\t\t\"id\": \"155\",\n\t\t\"p_id\": \"265.8197.1288\",\n\t\t\"p_sku\": \"VISEZM1601-5\",\n\t\t\"product\": \"Vision Security Siren G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Vision Security Siren G5\",\n\t\t\t\"rename,0-37,Siren\",\n\t\t\t\"rename,0-113-7-3,Siren Burglar Alarm\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 10:59:13\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 10:59:13\",\n\t\t\"commentary\": \"RS: renameNode, renamedeviceID\",\n\t\t\"created\": \"2017-03-16 10:59:13\"\n\t}, {\n\t\t\"id\": \"156\",\n\t\t\"p_id\": \"345.7.83\",\n\t\t\"p_sku\": \"GOAEZMNHZD1\",\n\t\t\"product\": \"Qubino Wetterstation\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Weather Station\",\n\t\t\t\"rename,8-49-5,Humidity S1\",\n\t\t\t\"rename,0-49-1,Temperature S2\",\n\t\t\t\"rename,0-49-5,Humidity S2\",\n\t\t\t\"noVDev,9-49-1\",\n\t\t\t\"noVDev,0-49-7\",\n\t\t\t\"noVDev,3-49-6\",\n\t\t\t\"noVDev,0-49-6\",\n\t\t\t\"rename,4-49-6,Wind speed\",\n\t\t\t\"noVDev,0-49-12\",\n\t\t\t\"icon,7-49-12,humidity\",\n\t\t\t\"noVDev,6-49-1\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 11:17:00\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-03-16 11:17:00\",\n\t\t\"commentary\": \"deactivate double moduls, rename Node and devices, set icon rain meter\",\n\t\t\"created\": \"2017-03-16 14:06:57\"\n\t}, {\n\t\t\"id\": \"157\",\n\t\t\"p_id\": \"526.19522.12596\",\n\t\t\"p_sku\": \"DOMEZBULB\",\n\t\t\"product\": \"Domitech ZBulb\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Domitech ZBulb\",\n\t\t\t\"rename,0-38,ZBulb Dimmer\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 11:18:26\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 11:18:26\",\n\t\t\"commentary\": \"RS: renameNode, renamedeviceID\",\n\t\t\"created\": \"2017-05-29 15:27:01\"\n\t}, {\n\t\t\"id\": \"158\",\n\t\t\"p_id\": \"340.256.257\",\n\t\t\"p_sku\": \"ZMEEWALLC-2\",\n\t\t\"product\": \"Z-Wave.Me Funkwandschalter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 16:08:48\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 16:08:48\",\n\t\t\"commentary\": \"NIR: add scene support; RS: discreteStateEAN: 0019962008504\",\n\t\t\"created\": \"2017-03-16 16:08:48\"\n\t}, {\n\t\t\"id\": \"159\",\n\t\t\"p_id\": \"277.256.257\",\n\t\t\"p_sku\": \"ZME_WALLC-S\",\n\t\t\"product\": \"Z-Wave.Me Funkwandschalter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 16:17:49\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 16:17:49\",\n\t\t\"commentary\": \"RS: scenesSupport, discreteState, EAN: 0696859123726\",\n\t\t\"created\": \"2017-03-16 16:17:49\"\n\t}, {\n\t\t\"id\": \"160\",\n\t\t\"p_id\": \"340.256.257\",\n\t\t\"p_sku\": \"POPE009303\",\n\t\t\"product\": \"POPP Wall_C Forever - Funkwandschalter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,30,1,press,B\",\n\t\t\t\"discreteState,0-91,31,1,release,B\",\n\t\t\t\"discreteState,0-91,32,1,hold,B\",\n\t\t\t\"discreteState,0-91,33,2,press,B\",\n\t\t\t\"discreteState,0-91,40,1,press,B\",\n\t\t\t\"discreteState,0-91,41,1,release,B\",\n\t\t\t\"discreteState,0-91,42,1,hold,B\",\n\t\t\t\"discreteState,0-91,43,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-16 16:29:50\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-03-16 16:29:50\",\n\t\t\"commentary\": \"NIR: add scene support; RS: discreteState, EAN: 0019962009303\",\n\t\t\"created\": \"2017-03-16 16:29:50\"\n\t}, {\n\t\t\"id\": \"161\",\n\t\t\"p_id\": \"271.1794.4096\",\n\t\t\"p_sku\": \"FIBEFGDW-002-X\",\n\t\t\"product\": \"Fibaro Door/Window Sensor 2 - all colors\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Door/Window Sensor 2\",\n\t\t\t\"rename,0-113-6,Door/Window Sensor\",\n\t\t\t\"rename,0-113-4-2,Temperature Alarm Heat\",\n\t\t\t\"rename,0-113-4-6,Temperature Alarm Cold\",\n\t\t\t\"hide,0-113-8-11\",\n\t\t\t\"noVDev,0-113-4-254\",\n\t\t\t\"noVDev,0-113-7-254\",\n\t\t\t\"noVDev,0-113-8-254\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-10 15:49:10\",\n\t\t\"author\": \"SPRS\",\n\t\t\"tester\": \"SPRS\",\n\t\t\"tester_last_update\": \"2018-07-10 15:49:10\",\n\t\t\"commentary\": \"SP: rename node and devicesRS: fix typos, hide, noVDev\",\n\t\t\"created\": \"2018-07-10 15:49:10\"\n\t}, {\n\t\t\"id\": \"162\",\n\t\t\"p_id\": \"351.1793.12546\",\n\t\t\"p_sku\": \"MCOEMH7-EH\",\n\t\t\"product\": \"MCOHome Thermostat MH7-EH-EU\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, MCOHOME Thermostat MH7-EH\"],\n\t\t\"author_last_update\": \"2017-03-22 11:57:44\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-03-22 11:57:44\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-06-27 12:06:01\"\n\t}, {\n\t\t\"id\": \"163\",\n\t\t\"p_id\": \"134.3.116\",\n\t\t\"p_sku\": \"AEOEZW116\",\n\t\t\"product\": \"Aeotec Nano Switch 1 Relay\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec NanoSwitch1R\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"setConfig(0,101,15,4);\",\n\t\t\t\"setConfig(0,120,1,1);\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-27 14:03:38\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-03-27 14:03:38\",\n\t\t\"commentary\": \"rename Device, rename widgets \",\n\t\t\"created\": \"2017-11-10 10:12:04\"\n\t}, {\n\t\t\"id\": \"164\",\n\t\t\"p_id\": \"134.2.95\",\n\t\t\"p_sku\": \"AEOEZW095C1A100\",\n\t\t\"product\": \"Aeotec Home Energy Meter - Gen5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Home Energy Meter - Gen 5\",\n\t\t\t\"hide,0-50-7\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"setConfig(0,101,63,4)\",\n\t\t\t\"setConfig(0,111,30,4)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-29 11:40:02\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-29 11:40:02\",\n\t\t\"commentary\": \"rename Node, rename Energy Meter, hide 0-50-7\",\n\t\t\"created\": \"2017-05-30 14:20:50\"\n\t}, {\n\t\t\"id\": \"166\",\n\t\t\"p_id\": \"134.3.111\",\n\t\t\"p_sku\": \"AEOEZW111\",\n\t\t\"product\": \"Aeotec Nano Dimmer ZW111\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Aeotec Nano Dimmer\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"hide,0-113\",\n\t\t\t\"setConfig(0,101,15,4)\",\n\t\t\t\"setConfig(0,80,3,1)\",\n\t\t\t\"rename,0-50-0,Total energy consumption\",\n\t\t\t\"setConfig(0,111,15,4)\",\n\t\t\t\"setConfig(0,120,3,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-03-31 15:13:05\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-03-31 15:00:47\",\n\t\t\"commentary\": \"rename Node, rename meter, hide alarm, config parameter 101,111 and 80\",\n\t\t\"created\": \"2017-06-13 09:18:00\"\n\t}, {\n\t\t\"id\": \"167\",\n\t\t\"p_id\": \"340.4.17\",\n\t\t\"p_sku\": \"POPE700168\",\n\t\t\"product\": \"Popp Z-Rain\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Popp Z-Rain\"],\n\t\t\"author_last_update\": \"2017-04-03 11:25:19\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-04-03 11:25:19\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-04-03 11:25:19\"\n\t}, {\n\t\t\"id\": \"168\",\n\t\t\"p_id\": \"134.3.139\",\n\t\t\"p_sku\": \"AEOEZW139\",\n\t\t\"product\": \"Aeotec Nano Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Nano Switch\",\n\t\t\t\"hide,0-113-4\",\n\t\t\t\"rename,0-37,Switch\",\n\t\t\t\"hide,0-113-4-2\"\n\t\t],\n\t\t\"author_last_update\": \"2017-05-08 15:44:39\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-05-08 15:44:39\",\n\t\t\"commentary\": \"RS: renameNode, hide, rename DeviceID\",\n\t\t\"created\": \"2017-05-08 15:51:05\"\n\t}, {\n\t\t\"id\": \"169\",\n\t\t\"p_id\": \"277.256.257\",\n\t\t\"p_sku\": \"ZMEEWALLC-S\",\n\t\t\"product\": \"Z-Wave.Me Funkwandschalter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,50,1,press,B\",\n\t\t\t\"discreteState,0-91,51,1,release,B\",\n\t\t\t\"discreteState,0-91,52,1,hold,B\",\n\t\t\t\"discreteState,0-91,53,2,press,B\",\n\t\t\t\"discreteState,0-91,60,1,press,B\",\n\t\t\t\"discreteState,0-91,61,1,release,B\",\n\t\t\t\"discreteState,0-91,62,1,hold,B\",\n\t\t\t\"discreteState,0-91,63,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-05-09 11:09:56\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-05-09 11:09:56\",\n\t\t\"commentary\": \"NIR: add scene support; RS: discreteState, EAN: 0019962008504\",\n\t\t\"created\": \"2017-05-09 11:09:56\"\n\t}, {\n\t\t\"id\": \"170\",\n\t\t\"p_id\": \"271.4609.4096\",\n\t\t\"p_sku\": \"FIBEFGCD001\",\n\t\t\"product\": \"Fibaro CO Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Fibaro CO Sensor\",\n\t\t\t\"noVDev,0-156-0\",\n\t\t\t\"noVDev,0-156-2\",\n\t\t\t\"noVDev,0-156-4\",\n\t\t\t\"hide,0-113-8-10\",\n\t\t\t\"hide,0-113-9-1\",\n\t\t\t\"hide,0-113-7-3\",\n\t\t\t\"noVDev,0-113-2-4\",\n\t\t\t\"rename,0-113-2-3,CO Alarm Test\"\n\t\t],\n\t\t\"author_last_update\": \"2017-05-17 10:00:28\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-05-17 10:00:28\",\n\t\t\"commentary\": \"rename Node and moduls, hide Systemalarm, disable 0-156\",\n\t\t\"created\": \"2017-05-17 10:00:28\"\n\t}, {\n\t\t\"id\": \"171\",\n\t\t\"p_id\": \"305.2.3\",\n\t\t\"p_sku\": \"ZIPERGBW2\",\n\t\t\"product\": \"Zipato Bulb 2\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Zipato Bulb 2\"],\n\t\t\"author_last_update\": \"2017-05-17 14:37:19\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-05-17 14:37:19\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-05-17 14:37:19\"\n\t}, {\n\t\t\"id\": \"172\",\n\t\t\"p_id\": \"373.2.14\",\n\t\t\"p_sku\": \"DEVE9355\",\n\t\t\"product\": \"Devolo Door/Window Contact\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Door/Window Contact\"],\n\t\t\"author_last_update\": \"2018-01-03 15:37:43\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-01-03 15:37:43\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-10-16 08:54:57\"\n\t}, {\n\t\t\"id\": \"173\",\n\t\t\"p_id\": \"340.4.2\",\n\t\t\"p_sku\": \"POPE005107\",\n\t\t\"product\": \"Popp Solar Outdoor Siren\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Solar Outdoor Siren\"],\n\t\t\"author_last_update\": \"2017-05-24 16:10:25\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-05-24 16:10:25\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-05-24 16:10:25\"\n\t}, {\n\t\t\"id\": \"174\",\n\t\t\"p_id\": \"345.5.83\",\n\t\t\"p_sku\": \"GOAEZMNHLD1\",\n\t\t\"product\": \"Qubino PWM Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino PWM Thermostat\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\",\n\t\t\t\"setConfig(0,40,1,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2019-01-21 09:54:51\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-21 09:54:51\",\n\t\t\"commentary\": \"rename Node, set Parameter 40\",\n\t\t\"created\": \"2017-05-26 14:51:03\"\n\t}, {\n\t\t\"id\": \"175\",\n\t\t\"p_id\": \"329.4628.772\",\n\t\t\"p_sku\": \"WIDEWPSS\",\n\t\t\"product\": \"WiDom Energy Driven Switch S/C\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,WiDom Switch S/C\"],\n\t\t\"author_last_update\": \"2017-05-30 08:15:18\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-05-30 08:15:18\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-05-31 14:41:34\"\n\t}, {\n\t\t\"id\": \"176\",\n\t\t\"p_id\": \"89.15.1\",\n\t\t\"p_sku\": \"SEC_SWM301\",\n\t\t\"product\": \"Secure Water Meter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Water Meter\",\n\t\t\t\"noVDev,0-49-1\",\n\t\t\t\"noVDev,0-156-4\",\n\t\t\t\"rename,0-50-0,Water Meter\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-02 12:15:50\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-02 12:15:50\",\n\t\t\"commentary\": \"delete Temperature and Head Alarm, rename Node\",\n\t\t\"created\": \"2017-06-02 12:15:50\"\n\t}, {\n\t\t\"id\": \"177\",\n\t\t\"p_id\": \"345.2.82\",\n\t\t\"p_sku\": \"GOAEZMNHAD1\",\n\t\t\"product\": \"Qubino Flush 1 Relay\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode, Qubino Flush 1 Relay\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2019-01-25 10:46:15\",\n\t\t\"author\": \"SPRS\",\n\t\t\"tester\": \"SPRS\",\n\t\t\"tester_last_update\": \"2019-01-25 10:46:15\",\n\t\t\"commentary\": \"SP: renameNodeRS: Association.Set\",\n\t\t\"created\": \"2018-07-17 14:20:27\"\n\t}, {\n\t\t\"id\": \"178\",\n\t\t\"p_id\": \"345.2.81\",\n\t\t\"p_sku\": \"GOAEZMNHBD1\",\n\t\t\"product\": \"Qubinio Flush2 Relays\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Flush2 Relays\",\n\t\t\t\"rename,0-37,Switch all\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-06 15:06:30\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-06 15:06:30\",\n\t\t\"commentary\": \"rename Node and switches\",\n\t\t\"created\": \"2017-06-06 15:06:30\"\n\t}, {\n\t\t\"id\": \"179\",\n\t\t\"p_id\": \"280.3.2\",\n\t\t\"p_sku\": \"TKBETZ68-G\",\n\t\t\"product\": \"TKB Home Wall Plug Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB Home Wall Plug Switch\"],\n\t\t\"author_last_update\": \"2017-06-09 11:14:26\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-09 11:14:26\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-06-09 11:14:26\"\n\t}, {\n\t\t\"id\": \"180\",\n\t\t\"p_id\": \"351.12609.4866\",\n\t\t\"p_sku\": \"MCO_TPS314\",\n\t\t\"product\": \"MCO Home MH-S314 EU (UK)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO S314\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-37,Switch1\",\n\t\t\t\"rename,2-37,Switch2\",\n\t\t\t\"rename,3-37,Switch3\",\n\t\t\t\"rename,4-37,Switch4\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-13 09:40:56\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-13 09:40:56\",\n\t\t\"commentary\": \"rename Node, hide mastermodul, rename Switch\",\n\t\t\"created\": \"2017-09-27 14:26:07\"\n\t}, {\n\t\t\"id\": \"181\",\n\t\t\"p_id\": \"351.2305.12546\",\n\t\t\"p_sku\": \"MCOEMH9-CO2\",\n\t\t\"product\": \"MCO Home CO2 Monitor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home CO2 Monitor\",\n\t\t\t\"rename,0-113-3-1,CO2 Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-17,CO2 Level\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-14 10:13:35\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-14 10:13:35\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-02-14 10:13:35\"\n\t}, {\n\t\t\"id\": \"182\",\n\t\t\"p_id\": \"351.16673.4866\",\n\t\t\"p_sku\": \"MCO_TPS412\",\n\t\t\"product\": \"MCO Home MH-S412\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, MCO MH-S412\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-37,Switch1\",\n\t\t\t\"rename,2-37,Switch2\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-13 10:34:59\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-13 10:34:59\",\n\t\t\"commentary\": \"rename Node and devices, hide master\",\n\t\t\"created\": \"2017-06-13 10:34:59\"\n\t}, {\n\t\t\"id\": \"183\",\n\t\t\"p_id\": \"351.16657.4866\",\n\t\t\"p_sku\": \"MCO_TPS411\",\n\t\t\"product\": \"MCO Home MH-S411\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, MCO MH-S411\",\n\t\t\t\"hide,0-37\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-13 10:34:59\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-13 11:01:36\",\n\t\t\"commentary\": \"rename Node and devices, hide master\",\n\t\t\"created\": \"2017-06-13 11:17:37\"\n\t}, {\n\t\t\"id\": \"184\",\n\t\t\"p_id\": \"351.12577.4866\",\n\t\t\"p_sku\": \"MCO_TPS312\",\n\t\t\"product\": \"MCO Home MH-S412 UK\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, MCO MH-S312\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-37,Switch1\",\n\t\t\t\"rename,2-37,Switch2\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-13 10:34:59\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-13 10:34:59\",\n\t\t\"commentary\": \"rename Node and devices, hide master\",\n\t\t\"created\": \"2017-06-13 10:34:59\"\n\t}, {\n\t\t\"id\": \"185\",\n\t\t\"p_id\": \"316.2.32\",\n\t\t\"p_sku\": \"PHIEPAT02-B\",\n\t\t\"product\": \"Philio 2-in-1 Sensor - Temperature and Humidity\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"hide,0-113-7-3\",\n\t\t\t\"setConfig(0,7,16,1)\",\n\t\t\t\"setCCData(0,132,'security','value',false)\",\n\t\t\t\"renameNode,Philio 2-in-1 Sensor - Temperature and Humidity\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,14,1,1)\",\n\t\t\t\"setConfig(0,20,10,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-06 13:37:56\",\n\t\t\"author\": \"RS NIRAIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2017-09-06 13:37:56\",\n\t\t\"commentary\": \"RS: renameNode, hide device, NIR: setConfig, setCCDataAIVS: Set PArameter 13, 14, 20\",\n\t\t\"created\": \"2017-06-13 14:21:36\"\n\t}, {\n\t\t\"id\": \"186\",\n\t\t\"p_id\": \"316.2.31\",\n\t\t\"p_sku\": \"PHIEPAT02-A\",\n\t\t\"product\": \"Philio 3-in-1 Sensor - Flood, Temperature and Humidity\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-113\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"setConfig(0,7,16,1)\",\n\t\t\t\"setCCData(0,132,'security','value',false)\",\n\t\t\t\"renameNode,Philio 3-in-1 Sensor - Flood, Temperature and Humidity\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,14,1,1)\",\n\t\t\t\"setConfig(0,15,0,1)\",\n\t\t\t\"setConfig(0,20,10,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-06 13:39:44\",\n\t\t\"author\": \"RS NIR\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2017-09-06 13:39:44\",\n\t\t\"commentary\": \"RS: renameNode, hide device, NIR: setConfig, setCCDataAIVS: setParameter 13, 14, 15, 20, no 113 vDev\",\n\t\t\"created\": \"2017-09-28 09:22:59\"\n\t}, {\n\t\t\"id\": \"187\",\n\t\t\"p_id\": \"345.3.82\",\n\t\t\"p_sku\": \"GOAEZMNHCD1\",\n\t\t\"product\": \"Qubino Roller Shutter Insert 2*1 kW with energy meter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Flush Shutter\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-17 14:31:25\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-07-17 14:31:25\",\n\t\t\"commentary\": \"RS: renameNode SP: set Assoc 1\",\n\t\t\"created\": \"2017-06-14 09:45:45\"\n\t}, {\n\t\t\"id\": \"188\",\n\t\t\"p_id\": \"345.1.81\",\n\t\t\"p_sku\": \"GOAEZMNHDD1\",\n\t\t\"product\": \"Qubino Dimmerinsert with energy meter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Flush Dimmer\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"noVDev,0-48-1\",\n\t\t\t\"noVDev,3-48-1\",\n\t\t\t\"noVDev,2-48-1\",\n\t\t\t\"noVDev,1-37\",\n\t\t\t\"noVDev,1-50-2\",\n\t\t\t\"noVDev,1-38\",\n\t\t\t\"noVDev,1-50-0\",\n\t\t\t\"noVDev,1-113-8-8\",\n\t\t\t\"noVDev,2-113-7-8\",\n\t\t\t\"noVDev,3-113-7-8\",\n\t\t\t\"noVDev,1-113-8-254\",\n\t\t\t\"noVDev,2-113-7-254\",\n\t\t\t\"noVDev,3-113-7-254\",\n\t\t\t\"setConfig(0,250,1,1)\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-17 14:19:50\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-17 14:19:50\",\n\t\t\"commentary\": \"RS: renameNode, hide device, noVDev, set Assoc 1\",\n\t\t\"created\": \"2017-07-12 12:09:57\"\n\t}, {\n\t\t\"id\": \"189\",\n\t\t\"p_id\": \"345.3.83\",\n\t\t\"p_sku\": \"GOAEZMNHOD1\",\n\t\t\"product\": \"Qubino Roller Shutter Insert 12-24V DC\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Flush Shutter DC\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-17 13:41:41\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-17 13:41:41\",\n\t\t\"commentary\": \"RS: renameNode, hide device SP: Set Assoc 1\",\n\t\t\"created\": \"2017-06-15 11:52:31\"\n\t}, {\n\t\t\"id\": \"190\",\n\t\t\"p_id\": \"316.1.21\",\n\t\t\"p_sku\": \"PHI_PAN08\",\n\t\t\"product\": \"Philio Relay Insert Blind\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio Relay Insert Blind\",\n\t\t\t\"hide,0-50-4\",\n\t\t\t\"hide,0-50-5\",\n\t\t\t\"hide,0-50-6\",\n\t\t\t\"hide,0-37\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-09 10:52:36\",\n\t\t\"author\": \"RS, SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-09 10:52:36\",\n\t\t\"commentary\": \"RS: renameNode, SP: hide meter, \",\n\t\t\"created\": \"2017-06-20 12:14:00\"\n\t}, {\n\t\t\"id\": \"191\",\n\t\t\"p_id\": \"134.3.121\",\n\t\t\"p_sku\": \"AEOEZW121\",\n\t\t\"product\": \"Aeotec LED Strip\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec LED Strip\"],\n\t\t\"author_last_update\": \"2017-06-22 09:04:09\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-22 09:04:09\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-06-22 09:04:09\"\n\t}, {\n\t\t\"id\": \"192\",\n\t\t\"p_id\": \"96.1.5\",\n\t\t\"p_sku\": \"EVRESP816\",\n\t\t\"product\": \"EverSpring Motion Sensor SP816\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,EverSpring Motion Sensor\",\n\t\t\t\"rename,0-113-7-8,Motion\",\n\t\t\t\"rename,0-113-7-3,Tamper\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-23 11:36:31\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-06-23 11:36:31\",\n\t\t\"commentary\": \"reneme Node and devices\",\n\t\t\"created\": \"2017-06-23 11:36:31\"\n\t}, {\n\t\t\"id\": \"195\",\n\t\t\"p_id\": \"280.785.259\",\n\t\t\"p_sku\": \"TKBETZ69-G\",\n\t\t\"product\": \"TKB Home Power Meter Socket\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB Home Power Meter Socket\"],\n\t\t\"author_last_update\": \"2017-06-28 15:59:59\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-28 15:59:59\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-06-28 15:59:59\"\n\t}, {\n\t\t\"id\": \"196\",\n\t\t\"p_id\": \"96.2.1\",\n\t\t\"p_sku\": \"EVR_HSM02\",\n\t\t\"product\": \"Everspring Door/ Window Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Door/ Window Sensor\",\n\t\t\t\"rename,0-48-1,Everspring D/W Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2017-06-30 13:33:51\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-06-30 13:33:51\",\n\t\t\"commentary\": \"RS: rename\",\n\t\t\"created\": \"2017-06-30 13:33:51\"\n\t}, {\n\t\t\"id\": \"197\",\n\t\t\"p_id\": \"316.1.3\",\n\t\t\"p_sku\": \"PHIEPAN04-1B\",\n\t\t\"product\": \"Philio Double Relay Insert 2*1.5 KW with Metering Function\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio Metering Double Relay Insert\"],\n\t\t\"author_last_update\": \"2017-07-05 10:55:10\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-07-05 10:55:10\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-07-05 10:55:10\"\n\t}, {\n\t\t\"id\": \"198\",\n\t\t\"p_id\": \"2.2.16389\",\n\t\t\"p_sku\": \"DANEHC5\",\n\t\t\"product\": \"Danfoss Hydronic Controller 5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Danfoss HC5\",\n\t\t\t\"rename,6-37,Boiler\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,7-37,Pump\",\n\t\t\t\"rename,1-64,Actuator 1\",\n\t\t\t\"rename,2-64,Actuator 2\",\n\t\t\t\"rename,3-64,Actuator 3\",\n\t\t\t\"rename,4-64,Actuator 4\",\n\t\t\t\"rename,5-64,Actuator 5\",\n\t\t\t\"hide,0-64\",\n\t\t\t\"hide,0-67\",\n\t\t\t\"rename,1-67-1,Temp Actuator 1\",\n\t\t\t\"rename,2-67-1,Temp Actuator 2\",\n\t\t\t\"rename,3-67-1,Temp Actuator 3\",\n\t\t\t\"rename,4-67-1,Temp Actuator 4\",\n\t\t\t\"rename,5-67-1,Temp Actuator 5\"\n\t\t],\n\t\t\"author_last_update\": \"2017-10-11 12:34:16\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-05 13:11:04\",\n\t\t\"commentary\": \"rename devices\",\n\t\t\"created\": \"2017-10-12 12:21:43\"\n\t}, {\n\t\t\"id\": \"199\",\n\t\t\"p_id\": \"89.3.2\",\n\t\t\"p_sku\": \"SEC_SSR302\",\n\t\t\"product\": \"Secure Z-Wave controlled Boiler Actuator (2 Channels)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Boiler Actuator (2 Ch)\"],\n\t\t\"author_last_update\": \"2017-07-05 15:22:46\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-07-05 15:22:46\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-07-05 15:22:46\"\n\t}, {\n\t\t\"id\": \"200\",\n\t\t\"p_id\": \"89.1.4\",\n\t\t\"p_sku\": \"SECESRT323\",\n\t\t\"product\": \"Secure Electronic Room Thermostat with Temperature Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Room Thermostat\",\n\t\t\t\"rename,0-67-1,Thermostat Heat Control\",\n\t\t\t\"rename,0-49-1,Thermostat Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2017-07-06 09:44:11\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-07-06 09:44:11\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2017-07-06 09:44:11\"\n\t}, {\n\t\t\"id\": \"201\",\n\t\t\"p_id\": \"89.13.3\",\n\t\t\"p_sku\": \"SECESES303\",\n\t\t\"product\": \"Secure Temperature and Humidity Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"renameNode, Secure Temp and Hum Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2017-07-06 09:57:39\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-06 09:57:39\",\n\t\t\"commentary\": \"rename devices and node\",\n\t\t\"created\": \"2017-07-06 09:57:39\"\n\t}, {\n\t\t\"id\": \"202\",\n\t\t\"p_id\": \"340.4.16\",\n\t\t\"p_sku\": \"POPE700342\",\n\t\t\"product\": \"Popp 10 year smoke detector\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp 10Y Smoke detector\",\n\t\t\t\"noVDev,0-113-7-3\",\n\t\t\t\"noVDev,0-113-1-2\"\n\t\t],\n\t\t\"author_last_update\": \"2017-07-11 13:54:30\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-11 13:54:30\",\n\t\t\"commentary\": \"rename Node, remove double\",\n\t\t\"created\": \"2017-07-11 13:54:30\"\n\t}, {\n\t\t\"id\": \"203\",\n\t\t\"p_id\": \"265.8198.1569\",\n\t\t\"p_sku\": \"VIS_ZM1702\",\n\t\t\"product\": \"Vision Door Lock with Handle\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Vision Door Lock\"],\n\t\t\"author_last_update\": \"2017-07-13 09:41:00\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-13 09:41:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-07-13 09:41:00\"\n\t}, {\n\t\t\"id\": \"204\",\n\t\t\"p_id\": \"265.8202.2562\",\n\t\t\"p_sku\": \"VIS_ZG8101\",\n\t\t\"product\": \"Vision Garage Door Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Vision Garage Door Sensor\",\n\t\t\t\"rename,0-48-1,Garage Door\"\n\t\t],\n\t\t\"author_last_update\": \"2017-07-13 10:49:31\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-13 10:49:31\",\n\t\t\"commentary\": \"renamen node\",\n\t\t\"created\": \"2017-07-13 10:49:31\"\n\t}, {\n\t\t\"id\": \"205\",\n\t\t\"p_id\": \"280.513.1281\",\n\t\t\"p_sku\": \"TKBETZ10-36\",\n\t\t\"product\": \"TKB Digitel Heating Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB Heating Thermostat\"],\n\t\t\"author_last_update\": \"2017-07-14 08:49:42\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-14 08:49:42\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-09-28 11:32:01\"\n\t}, {\n\t\t\"id\": \"206\",\n\t\t\"p_id\": \"21076.257.33655\",\n\t\t\"p_sku\": \"REM_ZXT120\",\n\t\t\"product\": \"Remotec IR Extender ZXT-120\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Remotec IR Extender\"],\n\t\t\"author_last_update\": \"2017-07-18 08:14:00\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-07-18 08:14:00\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2017-07-18 08:14:00\"\n\t}, {\n\t\t\"id\": \"207\",\n\t\t\"p_id\": \"133.3.1\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"Fakro Electric actuator\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fakro Electric actuator\"],\n\t\t\"author_last_update\": \"2018-11-28 11:46:10\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-11-28 11:46:10\",\n\t\t\"commentary\": \"renameNode\",\n\t\t\"created\": \"2018-11-28 11:46:10\"\n\t}, {\n\t\t\"id\": \"208\",\n\t\t\"p_id\": \"96.4.7\",\n\t\t\"p_sku\": \"EVR_AN1802\",\n\t\t\"product\": \"Everspring mini Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring mini Plug\",\n\t\t\t\"hide,0-113-8-0\",\n\t\t\t\"hide,0-113-8-1\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-05 14:20:12\",\n\t\t\"author\": \"SPRS\",\n\t\t\"tester\": \"SPRS\",\n\t\t\"tester_last_update\": \"2018-02-05 14:20:12\",\n\t\t\"commentary\": \"SP: renameNodeRS: hide\",\n\t\t\"created\": \"2018-02-05 14:20:12\"\n\t}, {\n\t\t\"id\": \"209\",\n\t\t\"p_id\": \"134.1.3\",\n\t\t\"p_sku\": \"AEO_MREM\",\n\t\t\"product\": \"Aeonlabs Minimote\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeonlabs Minimote\"],\n\t\t\"author_last_update\": \"2017-08-11 14:53:42\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-08-11 14:53:42\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-08-11 14:53:42\"\n\t}, {\n\t\t\"id\": \"210\",\n\t\t\"p_id\": \"134.1.3\",\n\t\t\"p_sku\": \"AEO_MREM_B\",\n\t\t\"product\": \"Aeonlabs Minimote\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeonlabs Minimote\"],\n\t\t\"author_last_update\": \"2017-08-11 14:53:42\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-08-11 14:53:42\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-08-11 14:53:42\"\n\t}, {\n\t\t\"id\": \"211\",\n\t\t\"p_id\": \"340.5.2\",\n\t\t\"p_sku\": \"POPE700045\",\n\t\t\"product\": \"POPP Keypad\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,POPP Keypad\",\n\t\t\t\"noVDev,0-113\",\n\t\t\t\"noVDev,0-91\",\n\t\t\t\"rename,0-48-8,Popp Keypad\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-08 13:58:03\",\n\t\t\"author\": \"KARSP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-09-08 13:58:03\",\n\t\t\"commentary\": \"rename device, remove discrete sensor, remove burglar alarm\",\n\t\t\"created\": \"2017-09-08 13:45:37\"\n\t}, {\n\t\t\"id\": \"212\",\n\t\t\"p_id\": \"89.1.3\",\n\t\t\"p_sku\": \"SEC_SRT321\",\n\t\t\"product\": \"Secure Wall Thermostat with LCD Display\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Wall Thermostat\",\n\t\t\t\"noVDev,0-0-B\",\n\t\t\t\"rename,0-67-1,Thermostat Control\",\n\t\t\t\"rename,0-49-1,Thermostat Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2017-08-18 10:39:23\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-08-18 10:39:23\",\n\t\t\"commentary\": \"RS: renameNode, rename, noVDev\",\n\t\t\"created\": \"2017-08-18 10:39:23\"\n\t}, {\n\t\t\"id\": \"213\",\n\t\t\"p_id\": \"411.1.1\",\n\t\t\"p_sku\": \"HEAE5430499\",\n\t\t\"product\": \"HEATIT Z-Wave Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [],\n\t\t\"author_last_update\": \"2017-08-18 13:38:00\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-08-18 13:38:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-08-18 13:38:00\"\n\t}, {\n\t\t\"id\": \"214\",\n\t\t\"p_id\": \"89.16.1\",\n\t\t\"p_sku\": \"SEC_SIR321\",\n\t\t\"product\": \"Secure RF Countdown Timer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Countdown Timer\"],\n\t\t\"author_last_update\": \"2017-08-21 15:07:45\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-08-21 15:07:45\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-08-21 15:07:45\"\n\t}, {\n\t\t\"id\": \"215\",\n\t\t\"p_id\": \"89.16.2\",\n\t\t\"p_sku\": \"SEC_SIR321\",\n\t\t\"product\": \"Secure RF Count Down Timer with Temperature Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Count Down Timer / Temperature\",\n\t\t\t\"setConfig(0,1,1,1)\",\n\t\t\t\"setConfig(0,2,1,1)\",\n\t\t\t\"setConfig(0,3,0,2)\",\n\t\t\t\"setConfig(0,4,1,2)\",\n\t\t\t\"setConfig(0,5,1,2)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-08-22 08:38:06\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-08-22 08:38:06\",\n\t\t\"commentary\": \"rename Node, Config Parameter 1-5\",\n\t\t\"created\": \"2017-08-22 08:38:06\"\n\t}, {\n\t\t\"id\": \"216\",\n\t\t\"p_id\": \"271.514.4098\",\n\t\t\"p_sku\": \"FIBEFGS-222\",\n\t\t\"product\": \"Fibaro Double Relay Switch FGS-222\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro double relay switch\"],\n\t\t\"author_last_update\": \"2018-01-03 15:34:32\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-03 15:34:32\",\n\t\t\"commentary\": \"renameNode\",\n\t\t\"created\": \"2017-08-24 09:04:48\"\n\t}, {\n\t\t\"id\": \"217\",\n\t\t\"p_id\": \"316.1.19\",\n\t\t\"p_sku\": \"PHI_PAN06\",\n\t\t\"product\": \"Philio Double Relay Insert 2x1,5KW\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio Double Relay Insert\",\n\t\t\t\"noVDev,3-37\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"setConfig(0,31,2,1)\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(2,1); self.zway.devices[nodeId].Association.Set(3,1);}\",\n\t\t\t\"self.zway.InjectPacket([nodeId],[0x60,0x08,0x40,0x03])\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-04 12:26:13\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-04 12:26:13\",\n\t\t\"commentary\": \"rename Node, disable instance 0 and 3\",\n\t\t\"created\": \"2017-08-28 10:16:29\"\n\t}, {\n\t\t\"id\": \"218\",\n\t\t\"p_id\": \"138.21.257\",\n\t\t\"p_sku\": \"BENECR2450\",\n\t\t\"product\": \"BeNext Panic Watch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,BeNext Panic Watch\",\n\t\t\t\"rename,0-48-1,Panic Button\",\n\t\t\t\"icon,0-48-1,switch\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-18 11:19:54\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-09-18 11:19:54\",\n\t\t\"commentary\": \"RS: rename, set icon\",\n\t\t\"created\": \"2017-09-18 11:19:54\"\n\t}, {\n\t\t\"id\": \"219\",\n\t\t\"p_id\": \"265.8195.775\",\n\t\t\"p_sku\": \"VISEZS5101-5\",\n\t\t\"product\": \"Vision Shock Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Vision Shock Sensor\",\n\t\t\t\"rename,0-113-7-2,Vibration\",\n\t\t\t\"rename,0-113-7-3,Tamper\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-20 15:33:57\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-09-20 15:33:57\",\n\t\t\"commentary\": \"rename node and device\",\n\t\t\"created\": \"2017-09-20 15:33:57\"\n\t}, {\n\t\t\"id\": \"220\",\n\t\t\"p_id\": \"270.9.1\",\n\t\t\"p_sku\": \"POLELOCKV3\",\n\t\t\"product\": \"Poly Control Dana Lock V3\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Danalock V3\"],\n\t\t\"author_last_update\": \"2018-01-25 13:58:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-25 13:58:08\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-09-27 10:08:08\"\n\t}, {\n\t\t\"id\": \"222\",\n\t\t\"p_id\": \"100.4096.9\",\n\t\t\"p_sku\": \"ZME_05433\",\n\t\t\"product\": \"Z-Wave.me Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-50-0\",\n\t\t\t\"noVDev,0-50-2\",\n\t\t\t\"rename,0-38,Dimmer\",\n\t\t\t\"renameNode,Z-Wave Me Dimmer\"\n\t\t],\n\t\t\"author_last_update\": \"2017-09-29 11:51:31\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-09-29 11:51:31\",\n\t\t\"commentary\": \"rename note, novdev meter\",\n\t\t\"created\": \"2017-09-29 11:51:46\"\n\t}, {\n\t\t\"id\": \"223\",\n\t\t\"p_id\": \"2.2.16394\",\n\t\t\"p_sku\": \"DANEHC10\",\n\t\t\"product\": \"Danfoss Hydronic Controller 10 \",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Danfoss HC10\",\n\t\t\t\"rename,11-37,Boiler\",\n\t\t\t\"rename,12-37,Pump\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-64,Actuator 1\",\n\t\t\t\"rename,2-64,Actuator 2\",\n\t\t\t\"rename,3-64,Actuator 3\",\n\t\t\t\"rename,4-64,Actuator 4\",\n\t\t\t\"rename,5-64,Actuator 5\",\n\t\t\t\"rename,6-64,Actuator 6\",\n\t\t\t\"rename,7-64,Actuator 7\",\n\t\t\t\"rename,8-64,Actuator 8\",\n\t\t\t\"rename,9-64,Actuator 9\",\n\t\t\t\"rename,10-64,Actuator 10\",\n\t\t\t\"hide,0-64\",\n\t\t\t\"hide,0-67\",\n\t\t\t\"rename,1-67-1,Temp Actuator 1\",\n\t\t\t\"rename,2-67-1,Temp Actuator 2\",\n\t\t\t\"rename,3-67-1,Temp Actuator 3\",\n\t\t\t\"rename,4-67-1,Temp Actuator 4\",\n\t\t\t\"rename,5-67-1,Temp Actuator 5\",\n\t\t\t\"rename,6-67-1,Temp Actuator 6\",\n\t\t\t\"rename,7-67-1,Temp Actuator 7\",\n\t\t\t\"rename,8-67-1,Temp Actuator 8\",\n\t\t\t\"rename,9-67-1,Temp Actuator 9\",\n\t\t\t\"rename,10-67-1,Temp Actuator 10\"\n\t\t],\n\t\t\"author_last_update\": \"2017-10-11 12:33:41\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-10-11 12:33:41\",\n\t\t\"commentary\": \"rename devices\",\n\t\t\"created\": \"2017-10-11 12:33:41\"\n\t}, {\n\t\t\"id\": \"224\",\n\t\t\"p_id\": \"89.13.2\",\n\t\t\"p_sku\": \"SECESES302\",\n\t\t\"product\": \"Secure Temperature Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Secure Temperature Sensor\",\n\t\t\t\"rename,0-49-1,Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2017-10-17 11:07:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-10-17 10:24:21\",\n\t\t\"commentary\": \"rename Node, rename device\",\n\t\t\"created\": \"2017-10-17 10:24:21\"\n\t}, {\n\t\t\"id\": \"225\",\n\t\t\"p_id\": \"134.3.98\",\n\t\t\"p_sku\": \"AEOEZW098\",\n\t\t\"product\": \"Aeotec RGBW Bulb\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec RGBW Bulb\"],\n\t\t\"author_last_update\": \"2017-10-17 12:16:24\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-10-17 12:16:24\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-10-17 12:16:24\"\n\t}, {\n\t\t\"id\": \"226\",\n\t\t\"p_id\": \"134.3.132\",\n\t\t\"p_sku\": \"AEOEZW132\",\n\t\t\"product\": \"Aeotec Dual Nano Switch with Meter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Dual Nano Switch\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-37,Aeotec Switch 1\",\n\t\t\t\"rename,2-37,Aeotec Switch 2\",\n\t\t\t\"rename,1-50-2,Current Consumption R1\",\n\t\t\t\"rename,2-50-2,Current Consumption R2\",\n\t\t\t\"rename,1-50-4,Voltage R1\",\n\t\t\t\"rename,2-50-4,Voltage R2\",\n\t\t\t\"rename,1-50-5,Power R1\",\n\t\t\t\"rename,2-50-5,Power R2\",\n\t\t\t\"hide,0-113-4-2\",\n\t\t\t\"hide,0-113-8-6\",\n\t\t\t\"hide,0-113-4-254\",\n\t\t\t\"hide,0-113-8-254\",\n\t\t\t\"rename,0-50-2,Current Consumption All\",\n\t\t\t\"rename,0-50-4,Voltage\",\n\t\t\t\"rename,0-50-5,Power All\",\n\t\t\t\"rename,0-50-0,Total Consumption All\",\n\t\t\t\"rename,1-50-0,Total Consumption R1\",\n\t\t\t\"rename,2-50-0,Total Consumption R2\",\n\t\t\t\"setConfig(0,101,1776399,4)\",\n\t\t\t\"setConfig(0,111,30,4)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-10-25 11:34:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-10-25 11:34:48\",\n\t\t\"commentary\": \"rename devices and Node, hide devices without function, set Parameter 101 and 11\",\n\t\t\"created\": \"2017-10-25 11:34:48\"\n\t}, {\n\t\t\"id\": \"227\",\n\t\t\"p_id\": \"134.4.80\",\n\t\t\"p_sku\": \"AEO_DSD31\",\n\t\t\"product\": \"Aeotec Indoor Siren Gen5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Indoor Siren\",\n\t\t\t\"rename,0-37,Siren\"\n\t\t],\n\t\t\"author_last_update\": \"2017-10-30 15:17:40\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node and Device\",\n\t\t\"created\": \"2017-10-30 15:17:40\"\n\t}, {\n\t\t\"id\": \"228\",\n\t\t\"p_id\": \"89.4.1\",\n\t\t\"p_sku\": \"SEC_SCS317\",\n\t\t\"product\": \"Secure 7 Day Programmable Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Thermostat\",\n\t\t\t\"rename,0-49-1, Temperature\",\n\t\t\t\"reaname,0-67-1,Thermostat\",\n\t\t\t\"hide,0-37\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-03 08:20:28\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-03 08:20:28\",\n\t\t\"commentary\": \"rename Node and devices, hide switch\",\n\t\t\"created\": \"2017-11-03 08:21:02\"\n\t}, {\n\t\t\"id\": \"229\",\n\t\t\"p_id\": \"316.5.49\",\n\t\t\"p_sku\": \"PHIEPAD02\",\n\t\t\"product\": \"Philio Smart Dimmer Socket PAD02\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Smart Dimmer Socket\",\n\t\t\t\"rename,0-38,Dimmer\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-06 10:27:52\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-06 10:27:52\",\n\t\t\"commentary\": \"rename node and widget\",\n\t\t\"created\": \"2017-11-06 10:29:18\"\n\t}, {\n\t\t\"id\": \"230\",\n\t\t\"p_id\": \"362.2.130\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"OOMI Mote\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,OOMI Mote\",\n\t\t\t\"hide,0-113-8-12\",\n\t\t\t\"hide,0-113-8-13\",\n\t\t\t\"hide,0-113-8-14\",\n\t\t\t\"hide,0-113-8-15\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-09 08:30:39\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-09 08:30:39\",\n\t\t\"commentary\": \"rename Node, hide Power Mangement\",\n\t\t\"created\": \"2017-11-09 08:30:39\"\n\t}, {\n\t\t\"id\": \"231\",\n\t\t\"p_id\": \"362.3.96\",\n\t\t\"p_sku\": \"OOMEFT096\",\n\t\t\"product\": \"OOMI Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,252,0,1)\",\n\t\t\t\"setConfig(0,80,2,1)\",\n\t\t\t\"setConfig(0,101,15,4);\",\n\t\t\t\"setConfig(0,111,15,4)\",\n\t\t\t\"renameNode,OOMI Plug\",\n\t\t\t\"noVDev,0-38\",\n\t\t\t\"noVDev,0-51\",\n\t\t\t\"hide,0-50-0\",\n\t\t\t\"hide,0-50-2\",\n\t\t\t\"hide,0-50-4\",\n\t\t\t\"hide,0-50-5\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-05 14:19:23\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-05 14:19:23\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2017-11-09 10:44:31\"\n\t}, {\n\t\t\"id\": \"232\",\n\t\t\"p_id\": \"362.4.118\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"OOMI Range Extender\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,OOMI Range Extender\",\n\t\t\t\"noVDev,0-38\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-10 08:45:46\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-10 08:45:46\",\n\t\t\"commentary\": \"rename Node, deactivate dimmer\",\n\t\t\"created\": \"2017-11-10 08:45:46\"\n\t}, {\n\t\t\"id\": \"233\",\n\t\t\"p_id\": \"362.3.139\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"OOMI In-Wall Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,OOMI IN-WALL-SWITCH\"],\n\t\t\"author_last_update\": \"2017-11-10 10:14:14\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-10 10:14:14\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-11-10 10:14:58\"\n\t}, {\n\t\t\"id\": \"234\",\n\t\t\"p_id\": \"362.3.111\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"OOMI In-Wall Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,OOMI IN-WALL-DIMMER\"],\n\t\t\"author_last_update\": \"2017-11-10 10:14:14\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-10 10:14:14\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-11-10 10:14:58\"\n\t}, {\n\t\t\"id\": \"235\",\n\t\t\"p_id\": \"96.6.1\",\n\t\t\"p_sku\": \"EVR_ST814\",\n\t\t\"product\": \"Everspring Temperature and Humidity Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Temperature and Humidity Sensor\",\n\t\t\t\"noVDev,2-49-5\",\n\t\t\t\"noVDev,1-49-1\",\n\t\t\t\"setConfig(0,8,5,1)\",\n\t\t\t\"setConfig(0,7,5,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-25 14:49:28\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-25 14:49:28\",\n\t\t\"commentary\": \"rename Node, delete inactive dopple devices, set Parameter 7 and 8\",\n\t\t\"created\": \"2017-11-14 15:24:53\"\n\t}, {\n\t\t\"id\": \"236\",\n\t\t\"p_id\": \"373.4.10\",\n\t\t\"p_sku\": \"DEVE9677\",\n\t\t\"product\": \"Devolo Alarmsirene\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,7,1,1)\",\n\t\t\t\"renameNode,Devolo Alarmsirene\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"rename,0-48-1,Siren\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-28 08:34:14\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-28 08:34:14\",\n\t\t\"commentary\": \"ename Node, Alarm on\",\n\t\t\"created\": \"2017-11-28 08:34:14\"\n\t}, {\n\t\t\"id\": \"237\",\n\t\t\"p_id\": \"373.2.32\",\n\t\t\"p_sku\": \"DEVE9663\",\n\t\t\"product\": \"Devolo Luftfeuchtemelder\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Luftfeuchtemelder\"],\n\t\t\"author_last_update\": \"2017-11-28 11:23:46\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-28 11:23:46\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-11-28 11:23:46\"\n\t}, {\n\t\t\"id\": \"238\",\n\t\t\"p_id\": \"373.2.33\",\n\t\t\"p_sku\": \"DEVE9670\",\n\t\t\"product\": \"Devolo Wassermelder\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Wassermelder\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"hide,0-48-6\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-03 15:25:59\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-03 15:25:59\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2017-11-28 12:23:22\"\n\t}, {\n\t\t\"id\": \"239\",\n\t\t\"p_id\": \"373.2.13\",\n\t\t\"p_sku\": \"DEVE9357\",\n\t\t\"product\": \"Devolo Bewegungsmelder\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,7,22,1)\",\n\t\t\t\"renameNode,Devolo Bewegungsmelder\",\n\t\t\t\"hide,0-113-7-3\",\n\t\t\t\"hide,0-113-7-8\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-28 14:06:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-28 14:06:08\",\n\t\t\"commentary\": \"rename Node, Set Parameter 7, hide CC 113\",\n\t\t\"created\": \"2017-11-28 14:06:08\"\n\t}, {\n\t\t\"id\": \"240\",\n\t\t\"p_id\": \"373.256.257\",\n\t\t\"p_sku\": \"DEVE9359\",\n\t\t\"product\": \"Devolo Funkschalter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Funkschalter\",\n\t\t\t\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,50,1,press,B\",\n\t\t\t\"discreteState,0-91,51,1,release,B\",\n\t\t\t\"discreteState,0-91,52,1,hold,B\",\n\t\t\t\"discreteState,0-91,53,2,press,B\",\n\t\t\t\"discreteState,0-91,60,1,press,B\",\n\t\t\t\"discreteState,0-91,61,1,release,B\",\n\t\t\t\"discreteState,0-91,62,1,hold,B\",\n\t\t\t\"discreteState,0-91,63,2,press,B\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-28 15:10:34\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-28 15:10:34\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2017-11-28 15:10:34\"\n\t}, {\n\t\t\"id\": \"241\",\n\t\t\"p_id\": \"2.5.373\",\n\t\t\"p_sku\": \"DEVE9356\",\n\t\t\"product\": \"Devolo Radiator Thermostat\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Radiator Thermostat\",\n\t\t\t\"rename,0-67-1,Thermostat Heat\",\n\t\t\t\"rename,0-49-1,Thermostat Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-29 10:40:02\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-29 10:40:02\",\n\t\t\"commentary\": \"SP: renaming\",\n\t\t\"created\": \"2017-11-29 10:40:02\"\n\t}, {\n\t\t\"id\": \"242\",\n\t\t\"p_id\": \"373.8196.1188\",\n\t\t\"p_sku\": \"DEVE8575\",\n\t\t\"product\": \"Devolo Rauchmelder\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Rauchmelder\",\n\t\t\t\"hide,0-113-7-3\"\n\t\t],\n\t\t\"author_last_update\": \"2017-11-29 12:04:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-29 12:04:08\",\n\t\t\"commentary\": \"rename node, hide tamper\",\n\t\t\"created\": \"2017-11-29 12:04:08\"\n\t}, {\n\t\t\"id\": \"243\",\n\t\t\"p_id\": \"373.256.258\",\n\t\t\"p_sku\": \"DEVE9360\",\n\t\t\"product\": \"Devolo KFOB\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"scenesSupport(0,91,1,4,'S');\",\n\t\t\t\"renameNode,Devolo KFOB\",\n\t\t\t\"discreteState,0-91,10,1,press,B\",\n\t\t\t\"discreteState,0-91,11,1,release,B\",\n\t\t\t\"discreteState,0-91,12,1,hold,B\",\n\t\t\t\"discreteState,0-91,13,2,press,B\",\n\t\t\t\"discreteState,0-91,20,1,press,B\",\n\t\t\t\"discreteState,0-91,21,1,release,B\",\n\t\t\t\"discreteState,0-91,22,1,hold,B\",\n\t\t\t\"discreteState,0-91,23,2,press,B\",\n\t\t\t\"discreteState,0-91,50,1,press,B\",\n\t\t\t\"discreteState,0-91,51,1,release,B\",\n\t\t\t\"discreteState,0-91,52,1,hold,B\",\n\t\t\t\"discreteState,0-91,53,2,press,B\",\n\t\t\t\"discreteState,0-91,60,1,press,B\",\n\t\t\t\"discreteState,0-91,61,1,release,B\",\n\t\t\t\"discreteState,0-91,62,1,hold,B\",\n\t\t\t\"discreteState,0-91,63,2,press,B\",\n\t\t\t\"rename,0-91,POPP KFOB\"\n\t\t],\n\t\t\"author_last_update\": \"2016-10-05 08:49:38\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-11-29 13:33:54\",\n\t\t\"commentary\": \"add scene support\",\n\t\t\"created\": \"2017-11-29 13:33:54\"\n\t}, {\n\t\t\"id\": \"244\",\n\t\t\"p_id\": \"271.4865.4096\",\n\t\t\"p_sku\": \"FIBEFGT-001\",\n\t\t\"product\": \"Fibaro Heat Controller\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,1-64\",\n\t\t\t\"noVDev,0-67-1\",\n\t\t\t\"hide,0-113\",\n\t\t\t\"noVDev,0-49-1\",\n\t\t\t\"renameNode,Fibaro Thermostat\",\n\t\t\t\"hide,1-113\",\n\t\t\t\"hide,2-113\"\n\t\t],\n\t\t\"author_last_update\": \"2017-12-04 09:15:20\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-12-04 09:15:20\",\n\t\t\"commentary\": \"rename node, hide elements\",\n\t\t\"created\": \"2017-12-04 09:15:20\"\n\t}, {\n\t\t\"id\": \"245\",\n\t\t\"p_id\": \"65535.3.4\",\n\t\t\"p_sku\": \"TKBETZ55-D\",\n\t\t\"product\": \"TKBHOME single/dual dimmer switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, TKB single/dual dimmer switc\"],\n\t\t\"author_last_update\": \"2016-11-21 15:42:11\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-12-07 10:20:38\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-22 12:28:33\"\n\t}, {\n\t\t\"id\": \"246\",\n\t\t\"p_id\": \"362.2.112\",\n\t\t\"p_sku\": \"OOMEFT112\",\n\t\t\"product\": \"OOMI Door Window Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,252,0,1);\",\n\t\t\t\"noVDev,0-113\",\n\t\t\t\"rename,0-48-1,Door/Window\",\n\t\t\t\"renameNode,OOMI Door Window Sensor 6\",\n\t\t\t\"setConfig(0,121,2,1);\",\n\t\t\t\"icon,0-48-1,door\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-10 14:57:06\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-10 14:57:06\",\n\t\t\"commentary\": \"don't create Alarm devices, change node name, change configuration,rename device 0-48-1chance icon\",\n\t\t\"created\": \"2017-12-07 15:48:43\"\n\t}, {\n\t\t\"id\": \"247\",\n\t\t\"p_id\": \"134.3.140\",\n\t\t\"p_sku\": \"AEOEZW140\",\n\t\t\"product\": \"Aeotec Dual Nano Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Dual Nano Switch\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"hide,0-113-4-2\",\n\t\t\t\"setConfig(0,80,2,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2017-12-13 10:38:10\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2017-12-13 10:38:10\",\n\t\t\"commentary\": \"rename Node, rename devices, hide management, set parameter 80\",\n\t\t\"created\": \"2017-12-13 10:38:10\"\n\t}, {\n\t\t\"id\": \"248\",\n\t\t\"p_id\": \"134.2.5\",\n\t\t\"p_sku\": \"SCHEZHS05\",\n\t\t\"product\": \"SCHWAIGER - 4 in 1 Multi Sensor Outdoor IP43\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"enameNode,4 in 1 Multi Sensor Outdoo\"],\n\t\t\"author_last_update\": \"2017-12-15 10:54:23\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-12-15 10:54:23\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2017-12-15 10:54:23\"\n\t}, {\n\t\t\"id\": \"249\",\n\t\t\"p_id\": \"96.3.3\",\n\t\t\"p_sku\": \"EVR_AD1472\",\n\t\t\"product\": \"Everspring Wall Plug Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Wall Plug Dimmer\",\n\t\t\t\"hide,0-113-8-0\",\n\t\t\t\"hide,0-113-8-1\"\n\t\t],\n\t\t\"author_last_update\": \"2017-12-29 14:36:26\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2017-12-29 14:36:26\",\n\t\t\"commentary\": \"RS: renameNode, hide\",\n\t\t\"created\": \"2017-12-29 14:36:26\"\n\t}, {\n\t\t\"id\": \"250\",\n\t\t\"p_id\": \"271.1793.16385\",\n\t\t\"p_sku\": \"FIBEFGK-101-ZW5-RUFIBEFGK-103-ZW5-RUFIBEFGK-106-ZW5-RU\",\n\t\t\"product\": \"Fibaro Door/Window Sensor G5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Door/Window Sensor G5\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"rename,0-113-6,Door/Window Sensor\",\n\t\t\t\"noVDev,0-156-0\",\n\t\t\t\"noVDev,0-48-1\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].MultiChannelAssociation.Remove(1,1,0);self.zway.devices[nodeId].Association.Set(1,1);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-03 10:58:01\",\n\t\t\"author\": \"AIVS,NIR\",\n\t\t\"tester\": \"AIVS,NIR\",\n\t\t\"tester_last_update\": \"2018-01-03 10:58:01\",\n\t\t\"commentary\": \"rename node,no create 0-156-0,no create 0-48-1,rename Tamper and Sensor,Update - To make security reports work: remove node 1 from MultiChannelAssociation group 1 and add node 1 to Association group 1\",\n\t\t\"created\": \"2017-08-10 12:21:47\"\n\t}, {\n\t\t\"id\": \"251\",\n\t\t\"p_id\": \"271.1026.4098\",\n\t\t\"p_sku\": \"FIBEFGS-212\",\n\t\t\"product\": \"FIBARO Single Switch - 1*2.5 kW\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,FIBARO Single Switch - 1*2.5 kW\"],\n\t\t\"author_last_update\": \"2018-01-04 11:25:00\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-01-04 11:25:00\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-01-04 11:25:00\"\n\t}, {\n\t\t\"id\": \"252\",\n\t\t\"p_id\": \"351.2561.12546\",\n\t\t\"p_sku\": \"MCOEMH10-PM\",\n\t\t\"product\": \"MCO Home PM2.5 Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home PM2.5 Sensor\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-35,Particulate Matter\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-11 10:40:15\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-01-11 10:40:15\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-01-04 12:35:10\"\n\t}, {\n\t\t\"id\": \"253\",\n\t\t\"p_id\": \"351.1810.20738\",\n\t\t\"p_sku\": \"MCOEMH7H-WH2\",\n\t\t\"product\": \"MCO Home - Water Heating Thermostat with humidity sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Water Heating Thermostat with humidity sensor\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-64,Thermostat operation\",\n\t\t\t\"rename,0-67-1,Thermostat Heat\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-19 13:08:57\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-19 13:08:57\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-01-04 15:31:41\"\n\t}, {\n\t\t\"id\": \"254\",\n\t\t\"p_id\": \"89.1.5\",\n\t\t\"p_sku\": \"SECESRT321-5\",\n\t\t\"product\": \"Secure Wall Thermostat with LCD Display\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Wall Thermostat\",\n\t\t\t\"noVDev,0-0-B\",\n\t\t\t\"rename,0-67-1,Thermostat Control\",\n\t\t\t\"rename,0-49-1,Thermostat Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-10 13:31:33\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-10 13:31:33\",\n\t\t\"commentary\": \"RS: renameNode, rename, noVDev\",\n\t\t\"created\": \"2018-01-05 10:39:42\"\n\t}, {\n\t\t\"id\": \"255\",\n\t\t\"p_id\": \"89.3.6\",\n\t\t\"p_sku\": \"SECESSR302\",\n\t\t\"product\": \"Secure Z-Wave controlled Boiler Actuator (2 Channels)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Boiler Actuator (2 Ch)\"],\n\t\t\"author_last_update\": \"2018-01-05 12:14:01\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-05 12:14:01\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-01-05 12:14:01\"\n\t}, {\n\t\t\"id\": \"256\",\n\t\t\"p_id\": \"362.3.121\",\n\t\t\"p_sku\": \"OOMEFT121\",\n\t\t\"product\": \"OOMI Colorstripe\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,252,0,1)\",\n\t\t\t\"renameNode,OOMI Colorstrip\"\n\t\t],\n\t\t\"author_last_update\": \"2019-01-04 10:58:12\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-04 10:58:12\",\n\t\t\"commentary\": \"rename Node, disable parameter security\",\n\t\t\"created\": \"2018-01-09 13:24:28\"\n\t}, {\n\t\t\"id\": \"257\",\n\t\t\"p_id\": \"410.3.10\",\n\t\t\"p_sku\": \"SENECOMFORTSENEDRIPS\",\n\t\t\"product\": \"Sensative Strips Comfort / Drips\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Sensative Multisensor\",\n\t\t\t\"hide,0-113-4-2\",\n\t\t\t\"hide,0-113-4-6\",\n\t\t\t\"hide,0-113-7-4\",\n\t\t\t\"rename,0-113-5-2,Water Alarm\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"rename,0-49-31,Moisture\",\n\t\t\t\"rename,0-113-4-2,Heat Alarm 1\",\n\t\t\t\"rename,0-113-4-6,Heat Alarm 2\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-113-7-4,Burglar Alarm\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-06 15:17:49\",\n\t\t\"author\": \"SPRS\",\n\t\t\"tester\": \"SPRS\",\n\t\t\"tester_last_update\": \"2018-04-19 10:51:53\",\n\t\t\"commentary\": \"SP: renameNodeRS: renameNode, hide, rename\",\n\t\t\"created\": \"2018-04-19 10:51:53\"\n\t}, {\n\t\t\"id\": \"258\",\n\t\t\"p_id\": \"362.2.122\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"OOMI WATERSENSOR\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,OOMI WATERSENSOR\",\n\t\t\t\"hide,0-113-4-2\",\n\t\t\t\"hide,0-113-4-6\",\n\t\t\t\"noVDev,0-113-5-2\",\n\t\t\t\"noVDev,1-113-5-0\",\n\t\t\t\"noVDev,2-113-5-0\",\n\t\t\t\"rename,0-113-4-2,Heat Alarm\",\n\t\t\t\"rename,0-113-4-6,Heat Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-113-7-3,Burglar Alarm\",\n\t\t\t\"rename,1-113-5-2,Water Alarm\",\n\t\t\t\"rename,2-113-5-2,Water Alarm\",\n\t\t\t\"setConfig(0,252,0,1);\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-12 10:05:55\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-01-12 10:05:55\",\n\t\t\"commentary\": \"RS: renameNode, rename, noVDev, hide, setConfig\",\n\t\t\"created\": \"2018-01-12 10:05:55\"\n\t}, {\n\t\t\"id\": \"259\",\n\t\t\"p_id\": \"373.1.18\",\n\t\t\"p_sku\": \"DEVE9914\",\n\t\t\"product\": \"Devolo Wall Plug 2.0\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Devolo Wall Plug 2.0\",\n\t\t\t\"rename,0-37,Wall Plug Switch\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-12 11:16:19\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-01-12 11:16:19\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-01-12 11:16:19\"\n\t}, {\n\t\t\"id\": \"260\",\n\t\t\"p_id\": \"362.2.100\",\n\t\t\"p_sku\": \"OOMEFT100\",\n\t\t\"product\": \"OOMI Multisensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"setConfig(0,252,0,1);\",\n\t\t\t\"setConfig(0,5,2,1);\",\n\t\t\t\"setConfig(0,3,10,2);\",\n\t\t\t\"setconfig(0,40,1,1);\",\n\t\t\t\"noVDev,0-113-7-8\",\n\t\t\t\"rename,0-48-1,PIR\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"renameNode,OOMI Multisensor Gen 6\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-16 09:17:36\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-16 09:17:36\",\n\t\t\"commentary\": \"don't create Alarm device 113-7-8, change node name, change configuration,rename tamper and motion sensor\",\n\t\t\"created\": \"2018-01-16 08:51:53\"\n\t}, {\n\t\t\"id\": \"261\",\n\t\t\"p_id\": \"361.1.1\",\n\t\t\"p_sku\": \"POPE005206\",\n\t\t\"product\": \"Popp Z-Weather\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Z-Weather\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-50-0,Electric Meter\",\n\t\t\t\"hide,0-50-0\",\n\t\t\t\"rename,0-50-3,Counter\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-6,Velocity\",\n\t\t\t\"rename,0-49-9,Barometric Pressure\",\n\t\t\t\"rename,0-49-11,Dew Point\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-18 10:12:05\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-18 10:12:05\",\n\t\t\"commentary\": \"rename devices and node\",\n\t\t\"created\": \"2018-01-18 10:12:05\"\n\t}, {\n\t\t\"id\": \"262\",\n\t\t\"p_id\": \"277.256.1024\",\n\t\t\"p_sku\": \"POPE005206\",\n\t\t\"product\": \"Popp Z-Weather\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Z-Weather\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-50-0,Electric Meter\",\n\t\t\t\"hide,0-50-0\",\n\t\t\t\"rename,0-50-3,Counter\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-6,Velocity\",\n\t\t\t\"rename,0-49-9,Barometric Pressure\",\n\t\t\t\"rename,0-49-11,Dew Point\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-18 10:12:05\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-18 10:12:05\",\n\t\t\"commentary\": \"rename devices and node\",\n\t\t\"created\": \"2018-01-18 10:12:05\"\n\t}, {\n\t\t\"id\": \"263\",\n\t\t\"p_id\": \"340.256.1024\",\n\t\t\"p_sku\": \"POPE005206\",\n\t\t\"product\": \"Popp Z-Weather\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Z-Weather\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-50-0,Electric Meter\",\n\t\t\t\"rename,0-50-3,Counter\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-6,Velocity\",\n\t\t\t\"rename,0-49-9,Barometric Pressure\",\n\t\t\t\"rename,0-49-11,Dew Point\"\n\t\t],\n\t\t\"author_last_update\": \"2018-01-18 10:52:54\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-01-18 10:52:54\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-01-18 10:52:54\"\n\t}, {\n\t\t\"id\": \"264\",\n\t\t\"p_id\": \"351.2305.513\",\n\t\t\"p_sku\": \"MCOEMH9-CO2\",\n\t\t\"product\": \"MCO Home CO2 Monitor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home CO2 Monitor\",\n\t\t\t\"rename,0-113-3-1,CO2 Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-17,CO2 Level\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-14 10:14:49\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-14 10:14:49\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-02-14 10:14:49\"\n\t}, {\n\t\t\"id\": \"265\",\n\t\t\"p_id\": \"89.3.5\",\n\t\t\"p_sku\": \"SECESSR303-5\",\n\t\t\"product\": \"Secure Receiver with Relay SSR303\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Secure Receiver\"],\n\t\t\"author_last_update\": \"2018-01-26 08:53:36\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-01-26 08:53:36\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"0000-00-00 00:00:00\"\n\t}, {\n\t\t\"id\": \"266\",\n\t\t\"p_id\": \"138.24.256\",\n\t\t\"p_sku\": \"BEN_PlDi\",\n\t\t\"product\": \"BeNext Wall Plug with Dimmer Function\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,BeNext Plug Dimmer\",\n\t\t\t\"rename,0-38,Dimmer\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-49-32,Current frequency\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-01 09:12:12\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-01 09:12:12\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-02-01 09:12:12\"\n\t}, {\n\t\t\"id\": \"267\",\n\t\t\"p_id\": \"96.11.1\",\n\t\t\"p_sku\": \"EVR_ST812\",\n\t\t\"product\": \"Everspring ST812 Flood Detector\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Flood Sensor\"],\n\t\t\"author_last_update\": \"2018-02-05 13:41:01\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-05 13:41:01\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-02-05 13:41:01\"\n\t}, {\n\t\t\"id\": \"268\",\n\t\t\"p_id\": \"96.12.1\",\n\t\t\"p_sku\": \"EVR_SE812\",\n\t\t\"product\": \"Everspring SE812 Indoor Siren\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Indoor Siren\"],\n\t\t\"author_last_update\": \"2018-02-05 14:16:13\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-05 14:16:13\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2018-02-05 14:16:13\"\n\t}, {\n\t\t\"id\": \"269\",\n\t\t\"p_id\": \"134.2.122\",\n\t\t\"p_sku\": \"AEOEZW122\",\n\t\t\"product\": \"Aeotec Water Sensor 6\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Water Sensor 6\",\n\t\t\t\"hide,0-113-4-2\",\n\t\t\t\"hide,0-113-4-6\",\n\t\t\t\"noVDev,0-113-5-2\",\n\t\t\t\"rename,0-113-7-3,Burglar Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,2-113-5-2,Water Alarm\",\n\t\t\t\"rename,1-113-5-2,Water Alarm\",\n\t\t\t\"rename,0-113-4-6,Heat Alarm\",\n\t\t\t\"rename,0-113-4-2,Heat Alarm\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-06 14:27:24\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-06 14:27:24\",\n\t\t\"commentary\": \"RS: renameNode, rename, noVDev, hide\",\n\t\t\"created\": \"2018-02-06 14:27:24\"\n\t}, {\n\t\t\"id\": \"270\",\n\t\t\"p_id\": \"520.512.11\",\n\t\t\"p_sku\": \"HNKESCN04\",\n\t\t\"product\": \"Hank Four-Key Scene Contoller\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Hank Scene Controller\"],\n\t\t\"author_last_update\": \"2018-02-06 15:34:24\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-06 15:34:24\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2018-02-06 15:34:24\"\n\t}, {\n\t\t\"id\": \"271\",\n\t\t\"p_id\": \"520.512.9\",\n\t\t\"p_sku\": \"HNKESCN01\",\n\t\t\"product\": \"Hank One-Key Scene Contoller\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Hank Scene Controller\"],\n\t\t\"author_last_update\": \"2018-02-08 14:27:55\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-08 14:27:55\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2018-02-08 14:27:55\"\n\t}, {\n\t\t\"id\": \"272\",\n\t\t\"p_id\": \"520.512.15\",\n\t\t\"p_sku\": \"HNKEFLD01\",\n\t\t\"product\": \"Hank Flood Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Hank Flood Sensor\",\n\t\t\t\"rename,0-48-5,Heat\",\n\t\t\t\"hide,0-48-5\",\n\t\t\t\"rename,0-48-7,Freeze\",\n\t\t\t\"hide,0-48-7\",\n\t\t\t\"rename,0-113-5-2,Water Alarm\",\n\t\t\t\"rename,0-113-7-9,Burglar Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-48-8,Tamper\",\n\t\t\t\"noVDev,0-48-6\",\n\t\t\t\"noVDev,0-113-4-2\",\n\t\t\t\"noVDev,0-113-4-6\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"setConfig(0,14,1,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-27 14:53:20\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-27 14:53:20\",\n\t\t\"commentary\": \"RS: renameNode, rename, noVDev, hide, set parameter 14\",\n\t\t\"created\": \"2018-02-08 15:34:47\"\n\t}, {\n\t\t\"id\": \"273\",\n\t\t\"p_id\": \"Hank Motion Sensor\",\n\t\t\"p_sku\": \"HNKEMS02\",\n\t\t\"product\": \"Hank Motion Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Hank Motion Sensor\",\n\t\t\t\"noVDev,0-48-12\",\n\t\t\t\"noVDev,0-48-8\",\n\t\t\t\"rename,0-113-7-9,Tamper\",\n\t\t\t\"rename,0-113-7-8,Motion\",\n\t\t\t\"setConfig(0,14,1,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-09 08:54:19\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-09 08:54:19\",\n\t\t\"commentary\": \"rename node and devices, remove death devices\",\n\t\t\"created\": \"2018-02-09 08:54:19\"\n\t}, {\n\t\t\"id\": \"274\",\n\t\t\"p_id\": \"520.256.10\",\n\t\t\"p_sku\": \"HNKESO05\",\n\t\t\"product\": \"Hank Smart Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Hank Smart Plug\",\n\t\t\t\"rename,0-37,Switch\",\n\t\t\t\"rename,0-50-0,Electric Meter kWh\",\n\t\t\t\"rename,0-50-2,Electric Meter W\",\n\t\t\t\"rename,0-50-4,Electric Meter V\",\n\t\t\t\"rename,0-50-5,Electric Meter A\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-09 09:04:58\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-09 09:04:58\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-02-09 09:04:58\"\n\t}, {\n\t\t\"id\": \"275\",\n\t\t\"p_id\": \"600.3.4226\",\n\t\t\"p_sku\": \"NEOEDS01Z\",\n\t\t\"product\": \"NEO Coolcam Door / Window Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,NEO Coolcam D/W Sensor\",\n\t\t\t\"noVDev,0-113-6\",\n\t\t\t\"rename,0-48-10,Door/Window Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-12 15:14:12\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-12 15:14:12\",\n\t\t\"commentary\": \"rename node, delate double device, rename device\",\n\t\t\"created\": \"2018-02-12 15:14:12\"\n\t}, {\n\t\t\"id\": \"276\",\n\t\t\"p_id\": \"600.3.4227\",\n\t\t\"p_sku\": \"NEOEMS01ZNEOEMS02Z\",\n\t\t\"product\": \"NEO Coolcam - Motion Sensor (PIR) & NEO Coolcam - Motion Sensor (PIR) with temperature sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,NEO Coolcam - Motion Sensor (PIR)\",\n\t\t\t\"rename,0-48-12,Motion\",\n\t\t\t\"rename,0-113-7-8,Burglar Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-3,Luminiscence\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-15 11:48:06\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-05-15 11:48:06\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-05-15 11:48:06\"\n\t}, {\n\t\t\"id\": \"277\",\n\t\t\"p_id\": \"600.3.4232\",\n\t\t\"p_sku\": \"NEOEAB01Z\",\n\t\t\"product\": \"Neo Coolcam Siren\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-37,Siren\",\n\t\t\t\"renameNode,Neo Siren\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-13 14:34:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-13 14:34:08\",\n\t\t\"commentary\": \"rename node and device\",\n\t\t\"created\": \"2018-02-13 14:34:08\"\n\t}, {\n\t\t\"id\": \"278\",\n\t\t\"p_id\": \"351.12577.20738\",\n\t\t\"p_sku\": \"MCOETPS312\",\n\t\t\"product\": \"MCO Home Glass Touch Switch (2 Buttons) British Standard\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Glass Touch Switch (2 Buttons) British Standard\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\",\n\t\t\t\"rename,0-91,Control\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-14 13:44:01\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-14 13:44:01\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide\",\n\t\t\"created\": \"2018-02-14 13:44:01\"\n\t}, {\n\t\t\"id\": \"279\",\n\t\t\"p_id\": \"351.16657.20738\\t\",\n\t\t\"p_sku\": \"MCOETPS411\",\n\t\t\"product\": \"MCO Home Glass Touch Switch (1 Button)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Glass Touch Switch (1 Button)\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,0-91,Control\",\n\t\t\t\"rename,1-37,Switch\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-14 14:59:58\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-14 14:59:58\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide\",\n\t\t\"created\": \"2018-02-14 14:59:58\"\n\t}, {\n\t\t\"id\": \"280\",\n\t\t\"p_id\": \"351.2561.12546\",\n\t\t\"p_sku\": \"MCOEMH10-PM-230\",\n\t\t\"product\": \"MCO Home PM2.5 Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home PM2.5 Sensor\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-35,Particulate Matter\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-15 10:17:43\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-15 10:17:43\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-02-15 10:17:43\"\n\t}, {\n\t\t\"id\": \"281\",\n\t\t\"p_id\": \"351.16673.20738\",\n\t\t\"p_sku\": \"MCOETPS412\",\n\t\t\"product\": \"MCO Home Glass Touch Switch (2 Buttons)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Glass Touch Switch (2 Buttons)\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,0-91,Control\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-15 10:53:48\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-15 10:53:48\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide\",\n\t\t\"created\": \"2018-02-15 10:53:48\"\n\t}, {\n\t\t\"id\": \"282\",\n\t\t\"p_id\": \"351.12609.20738\",\n\t\t\"p_sku\": \"MCOETPS314\",\n\t\t\"product\": \"MCO Home Glass Touch Switch (4 Buttons) British Standard\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Glass Touch Switch (4 Buttons) British Standard\",\n\t\t\t\"rename,0-91,Control\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\",\n\t\t\t\"rename,3-37,Switch 3\",\n\t\t\t\"rename,4-37,Switch 4\",\n\t\t\t\"hide,0-37\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-15 11:28:37\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-15 11:28:37\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide\",\n\t\t\"created\": \"2018-02-15 11:28:37\"\n\t}, {\n\t\t\"id\": \"284\",\n\t\t\"p_id\": \"351.1794.20738\",\n\t\t\"p_sku\": \"MCOEMH7H-EH2\",\n\t\t\"product\": \"MCO Home - Electrical Heating Thermostat with humidity sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Electrical Heating Thermostat with humidity sensor\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-64,Thermostat operation\",\n\t\t\t\"rename,0-67-1,Thermostat Heat\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-19 11:47:13\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-02-19 11:47:13\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-02-15 12:29:40\"\n\t}, {\n\t\t\"id\": \"286\",\n\t\t\"p_id\": \"625.1.6772\",\n\t\t\"p_sku\": \"STEERSLEDD2\",\n\t\t\"product\": \"Steinel Indoor Light\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Steinel Indoor Light\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"noVDev,0-113-9-3\",\n\t\t\t\"noVDev,0-113-9-4\",\n\t\t\t\"noVDev,0-113-9-254\",\n\t\t\t\"noVDev,0-113-7-8\",\n\t\t\t\"rename,1-37, Light\",\n\t\t\t\"rename,2-113-7-8,Motion\",\n\t\t\t\"rename,3-49-6,Luminiscence\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-15 13:49:16\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-15 13:49:16\",\n\t\t\"commentary\": \"renmane node, delete burgler and alarm devices, rename devices\",\n\t\t\"created\": \"2018-02-15 13:49:16\"\n\t}, {\n\t\t\"id\": \"287\",\n\t\t\"p_id\": \"316.1.18\",\n\t\t\"p_sku\": \"PHIEPAN04-1B\",\n\t\t\"product\": \"Philio Double Relay Insert 2*1.5 kW with Metering Function\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"hide,3-37\",\n\t\t\t\"rename,0-37,Switch All\",\n\t\t\t\"rename,1-37,Switch 1\",\n\t\t\t\"rename,2-37,Switch 2\",\n\t\t\t\"renameNode,Philio Double Relay Insert 2*1.5 kW with Metering Function\",\n\t\t\t\"setConfig(0,31,2,1)\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(2,1); self.zway.devices[nodeId].Association.Set(3,1);}\",\n\t\t\t\"self.zway.InjectPacket([nodeId],[0x60,0x08,0x40,0x03])\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-10 11:40:24\",\n\t\t\"author\": \"RSSP\",\n\t\t\"tester\": \"RSSP\",\n\t\t\"tester_last_update\": \"2018-04-10 11:40:24\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide\",\n\t\t\"created\": \"2018-02-16 15:44:23\"\n\t}, {\n\t\t\"id\": \"288\",\n\t\t\"p_id\": \"625.2.6770\",\n\t\t\"p_sku\": \"STEEIS1402\",\n\t\t\"product\": \"Steinel Motion Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Steinel Motion Sensor\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"hide,0-113-9-254\",\n\t\t\t\"hide,0-113-9-4\",\n\t\t\t\"hide,0-113-9-3\",\n\t\t\t\"hide,0-113-7-8\",\n\t\t\t\"rename,3-37,Switch\",\n\t\t\t\"rename,1-113-7-8,Motion\",\n\t\t\t\"rename,2-49-3,Luminiscence\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-14 12:03:46\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-08-14 12:03:46\",\n\t\t\"commentary\": \"rename Node, rename device, delete death device\",\n\t\t\"created\": \"2018-02-16 09:27:29\"\n\t}, {\n\t\t\"id\": \"289\",\n\t\t\"p_id\": \"625.1.6771\",\n\t\t\"p_sku\": \"STEEXLED\",\n\t\t\"product\": \"Steinel XLED home 2\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Steinel XLED 2\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"noVDev,0-113-7-8\",\n\t\t\t\"noVDev,0-113-9-3\",\n\t\t\t\"noVDev,0-113-9-4\",\n\t\t\t\"noVDev,0-113-9-254\",\n\t\t\t\"noVDev,0-49-3\",\n\t\t\t\"rename,3-49-3,Luminiscence\",\n\t\t\t\"rename,1-37,LED light\",\n\t\t\t\"rename,2-113-7-8,Motion\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-16 11:40:33\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-16 11:40:33\",\n\t\t\"commentary\": \"rename node and device, delete double devices\",\n\t\t\"created\": \"2018-02-16 11:40:33\"\n\t}, {\n\t\t\"id\": \"290\",\n\t\t\"p_id\": \"625.1.6773\",\n\t\t\"p_sku\": \"STEEL810\",\n\t\t\"product\": \"Steinel Senor-Switched Outdoor Light\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Seinel Outdoor light\",\n\t\t\t\"noVDev,0-113-7-8\",\n\t\t\t\"noVDev,0-113-9-3\",\n\t\t\t\"noVDev,0-113-9-4\",\n\t\t\t\"noVDev,0-113-9-254\",\n\t\t\t\"noVDev,0-49-3\",\n\t\t\t\"rename,1-38,Light\",\n\t\t\t\"rename,2-113-7-8,Motion\",\n\t\t\t\"rename,3-49-3,Luminiscence\",\n\t\t\t\"noVDev,0-38\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-16 14:10:55\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-16 14:10:55\",\n\t\t\"commentary\": \"rename node and device, hide other devices\",\n\t\t\"created\": \"2018-02-16 14:10:55\"\n\t}, {\n\t\t\"id\": \"291\",\n\t\t\"p_id\": \"134.2.29\",\n\t\t\"p_sku\": \"FOXEDWSENS\",\n\t\t\"product\": \"Foxx Project Door/Window Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Foxx Door/Window Sensor\",\n\t\t\t\"rename,0-48-1,Door/Window Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-27 10:57:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-27 10:57:48\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-02-27 10:57:48\"\n\t}, {\n\t\t\"id\": \"292\",\n\t\t\"p_id\": \"134.2.45\",\n\t\t\"p_sku\": \"FOXEFLOOD\",\n\t\t\"product\": \"Foxx Project Flood Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Foxx Water Sensor\",\n\t\t\t\"rename,0-48-1,Water detection\"\n\t\t],\n\t\t\"author_last_update\": \"2018-02-27 11:09:30\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-02-27 11:09:30\",\n\t\t\"commentary\": \"rename node and device\",\n\t\t\"created\": \"2018-02-27 11:09:30\"\n\t}, {\n\t\t\"id\": \"293\",\n\t\t\"p_id\": \"96.13.1\",\n\t\t\"p_sku\": \"TECE9504\",\n\t\t\"product\": \"Everspring/TechniSat RM1\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"enameNode,Everspring Smoke Detecto\"],\n\t\t\"author_last_update\": \"2018-03-12 09:24:05\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-03-12 09:24:05\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2018-03-12 09:24:05\"\n\t}, {\n\t\t\"id\": \"294\",\n\t\t\"p_id\": \"608.32770.4096\",\n\t\t\"p_sku\": \"HEIEHS1SA\",\n\t\t\"product\": \"Heiman Smart Smoke Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heiman Smart Smoke Sensor\",\n\t\t\t\"hide,0-113-1-8\",\n\t\t\t\"rename,0-48-2,Smoke Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-03-19 15:18:04\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-03-19 15:18:04\",\n\t\t\"commentary\": \"rename Node, hide dopple withget, rename device\",\n\t\t\"created\": \"2018-03-19 15:18:04\"\n\t}, {\n\t\t\"id\": \"295\",\n\t\t\"p_id\": \"881.2.4\",\n\t\t\"p_sku\": \"AEOEZWA004\",\n\t\t\"product\": \"Aeotec NanoMote One\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec NanoMote One\"],\n\t\t\"author_last_update\": \"2018-04-09 14:34:55\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-09 14:34:55\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-04-09 14:34:55\"\n\t}, {\n\t\t\"id\": \"296\",\n\t\t\"p_id\": \"881.2.3\",\n\t\t\"p_sku\": \"AEOEZWA003\",\n\t\t\"product\": \"Aeotec NanoMote Quad\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec NanoMote Quad\"],\n\t\t\"author_last_update\": \"2018-04-09 14:45:13\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-09 14:45:13\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-04-09 14:45:13\"\n\t}, {\n\t\t\"id\": \"297\",\n\t\t\"p_id\": \"280.785.514\",\n\t\t\"p_sku\": \"TKBETZ56-DTKBETZ56-S\",\n\t\t\"product\": \"TKBHome single/dual wall switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB single/dual switch\"],\n\t\t\"author_last_update\": \"2016-11-21 11:46:13\",\n\t\t\"author\": \"\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"0000-00-00 00:00:00\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2016-11-22 12:27:24\"\n\t}, {\n\t\t\"id\": \"298\",\n\t\t\"p_id\": \"280.785.513\",\n\t\t\"p_sku\": \"TKBETZ55-D\",\n\t\t\"product\": \"TKBHOME single/dual dimmer switch (TZ35-S/TZ55-D)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, TKB single/dual dimmer switc\"],\n\t\t\"author_last_update\": \"2019-01-28 10:24:21\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-28 10:24:21\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-04-17 13:20:00\"\n\t}, {\n\t\t\"id\": \"299\",\n\t\t\"p_id\": \"280.4.2\",\n\t\t\"p_sku\": \"TKBETZ69-GTKBETZ69-E\",\n\t\t\"product\": \"TKB Home Energy Plug In Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,TKB Home Energy Plug In Switch\"],\n\t\t\"author_last_update\": \"2018-04-17 15:13:32\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-04-17 15:13:32\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-04-17 15:13:32\"\n\t}, {\n\t\t\"id\": \"300\",\n\t\t\"p_id\": \"96.4.2\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"Everspring Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Plug\"],\n\t\t\"author_last_update\": \"2018-04-23 13:57:54\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-23 13:57:54\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-04-23 13:57:54\"\n\t}, {\n\t\t\"id\": \"301\",\n\t\t\"p_id\": \"881.2.5\",\n\t\t\"p_sku\": \"AEOEZWA005\",\n\t\t\"product\": \"Aeotec TriSensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Trisensor\",\n\t\t\t\"hide,0-48-12\",\n\t\t\t\"rename,0-113-7-8,Motion\",\n\t\t\t\"setConfig(0,1,30,2)\",\n\t\t\t\"setConfig(0,2,60,2)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-08 10:37:04\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-05-08 10:37:04\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-04-23 15:17:40\"\n\t}, {\n\t\t\"id\": \"302\",\n\t\t\"p_id\": \"340.3.4098\",\n\t\t\"p_sku\": \"POPE700793\",\n\t\t\"product\": \"Popp Power Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Power Plug\",\n\t\t\t\"hide,0-113-4-2\",\n\t\t\t\"hide,0-113-9-1\",\n\t\t\t\"hide,0-113-8-6\"\n\t\t],\n\t\t\"author_last_update\": \"2018-04-24 11:19:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-24 11:19:48\",\n\t\t\"commentary\": \"rename Node, hide Alarm\",\n\t\t\"created\": \"2018-04-24 11:19:48\"\n\t}, {\n\t\t\"id\": \"303\",\n\t\t\"p_id\": \"351.2049.20738\",\n\t\t\"p_sku\": \"MCOEMH8-FC\",\n\t\t\"product\": \"MCO Home Fan Coil Thermostat (2-pipe) V3.0\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Fan Coil Thermostat (2-pipe)\"],\n\t\t\"author_last_update\": \"2018-04-25 11:31:54\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-25 11:31:54\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-04-25 11:31:54\"\n\t}, {\n\t\t\"id\": \"304\",\n\t\t\"p_id\": \"345.7.84\",\n\t\t\"p_sku\": \"GOAEZMNHXD1\",\n\t\t\"product\": \"Qubino 3-Phase Smart Meter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino 3-Phase Smart Meter\"],\n\t\t\"author_last_update\": \"2018-04-30 11:12:37\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-04-30 11:12:37\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-04-30 11:12:37\"\n\t}, {\n\t\t\"id\": \"305\",\n\t\t\"p_id\": \"345.2.84\",\n\t\t\"p_sku\": \"GOAEZMNHYD1\",\n\t\t\"product\": \"Qubino Smart Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Qubino Smart Plug\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-0,Total consumption\",\n\t\t\t\"rename,0-113-8-9,Overload Alarm\",\n\t\t\t\"rename,0-113-8-6,Overheat Alarm\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-08 10:23:32\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-05-08 10:23:32\",\n\t\t\"commentary\": \"rename Node and devices\",\n\t\t\"created\": \"2018-05-08 10:23:06\"\n\t}, {\n\t\t\"id\": \"306\",\n\t\t\"p_id\": \"351.2305.20738\",\n\t\t\"p_sku\": \"MCOEMH9-CO2-230\",\n\t\t\"product\": \"MCO Home CO2 Monitor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home CO2 Monitor\",\n\t\t\t\"rename,0-113-3-1,CO2 Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-17,CO2 Level\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-08 12:10:01\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-05-08 12:10:01\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-05-08 12:10:01\"\n\t}, {\n\t\t\"id\": \"307\",\n\t\t\"p_id\": \"351.2050.20738\",\n\t\t\"p_sku\": \"MCOEMH8-FC4\",\n\t\t\"product\": \"MCO Home Fan Coil Thermostat (4-pipe)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home Fan Coil Thermostat (4-pipe)\"],\n\t\t\"author_last_update\": \"2018-05-15 13:48:06\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-05-15 13:48:06\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-05-15 13:47:50\"\n\t}, {\n\t\t\"id\": \"309\",\n\t\t\"p_id\": \"280.785.514\",\n\t\t\"p_sku\": \"TKBETZ36-S\",\n\t\t\"product\": \"TKBHOME single/dual wall switch TZ36S/D\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, TKBsingle/dual switch TZ36S/D\"],\n\t\t\"author_last_update\": \"2018-05-18 12:00:37\",\n\t\t\"author\": \"\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-05-18 12:00:37\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-05-18 12:00:37\"\n\t}, {\n\t\t\"id\": \"310\",\n\t\t\"p_id\": \"316.2.13\",\n\t\t\"p_sku\": \"PHI_PST02-1B\",\n\t\t\"product\": \"Philio 3 in 1 Sensor (Motion, illumination and temperature)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio 3 in 1 Sensor 1B\",\n\t\t\t\"rename,0-48-8,Tamper\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"rename,0-48-12,Motion\",\n\t\t\t\"noVDev,0-113-7-3\",\n\t\t\t\"rename,0-113-7-8,Burglar Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"setConfig(0,11,0,1)\",\n\t\t\t\"setConfig(0,12,1,1)\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,20,10,1)\",\n\t\t\t\"setConfig(0,7,22,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-22 11:30:41\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-05-22 11:30:41\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide, noVDev, setConfig\",\n\t\t\"created\": \"2018-05-22 11:30:41\"\n\t}, {\n\t\t\"id\": \"311\",\n\t\t\"p_id\": \"316.2.14\",\n\t\t\"p_sku\": \"PHI_PST02-1C\",\n\t\t\"product\": \"Philio 3-in-1 Sensor (Door/Window, Temperature, Brightness)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio 3-in-1 Sensor 1C\",\n\t\t\t\"rename,0-48-8,Tamper\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"rename,0-48-10,Door/Window\",\n\t\t\t\"noVDev,0-113-6\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"setConfig(0,7,16,1)\",\n\t\t\t\"setConfig(0,11,0,1)\",\n\t\t\t\"setConfig(0,12,1,1)\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,20,10,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-22 11:31:30\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-05-22 11:31:30\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide, noVDev, setConfig\",\n\t\t\"created\": \"2018-05-22 11:31:30\"\n\t}, {\n\t\t\"id\": \"312\",\n\t\t\"p_id\": \"316.2.12\",\n\t\t\"p_sku\": \"PHI_PST02-1A\",\n\t\t\"product\": \"Philio 4-in-1 Sensor (Door/Window, Temperature, Brightness, Motion)\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Philio 4-in-1 Sensor 1A\",\n\t\t\t\"rename,0-48-8,Tamper\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"rename,0-48-10,Door/Window\",\n\t\t\t\"rename,0-48-12,Motion\",\n\t\t\t\"noVDev,0-113-6\",\n\t\t\t\"noVDev,0-113-7-3\",\n\t\t\t\"rename,0-113-7-8,Burglar Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-3,Luminiscence\",\n\t\t\t\"setConfig(0,7,22,1)\",\n\t\t\t\"setConfig(0,11,0,1)\",\n\t\t\t\"setConfig(0,12,1,1)\",\n\t\t\t\"setConfig(0,13,1,1)\",\n\t\t\t\"setConfig(0,20,10,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-05-22 12:11:18\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-05-22 12:11:18\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide, noVDev, setConfig\",\n\t\t\"created\": \"2018-05-22 12:11:18\"\n\t}, {\n\t\t\"id\": \"313\",\n\t\t\"p_id\": \"05.32771.4096\",\n\t\t\"p_sku\": \"ZIPEGASSENSOR\",\n\t\t\"product\": \"Zipato Combustible Gas Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Zipato Combustible Gas Sensor\"],\n\t\t\"author_last_update\": \"2018-05-24 11:25:29\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-05-24 11:25:29\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2018-05-24 11:25:29\"\n\t}, {\n\t\t\"id\": \"314\",\n\t\t\"p_id\": \"271.2817.4099\",\n\t\t\"p_sku\": \"FIBEFGFS-101-ZW5\",\n\t\t\"product\": \"Fibaro Flood Sensor V3.03\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-5-2,Water\",\n\t\t\t\"renameNode,Fibaro Leakage Sensor G5\",\n\t\t\t\"rename,0-113-7-3,Tampe\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"hide,0-156-0\",\n\t\t\t\"hide,0-156-5\"\n\t\t],\n\t\t\"author_last_update\": \"2018-06-11 11:12:37\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-06-11 11:12:37\",\n\t\t\"commentary\": \"hide elements, rename elements, rename device\",\n\t\t\"created\": \"2018-06-11 11:12:37\"\n\t}, {\n\t\t\"id\": \"315\",\n\t\t\"p_id\": \"271.6145.4096\",\n\t\t\"p_sku\": \"FIBEFGWPG-111-5\",\n\t\t\"product\": \"Fibaro Wall Plug Type G\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"hide,0-113-8-6\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"hide-0-113-9-3\",\n\t\t\t\"renameNode,Fibaro Wall Plug Type G\"\n\t\t],\n\t\t\"author_last_update\": \"2018-06-11 15:19:08\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-06-11 15:19:08\",\n\t\t\"commentary\": \"SP: rename Node\",\n\t\t\"created\": \"2018-06-11 15:13:53\"\n\t}, {\n\t\t\"id\": \"316\",\n\t\t\"p_id\": \"608.32769.4096\",\n\t\t\"p_sku\": \"HEIEHS1MS-Z\",\n\t\t\"product\": \"Heiman Smart Motion Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heimann Motion Sensor\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"hide,0-48-12\",\n\t\t\t\"rename,0-113-7-8,Motion\"\n\t\t],\n\t\t\"author_last_update\": \"2018-06-19 13:45:53\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-06-19 13:45:53\",\n\t\t\"commentary\": \"rename Node and Sensors\",\n\t\t\"created\": \"2018-06-19 13:45:53\"\n\t}, {\n\t\t\"id\": \"317\",\n\t\t\"p_id\": \"608.32775.4096\",\n\t\t\"p_sku\": \"HEIEHS1HT-Z\",\n\t\t\"product\": \"Heiman Temperature & Humidity Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humuidity\",\n\t\t\t\"renameNode,Heimann Temperature und Humidity Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-06-19 13:47:23\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-06-19 13:47:23\",\n\t\t\"commentary\": \"rename Node and sensors\",\n\t\t\"created\": \"2018-06-19 13:47:23\"\n\t}, {\n\t\t\"id\": \"318\",\n\t\t\"p_id\": \"608.32771.4096\",\n\t\t\"p_sku\": \"HEIEHS1CG-Z\",\n\t\t\"product\": \"Heiman Smart Combustible Gas Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heiman Combustible Gas Sensor\"],\n\t\t\"author_last_update\": \"2018-06-19 13:55:03\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-06-19 13:55:03\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2018-06-19 13:55:03\"\n\t}, {\n\t\t\"id\": \"319\",\n\t\t\"p_id\": \"608.32777.4096\",\n\t\t\"p_sku\": \"HEIEHS2WD-Z\",\n\t\t\"product\": \"Heiman Smart Siren\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Smart Siren\",\n\t\t\t\"rename,0-37,Siren\"\n\t\t],\n\t\t\"author_last_update\": \"2018-06-19 14:20:34\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-06-19 14:20:34\",\n\t\t\"commentary\": \"rename node, siren\",\n\t\t\"created\": \"2018-06-19 14:20:34\"\n\t}, {\n\t\t\"id\": \"320\",\n\t\t\"p_id\": \"600.3.4237\",\n\t\t\"p_sku\": \"NEOEMS02Z\",\n\t\t\"product\": \"NEO Coolcam - Motion Sensor (PIR) with temperature sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,NEO Coolcam - Motion Sensor (PIR) with temperature sensor\",\n\t\t\t\"rename,0-48-12,Motion\",\n\t\t\t\"rename,0-113-7-8,Burglar Alarm\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-3,Luminiscence\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-02 10:14:04\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-07-02 10:14:04\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-07-02 10:14:04\"\n\t}, {\n\t\t\"id\": \"321\",\n\t\t\"p_id\": \"96.10.2\",\n\t\t\"p_sku\": \"EVREAC136\",\n\t\t\"product\": \"Everspring Panic Button AC136\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Panic Button\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(2,1,0);}\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-05 13:09:09\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-05 13:09:09\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-07-05 12:22:03\"\n\t}, {\n\t\t\"id\": \"322\",\n\t\t\"p_id\": \"351.54289.20738\",\n\t\t\"p_sku\": \"MCOEDT411\",\n\t\t\"product\": \"MCO Touch Panel Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Dimmer\",\n\t\t\t\"rename,0-50-0,Total energy consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"setConfig(0,15,15,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-06 10:28:14\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-06 10:28:14\",\n\t\t\"commentary\": \"rename node and devices, hide system alarm\",\n\t\t\"created\": \"2018-07-06 10:28:14\"\n\t}, {\n\t\t\"id\": \"323\",\n\t\t\"p_id\": \"351.54033.20738\",\n\t\t\"p_sku\": \"MCOEDT311\",\n\t\t\"product\": \"MCO Touch Panel Dimmer UK\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Dimmer UK\",\n\t\t\t\"rename,0-50-0,Total energy consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"hide,0-113-8-8\",\n\t\t\t\"setConfig(0,15,15,1)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-31 13:09:14\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-31 13:09:14\",\n\t\t\"commentary\": \"rename node and devices, hide system alarm\",\n\t\t\"created\": \"2018-07-06 10:27:58\"\n\t}, {\n\t\t\"id\": \"324\",\n\t\t\"p_id\": \"96.2.3\",\n\t\t\"p_sku\": \"EVRESM810-1\",\n\t\t\"product\": \"Everspring Door/ Window Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Everspring Door/ Window Sensor\",\n\t\t\t\"rename,0-113-6,Everspring D/W Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-05 15:33:02\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-05 15:33:02\",\n\t\t\"commentary\": \"RS: rename\",\n\t\t\"created\": \"2018-07-05 15:33:02\"\n\t}, {\n\t\t\"id\": \"325\",\n\t\t\"p_id\": \"96.1.6\",\n\t\t\"p_sku\": \"EVRESP817\",\n\t\t\"product\": \"Everspring Motion Sensor SP817\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-7-3,Tamper\",\n\t\t\t\"rename,0-113-7-8,Motion\",\n\t\t\t\"renameNode,Everspring Motion Sensor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-06 08:49:05\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-06 08:49:05\",\n\t\t\"commentary\": \"rename Node, Tamper, Motion\",\n\t\t\"created\": \"2018-07-06 08:49:05\"\n\t}, {\n\t\t\"id\": \"326\",\n\t\t\"p_id\": \"96.1.6\",\n\t\t\"p_sku\": \"EVRESP815\",\n\t\t\"product\": \"Everspring Motion Sensor SP815\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Everspring Motion Sensor\",\n\t\t\t\"rename,0-113-7-8,Motion\",\n\t\t\t\"rename,0-113-7-3,Tamper\",\n\t\t\t\"setConfig(0,1,10,2)\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-06 09:57:26\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-07-06 09:57:26\",\n\t\t\"commentary\": \"rename Node, Motion, Tamper, Set Parameter 1 to value 10\",\n\t\t\"created\": \"2018-07-06 09:57:26\"\n\t}, {\n\t\t\"id\": \"327\",\n\t\t\"p_id\": \"351.2562.20738\",\n\t\t\"p_sku\": \"MCOEMH10-PM\",\n\t\t\"product\": \"MCO Home PM2.5 Sensor Air Quality Monitor - 12V\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home PM2.5 Monitor\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-35,Particulate Matter\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-06 10:57:13\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-07-06 10:57:13\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-07-06 10:57:13\"\n\t}, {\n\t\t\"id\": \"328\",\n\t\t\"p_id\": \"351.50209.20738\",\n\t\t\"p_sku\": \"MCOEC421\",\n\t\t\"product\": \"MCO Shutter Panel Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Roller Shutter\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-0,Total energy consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-01 07:44:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-08-01 07:44:48\",\n\t\t\"commentary\": \"rename node, energy meters\",\n\t\t\"created\": \"2018-07-06 11:06:33\"\n\t}, {\n\t\t\"id\": \"329\",\n\t\t\"p_id\": \"351.49953.20738\",\n\t\t\"p_sku\": \"MCOEC321\",\n\t\t\"product\": \"MCO Shutter Panel Switch UK\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Roller Shutter UK\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-0,Total energy consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-01 07:44:56\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-08-01 07:44:56\",\n\t\t\"commentary\": \"rename node, energy meters\",\n\t\t\"created\": \"2018-07-06 11:06:33\"\n\t}, {\n\t\t\"id\": \"330\",\n\t\t\"p_id\": \"351.2561.20738\",\n\t\t\"p_sku\": \"MCOEMH10-PM-230\",\n\t\t\"product\": \"MCO Home PM2.5 Sensor Air Quality Monitor - 230V\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home PM2.5 Monitor\",\n\t\t\t\"rename,0-49-1,Temperature\",\n\t\t\t\"rename,0-49-5,Humidity\",\n\t\t\t\"rename,0-49-35,Particulate Matter\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-06 16:32:39\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-07-06 16:32:39\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-07-06 16:32:39\"\n\t}, {\n\t\t\"id\": \"331\",\n\t\t\"p_id\": \"351.2051.20738\",\n\t\t\"p_sku\": \"MCOEMH8-FC\",\n\t\t\"product\": \"MCO Home - Fan Coil Thermostat 2 pipe\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MCO Home - Fan Coil Thermostat 2 pipe\",\n\t\t\t\"rename,0-64,Thermostat operation\",\n\t\t\t\"rename,0-67-1,Thermostat Heat\",\n\t\t\t\"rename,0-67-2,Thermostat Cool\",\n\t\t\t\"rename,0-49-1,Temperature\"\n\t\t],\n\t\t\"author_last_update\": \"2018-07-09 16:32:32\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-07-09 16:32:32\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-07-09 16:32:32\"\n\t}, {\n\t\t\"id\": \"332\",\n\t\t\"p_id\": \"608.32773.4096\",\n\t\t\"p_sku\": \"Heiman CO Sensor\",\n\t\t\"product\": \"HEIEHS1CA\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heiman CO Sensor\",\n\t\t\t\"hide,0-113-2-8\",\n\t\t\t\"rename,0-48-3,CO - Alarm\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-02 14:43:49\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-08-02 14:43:49\",\n\t\t\"commentary\": \"rename Node and CO-Alarm, hide widget\",\n\t\t\"created\": \"2018-08-02 14:43:49\"\n\t}, {\n\t\t\"id\": \"333\",\n\t\t\"p_id\": \"151.24881.17665\",\n\t\t\"p_sku\": \"ZIPERFID\",\n\t\t\"product\": \"Zipato RFID Keypad\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Zipato RFID Keypad\",\n\t\t\t\"rename,0-37,Keypad Switch\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-03 15:08:08\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-08-03 15:08:08\",\n\t\t\"commentary\": \"RS: renameNode, rename\",\n\t\t\"created\": \"2018-08-03 15:08:08\"\n\t}, {\n\t\t\"id\": \"334\",\n\t\t\"p_id\": \"520.768.18\",\n\t\t\"p_sku\": \"HNKEMS02\",\n\t\t\"product\": \"Hank Motion Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Hank Motion Sensor\",\n\t\t\t\"rename,0-48-8,Tamper\",\n\t\t\t\"rename,0-48-12,Motion\",\n\t\t\t\"rename,0-113-7-8,Burglar Alarm\",\n\t\t\t\"rename,0-113-7-9,Burglar Alarm\",\n\t\t\t\"hide,0-48-8\",\n\t\t\t\"hide,0-113-7-9\",\n\t\t\t\"rename,0-113-7-254,Burglar Alarm\",\n\t\t\t\"hide,0-113-7-254\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-08 15:04:12\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-08-08 15:04:12\",\n\t\t\"commentary\": \"RS: renameNode, rename, hide\",\n\t\t\"created\": \"2018-08-08 15:04:12\"\n\t}, {\n\t\t\"id\": \"335\",\n\t\t\"p_id\": \"625.2.6651\",\n\t\t\"p_sku\": \"\",\n\t\t\"product\": \"Steinel Motion Switch LED\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,MotionSwitch LED\",\n\t\t\t\"hide,0-113-7-8\",\n\t\t\t\"hide,0-49-3\",\n\t\t\t\"hide,0-91\",\n\t\t\t\"rename,1-113-7-8,Motion\"\n\t\t],\n\t\t\"author_last_update\": \"2018-08-13 11:13:01\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-08-13 11:13:01\",\n\t\t\"commentary\": \"rename device, hide inactive elements\",\n\t\t\"created\": \"2018-08-13 11:13:01\"\n\t}, {\n\t\t\"id\": \"336\",\n\t\t\"p_id\": \"134.3.141\",\n\t\t\"p_sku\": \"AEOEZW141\",\n\t\t\"product\": \"Aeotec Nano Shutter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec Nano Shutter\"],\n\t\t\"author_last_update\": \"2018-08-22 14:56:48\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-08-22 14:56:48\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-08-22 14:56:48\"\n\t}, {\n\t\t\"id\": \"337\",\n\t\t\"p_id\": \"271.2049.4098\",\n\t\t\"p_sku\": \"FIBEFGMS-001-ZW5\",\n\t\t\"product\": \"FIBARO Motion Sensor (4-in-1 Multi Sensor) GEN 5\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Motion Sensor\",\n\t\t\t\"hide,0-49-25\",\n\t\t\t\"hide,0-49-52\",\n\t\t\t\"hide,0-49-53\",\n\t\t\t\"hide,0-49-54\",\n\t\t\t\"hide,0-156-0\",\n\t\t\t\"rename,0-113-7-8,Fibaro Motion Sensor\",\n\t\t\t\"hide,0-48-1\"\n\t\t],\n\t\t\"author_last_update\": \"2018-09-13 11:20:24\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-09-13 11:20:24\",\n\t\t\"commentary\": \"RS: renameNode, hide, rename\",\n\t\t\"created\": \"2018-09-13 11:20:24\"\n\t}, {\n\t\t\"id\": \"338\",\n\t\t\"p_id\": \"266\",\n\t\t\"p_sku\": \"VITRUM\",\n\t\t\"product\": \"ALL VITRUM\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"setDeviceData('acceptSetSecurityLevel', 'value', 0)\",\n\t\t\t\"if (instanceId === 0 && commandClassId === self.CC['Basic']){for (var _instanceId in self.zway.devices[1].instances) {if (self.zway.devices[1].instances[_instanceId].Basic && self.zway.devices[1].instances[_instanceId].Basic.data.srcNodeId){self.zway.devices[1].instances[_instanceId].Basic.data.srcNodeId.bind(function(type, __instanceId) {if (this.value === nodeId) {if (self.zway.devices[nodeId].instances[__instanceId].SwitchMultilevel){self.zway.devices[nodeId].instances[__instanceId].SwitchMultilevel.Get();}if (self.zway.devices[nodeId].instances[__instanceId].SwitchBinary){self.zway.devices[nodeId].instances[__instanceId].SwitchBinary.Get();}var multiChannelAssociationData = self.zway.devices[nodeId].MultiChannelAssociation.data;for (var el in multiChannelAssociationData) {if (! isNaN(el)) {var assoc = multiChannelAssociationData[el].nodesInstances.value;var nodeList = assoc.filter(function(item, i) { return i % 2 === 0; }),instancesList = assoc.filter(function(item, i) { return i % 2 === 1; });nodeList.forEach(function(item, i, arr) {if (item === 1) return;if (self.zway.devices[nodeList[i]].instances[instancesList[i]].SwitchMultilevel){self.zway.devices[nodeList[i]].instances[instancesList[i]].SwitchMultilevel.Get();}if (self.zway.devices[nodeList[i]].instances[instancesList[i]].SwitchBinary){self.zway.devices[nodeList[i]].instances[instancesList[i]].SwitchBinary.Get();}});}}var associationData = self.zway.devices[nodeId].Association.data;for (var el in associationData) {if (! isNaN(el)) {associationData[el].nodes.value.forEach(function(item, i, arr) {if (item === 1) return;if (self.zway.devices[item].SwitchMultilevel){self.zway.devices[item].SwitchMultilevel.Get();}if (self.zway.devices[item].SwitchBinary){self.zway.devices[item].SwitchBinary.Get();}});}}}},_instanceId);}if (self.zway.devices[1].instances[_instanceId].SwitchMultilevel && self.zway.devices[1].instances[_instanceId].SwitchMultilevel.data.srcNodeId){self.zway.devices[1].instances[_instanceId].SwitchMultilevel.data.srcNodeId.bind(function(type, __instanceId) {if (this.value === nodeId) {self.zway.devices[nodeId].instances[__instanceId].SwitchMultilevel.Get();}},_instanceId)}}}\"\n\t\t],\n\t\t\"author_last_update\": \"2019-01-28 07:46:03\",\n\t\t\"author\": \"AIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2019-01-28 07:46:03\",\n\t\t\"commentary\": \"bind Basic to SwitchMultilevel and SwitchBinary for all VITRUM devices\",\n\t\t\"created\": \"2018-10-05 16:17:04\"\n\t}, {\n\t\t\"id\": \"339\",\n\t\t\"p_id\": \"881.3.2\",\n\t\t\"p_sku\": \"AEOEZWA002\",\n\t\t\"product\": \"AEOTEC - LED Bulb 6 Multi-Colour\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec LED Bulb 6 Multi-Colour\"],\n\t\t\"author_last_update\": \"2018-10-29 14:17:12\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-10-29 14:17:12\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-10-29 14:17:12\"\n\t}, {\n\t\t\"id\": \"340\",\n\t\t\"p_id\": \"881.3.1\",\n\t\t\"p_sku\": \"AEOEZWA001\",\n\t\t\"product\": \"AEOTEC - LED Bulb 6 Multi-White\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Aeotec LED Bulb 6 Multi-White\"],\n\t\t\"author_last_update\": \"2018-10-29 15:28:22\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-10-29 15:28:22\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-10-29 15:28:22\"\n\t}, {\n\t\t\"id\": \"341\",\n\t\t\"p_id\": \"608.32771.4096\",\n\t\t\"p_sku\": \"HEIEHS1CG\",\n\t\t\"product\": \"Heiman Combustible Gas Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heiman Combustible Gas Sensor\"],\n\t\t\"author_last_update\": \"2018-11-19 14:26:22\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-11-19 14:26:22\",\n\t\t\"commentary\": \"\",\n\t\t\"created\": \"2018-11-19 14:26:22\"\n\t}, {\n\t\t\"id\": \"342\",\n\t\t\"p_id\": \"133.2.3\",\n\t\t\"p_sku\": \"FAK_ZWS230\",\n\t\t\"product\": \"Fakro Electric actuator\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fakro Electric actuator\"],\n\t\t\"author_last_update\": \"2018-11-28 11:46:10\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-11-28 11:46:10\",\n\t\t\"commentary\": \"renameNode\",\n\t\t\"created\": \"2018-11-28 11:46:10\"\n\t}, {\n\t\t\"id\": \"343\",\n\t\t\"p_id\": \"340.3.10\",\n\t\t\"p_sku\": \"POPE700397\",\n\t\t\"product\": \"Popp Smart Outdoor Plug\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Smart Outdoor Plug\",\n\t\t\t\"rename,0-50-0,Total energy consumption\",\n\t\t\t\"rename,0-50-2,Current consumption\",\n\t\t\t\"rename,0-50-4,Current voltage\",\n\t\t\t\"rename,0-50-5,Current power\",\n\t\t\t\"rename,0-50-6,Power factor\"\n\t\t],\n\t\t\"author_last_update\": \"2018-11-28 14:19:55\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-11-28 14:19:55\",\n\t\t\"commentary\": \"rename Node and devices\",\n\t\t\"created\": \"2018-11-28 14:19:55\"\n\t}, {\n\t\t\"id\": \"344\",\n\t\t\"p_id\": \"329.4628.2816\",\n\t\t\"p_sku\": \"WIDEWDSL\",\n\t\t\"product\": \"WiDom Smart Double Switch\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,WiDom Double Switch\",\n\t\t\t\"hide,0-37\",\n\t\t\t\"rename,1-37,Relay 1\",\n\t\t\t\"rename,2-37,Relay 2\",\n\t\t\t\"rename,1-50-2,Current consumption O1\",\n\t\t\t\"rename,2-50-2,Current consumption O2\"\n\t\t],\n\t\t\"author_last_update\": \"2018-11-29 11:15:20\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-11-29 11:15:20\",\n\t\t\"commentary\": \"rename node and devices, hide master\",\n\t\t\"created\": \"2018-11-29 11:15:20\"\n\t}, {\n\t\t\"id\": \"345\",\n\t\t\"p_id\": \"329.4628.2048\",\n\t\t\"p_sku\": \"WIDEWRS\",\n\t\t\"product\": \"WiDom Smart Roller Shutter\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,WiDom Roller Shutter\"],\n\t\t\"author_last_update\": \"2018-11-29 11:49:52\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-11-29 11:49:52\",\n\t\t\"commentary\": \"rename Node\",\n\t\t\"created\": \"2018-11-29 11:49:52\"\n\t}, {\n\t\t\"id\": \"346\",\n\t\t\"p_id\": \"271.3074.4099\",\n\t\t\"p_sku\": \"FIBEFGSD-002\",\n\t\t\"product\": \"Fibaro Smoke Sensor FGSD-002\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"noVDev,0-156\",\n\t\t\t\"noVDev,0-113-1-3\",\n\t\t\t\"noVDev,0-113-7\",\n\t\t\t\"noVDev,0-113-8\",\n\t\t\t\"noVDev,0-113-9\",\n\t\t\t\"rename,0-113-4-2,Heat Alarm\",\n\t\t\t\"rename,0-113-1-2,Smoke Alarm\",\n\t\t\t\"renameNode,Fibaro Smoke Sensor FGSD-002\",\n\t\t\t\"icon,0-113-1-2,smoke\",\n\t\t\t\"icon,0-113-4-2,smoke\"\n\t\t],\n\t\t\"author_last_update\": \"2018-12-04 11:10:28\",\n\t\t\"author\": \"NIRRS\",\n\t\t\"tester\": \"\",\n\t\t\"tester_last_update\": \"2018-12-04 11:10:28\",\n\t\t\"commentary\": \"hide Alarm and AlarmSensor widgets, rename widgets and nodechange icons\",\n\t\t\"created\": \"2018-12-04 11:10:28\"\n\t}, {\n\t\t\"id\": \"347\",\n\t\t\"p_id\": \"271.4609.4097\",\n\t\t\"p_sku\": \"FIBEFGCD001\",\n\t\t\"product\": \"Fibaro CO Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode, Fibaro CO Sensor\",\n\t\t\t\"noVDev,0-156-0\",\n\t\t\t\"noVDev,0-156-2\",\n\t\t\t\"noVDev,0-156-4\",\n\t\t\t\"hide,0-113-8-10\",\n\t\t\t\"hide,0-113-9-1\",\n\t\t\t\"hide,0-113-7-3\",\n\t\t\t\"noVDev,0-113-2-4\",\n\t\t\t\"rename,0-113-2-3,CO Alarm Test\"\n\t\t],\n\t\t\"author_last_update\": \"2018-12-04 14:19:04\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-12-04 14:19:04\",\n\t\t\"commentary\": \"rename Node and moduls, hide Systemalarm, disable 0-156\",\n\t\t\"created\": \"2018-12-04 14:19:04\"\n\t}, {\n\t\t\"id\": \"348\",\n\t\t\"p_id\": \"340.4.20\",\n\t\t\"p_sku\": \"POPE701202\",\n\t\t\"product\": \"POPP Mold Detector\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Mold Detector\",\n\t\t\t\"rename,0-48-1,Mold Alarm\"\n\t\t],\n\t\t\"author_last_update\": \"2018-12-04 15:14:54\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-12-04 15:14:54\",\n\t\t\"commentary\": \"rename node and device\",\n\t\t\"created\": \"2018-12-04 15:14:54\"\n\t}, {\n\t\t\"id\": \"349\",\n\t\t\"p_id\": \"564.3.268\",\n\t\t\"p_sku\": \"HEAE4512454\",\n\t\t\"product\": \"Heatit Z-Scene Controller\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heatit Z-Scene Controller\"],\n\t\t\"author_last_update\": \"2018-12-19 14:55:25\",\n\t\t\"author\": \"RS\",\n\t\t\"tester\": \"RS\",\n\t\t\"tester_last_update\": \"2018-12-19 14:55:25\",\n\t\t\"commentary\": \"RS: renameNode\",\n\t\t\"created\": \"2018-12-19 14:55:25\"\n\t}, {\n\t\t\"id\": \"350\",\n\t\t\"p_id\": \"411.3.514\",\n\t\t\"p_sku\": \"HEAE5430560\",\n\t\t\"product\": \"Heatit Z-TRM2fx\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Heatit Z-TRM2fx\",\n\t\t\t\"hide,0-67-1\",\n\t\t\t\"hide,0-67-2\",\n\t\t\t\"rename,4-50-4,Current voltage\",\n\t\t\t\"rename,4-50-2,Current consumption\",\n\t\t\t\"rename,4-50-0,Total consumption\",\n\t\t\t\"hide,0-64\"\n\t\t],\n\t\t\"author_last_update\": \"2018-12-27 14:29:26\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-12-27 14:29:26\",\n\t\t\"commentary\": \"rename Node, hide double\",\n\t\t\"created\": \"2018-12-27 14:29:26\"\n\t}, {\n\t\t\"id\": \"351\",\n\t\t\"p_id\": \"271.771.4096\",\n\t\t\"p_sku\": \"FIBEFGR-223\",\n\t\t\"product\": \"Fibaro Roller Shutter 3\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Fibaro Roller Shutter 3\",\n\t\t\t\"hide,0-38\",\n\t\t\t\"hide,2-38\"\n\t\t],\n\t\t\"author_last_update\": \"2018-12-28 15:18:00\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2018-12-28 15:18:00\",\n\t\t\"commentary\": \"raname node\",\n\t\t\"created\": \"2018-12-27 15:14:20\"\n\t}, {\n\t\t\"id\": \"354\",\n\t\t\"p_id\": \"329.4628.2560\",\n\t\t\"p_sku\": \"WIDEWTD\",\n\t\t\"product\": \"wiDom Dimmer\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,WiDom Dimmer\"],\n\t\t\"author_last_update\": \"2019-01-18 12:27:09\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-18 12:27:09\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2019-01-18 12:27:09\"\n\t}, {\n\t\t\"id\": \"355\",\n\t\t\"p_id\": \"329.4628.2304\",\n\t\t\"p_sku\": \"WIDEWSD\",\n\t\t\"product\": \"Widom Relay with Dry Contact\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,WiDom Dry Relay\"],\n\t\t\"author_last_update\": \"2019-01-18 14:45:14\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-18 14:45:14\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2019-01-18 14:45:14\"\n\t}, {\n\t\t\"id\": \"356\",\n\t\t\"p_id\": \"340.4.7\",\n\t\t\"p_sku\": \"POPE700892\",\n\t\t\"product\": \"Popp Door/Window Sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"renameNode,Popp Door/Window Sensor\"],\n\t\t\"author_last_update\": \"2019-01-21 13:46:50\",\n\t\t\"author\": \"SP\",\n\t\t\"tester\": \"SP\",\n\t\t\"tester_last_update\": \"2019-01-21 13:46:50\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2019-01-21 13:46:50\"\n\t}, {\n\t\t\"id\": \"357\",\n\t\t\"p_id\": \"316.8.29\",\n\t\t\"p_sku\": \"PSR03-B\",\n\t\t\"product\": \"Philio PSR03-B\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"setDeviceData('acceptSetSecurityLevel', 'value', 0)\",\n\t\t\t\"emulateOff,0-113-10-3,10000\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-08 18:46:50\",\n\t\t\"author\": \"PS\",\n\t\t\"tester\": \"PS\",\n\t\t\"tester_last_update\": \"2020-11-08 18:46:50\",\n\t\t\"commentary\": \"AutoOff on the Alarm button and Allow less secure Set\",\n\t\t\"created\": \"2020-11-08 18:46:50\"\n\t},{\n\t\t\"id\": \"357\",\n\t\t\"p_id\": \"411.3.8704\",\n\t\t\"p_sku\": \"HEAE1444444\",\n\t\t\"product\": \"Heatit Z-Dim\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Heatit Z-Dim\",\n\t\t\t\"noVDev,0-37\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-09 23:20:00\",\n\t\t\"author\": \"AIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2020-11-09 23:20:00\",\n\t\t\"commentary\": \"rename Node, stop switch\",\n\t\t\"created\": \"2020-11-09 23:20:00\"\n\t},{\n\t\t\"id\": \"358\",\n\t\t\"p_id\": \"411.3.13\",\n\t\t\"p_sku\": \"HEAE4512689\",\n\t\t\"product\": \"Heatit Z-Smoke Detector 230V\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Heatit Z-Smoke Detector 230V\",\n\t\t\t\"hide,0-113-1-6\",\n\t\t\t\"hide,0-113-4-9\",\n\t\t\t\"hide,0-113-7-0\",\n\t\t\t\"hide,0-113-8-3\",\n\t\t\t\"rename,0-113-7-8, Motion Sensor Alarm\",\n\t\t\t\"icon,0-113-7-8,motion\",\n\t\t\t\"probeType,0-113-7-8,motion\",\n\t\t\t\"rename,0-113-7-3, Siren Tamper Alarm\",\n\t\t\t\"icon,0-113-7-3,tamper\",\n\t\t\t\"probeType,0-113-7-3,tamper\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-09 23:20:00\",\n\t\t\"author\": \"AIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2020-11-09 23:20:00\",\n\t\t\"commentary\": \"rename Node, hide double alarms\",\n\t\t\"created\": \"2020-11-09 23:20:00\"\n\t}, {\n\t\t\"id\": \"359\",\n\t\t\"p_id\": \"411.3.520\",\n\t\t\"p_sku\": \"HEAE4512554\",\n\t\t\"product\": \"Heatit Z-Relay\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Heatit Z-Relay\",\n\t\t\t\"noVDev,1-37\",\n\t\t\t\"noVDev,1-50-0\",\n\t\t\t\"noVDev,1-50-2\",\n\t\t\t\"noVDev,1-50-5\",\n\t\t\t\"rename,0-37,Flow Stop\",\n\t\t\t\"icon,0-37,valve\",\n\t\t\t\"probeType,0-37,valve\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-09 23:20:00\",\n\t\t\"author\": \"AIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2020-11-09 23:20:00\",\n\t\t\"commentary\": \"rename Node, stop switch\",\n\t\t\"created\": \"2020-11-09 23:20:00\"\n\t}, {\n\t\t\"id\": \"360\",\n\t\t\"p_id\": \"564.3.274\",\n\t\t\"p_sku\": \"HEAE4512561\",\n\t\t\"product\": \"Heatit Z-DIN 616\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Heatit Z-DIN 616\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"noVDev,7-37\",\n\t\t\t\"noVDev,8-37\",\n\t\t\t\"noVDev,9-37\",\n\t\t\t\"noVDev,10-37\",\n\t\t\t\"noVDev,11-37\",\n\t\t\t\"noVDev,12-37\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-09 12:09:29\",\n\t\t\"author\": \"AIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2020-11-09 12:09:29\",\n\t\t\"commentary\": \"rename node\",\n\t\t\"created\": \"2020-11-09 12:09:29\"\n\t}, {\n\t\t\"id\": \"361\",\n\t\t\"p_id\": \"411.3.522\",\n\t\t\"p_sku\": \"HEAE4512475\",\n\t\t\"product\": \"Heatit Z-Water\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Heatit Z-Water\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"rename,1-37,Relay 1\",\n\t\t\t\"rename,2-37,Relay 2\",\n\t\t\t\"rename,3-37,Relay 3\",\n\t\t\t\"rename,4-37,Relay 4\",\n\t\t\t\"rename,5-37,Relay 5\",\n\t\t\t\"rename,6-37,Relay 6\",\n\t\t\t\"rename,7-37,Relay 7\",\n\t\t\t\"rename,8-37,Relay 8\",\n\t\t\t\"rename,9-37,Relay 9\",\n\t\t\t\"rename,10-37,Relay 10\",\n\t\t\t\"rename,11-49-1,IN 1 Temperature\",\n\t\t\t\"rename,12-49-1,IN 2 Temperature\",\n\t\t\t\"rename,13-49-1,IN 3 Temperature\",\n\t\t\t\"rename,14-49-1,IN 4 Temperature\",\n\t\t\t\"setConfig(0,3,0,1);\",\n\t\t\t\"setConfig(0,4,0,1);\",\n\t\t\t\"setConfig(0,5,0,1);\",\n\t\t\t\"setConfig(0,6,0,1);\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-09 12:09:29\",\n\t\t\"author\": \"AIVS\",\n\t\t\"tester\": \"AIVS\",\n\t\t\"tester_last_update\": \"2020-11-09 12:09:29\",\n\t\t\"commentary\": \"rename Node and Devices, disable temperature reports\",\n\t\t\"created\": \"2020-11-09 12:09:29\"\n\t}, {\n\t\t\"id\": \"362\",\n\t\t\"p_id\": \"316.8.38\",\n\t\t\"p_sku\": \"PSR03-A\",\n\t\t\"product\": \"Philio PSR03-A\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"setDeviceData('acceptSetSecurityLevel', 'value', 0x80)\",\n\t\t\t\"scenesSupport(0,133,2,3,'S')\",\n\t\t\t\"emulateOff,0-113-10-3,10000\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-08 18:46:50\",\n\t\t\"author\": \"PS\",\n\t\t\"tester\": \"PS\",\n\t\t\"tester_last_update\": \"2020-11-08 18:46:50\",\n\t\t\"commentary\": \"AutoOff on the Alarm button and Allow less secure Set, create the button on Association completion\",\n\t\t\"created\": \"2020-11-08 18:46:50\"\n\t}, {\n\t\t\"id\": \"363\",\n\t\t\"p_id\": \"316.4.10\",\n\t\t\"p_sku\": \"PSE02\",\n\t\t\"product\": \"Philio PSE02\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"noVDev,0-48-1\",\n\t\t\t\"noVDev,0-48-8\",\n\t\t\t\"noVDev,0-113-7-3\"\n\t\t],\n\t\t\"author_last_update\": \"2020-11-08 18:46:50\",\n\t\t\"author\": \"PS\",\n\t\t\"tester\": \"PS\",\n\t\t\"tester_last_update\": \"2020-11-08 18:46:50\",\n\t\t\"commentary\": \"Removed extra widgets\",\n\t\t\"created\": \"2020-11-08 18:46:50\"\n\t}, {\n\t\t\"id\": \"364\",\n\t\t\"p_id\": \"277.256.2304\",\n\t\t\"p_sku\": \"ZME_TION3S\",\n\t\t\"product\": \"Tion 3S\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Tion 3S\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"rename,0-49-1,Tion Temperature\",\n\t\t\t\"rename,0-64,Tion Heat operation\",\n\t\t\t\"rename,0-67-1,Tion Thermostat Heat\",\n\t\t\t\"rename,0-38,Tion Fan Speed\",\n\t\t\t\"rename,1-37,Tion On/Off\",\n\t\t\t\"rename,2-37,Tion Recycling/Input Ventilation\"\n\t\t],\n\t\t\"author_last_update\": \"2021-02-19 17:00:00\",\n\t\t\"author\": \"SMR\",\n\t\t\"tester\": \"SMR\",\n\t\t\"tester_last_update\": \"2021-02-19 17:00:00\",\n\t\t\"commentary\": \"Removed extra widgets, rename\",\n\t\t\"created\": \"2021-02-19 17:00:00\"\n\t },{\n\t\t\"id\": \"365\",\n\t\t\"p_id\": \"277.256.2320\",\n\t\t\"p_sku\": \"ZME_TION4S\",\n\t\t\"product\": \"Tion 4S\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"renameNode,Tion 4S\",\n\t\t\t\"noVDev,0-37\",\n\t\t\t\"noVDev,0-38\",\n\t\t\t\"noVDev,0-49-1\",\n\t\t\t\"rename,0-64,Tion Heat operation\",\n\t\t\t\"rename,0-67-1,Tion Heat\",\n\t\t\t\"rename,1-37,Tion On/Off\",\n\t\t\t\"rename,2-37,Tion Recycling/Input Ventilation\",\n\t\t\t\"rename,3-38,Tion Fan Speed\",\n\t\t\t\"rename,4-49-1,Tion Inflow Temperature\",\n\t\t\t\"rename,5-49-1,Tion Out Temperature\",\n\t\t\t\"if (self.zway.devices[nodeId].SwitchMultilevel.data.interviewDone.value == false) {self.zway.devices[nodeId].SwitchMultilevel.data.interviewDone.value = true}\"\n\t\t],\n\t\t\"author_last_update\": \"2021-04-12 17:00:00\",\n\t\t\"author\": \"SMR\",\n\t\t\"tester\": \"SMR\",\n\t\t\"tester_last_update\": \"2021-04-12 17:00:00\",\n\t\t\"commentary\": \"Removed extra widgets, rename\",\n\t\t\"created\": \"2021-02-19 17:00:00\"\n\t},{\n                \"id\": \"367\",\n                \"p_id\": \"316.2.123\",\n                \"p_sku\": \"PAT13\",\n                \"product\": \"Philio PAT13\",\n                \"apply_postfix\": \"1\",\n                \"preInterview\": [],\n                \"postInterview\": [\n                        \"renameNode,Philio PAT13 Temperature Sensor\",\n                        \"emulateOff,0-113-7-3,10000\",\n                        \"if (self.zway.devices[nodeId].Alarm.data[7].status.value == null) {self.zway.devices[nodeId].Alarm.Set(7,255);}\"\n                ],\n                \"author_last_update\": \"2022-01-14 18:46:50\",\n                \"author\": \"AIVS\",\n                \"tester\": \"AIVS\",\n                \"tester_last_update\": \"2022-01-14 18:46:50\",\n                \"commentary\": \"AutoOff on the Alarm button, set Alarm On\",\n                \"created\": \"2022-01-14 18:46:50\"\n\t}, {\n\t\t\"id\": \"368\",\n\t\t\"p_id\": \"1043.4.3\",\n\t\t\"p_sku\": \"RehauSmartGuad\",\n\t\t\"product\": \"Rehau Smart Guard\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\n\t\t\t\"tilt,0-113-6\",\n\t\t\t\"notificationStatus,0-113-7\",\n\t\t\t\"configVDev,0,3,switchBinary,return value?'off':'on',return command=='on'?0:1,PIR High Sensitivity\",\n\t\t\t\"configVDev,0,6,switchBinary,return value?'on':'off',return command=='on'?1:0,Pre Alarm Activated\",\n\t\t\t\"if(commandClassId==0x84 && self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Wakeup){self.zway.devices[nodeId].Wakeup.Set(120,self.zway.controller.data.nodeId.value);}\"\n\t\t],\n\t\t\"author_last_update\": \"2022-06-10 18:46:50\",\n\t\t\"author\": \"PS\",\n\t\t\"tester\": \"PS\",\n\t\t\"tester_last_update\": \"2022-06-10 18:46:50\",\n\t\t\"commentary\": \"Tilt, Config #6 VDev\",\n\t\t\"created\": \"2022-06-10 18:46:50\"\n\t},{\n\t\t\"id\": \"369\",\n\t\t\"p_id\": \"265.8223.7952\",\n\t\t\"p_sku\": \"VISEZD2202-5\",\n\t\t\"product\": \"Zipato 4in1 sensor\",\n\t\t\"apply_postfix\": \"1\",\n\t\t\"preInterview\": [],\n\t\t\"postInterview\": [\"rename,0-113-7-3,Tamper\",\n\t\t\t\"renameNode,Zipato 4in1 sensor\",\n\t\t\t\"rename,0-113-6,Door/Window Sensor\",\n\t\t\t\"rename,0-49-1,Temperature Sensor\",\n\t\t\t\"rename,0-49-3,Humidity Sensor\",\n\t\t\t\"rename,0-49-5,Luminiscence Sensor\",\n\t\t\t\"icon,0-113-6,door\",\n\t\t\t\"icon,0-113-7-3,tamper\",\n\t\t\t\"if(self.zway.controller.data.lastIncludedDevice.value === nodeId && self.zway.devices[nodeId].Association.data.groups.value){self.zway.devices[nodeId].Association.Set(1,1,0);}\",\n\t\t\t\"if (self.zway.devices[nodeId].AssociationGroupInformation.data.interviewDone.value == false) {self.zway.devices[nodeId].AssociationGroupInformation.data.interviewDone.value = true}\"\n\t\t],\n\t\t\"author_last_update\": \"2022-06-17 00:00:00\",\n\t\t\"author\": \"SMR\",\n\t\t\"tester\": \"SMR\",\n\t\t\"tester_last_update\": \"2022-06-17 00:00:00\",\n\t\t\"commentary\": \"rename and change icon of devices 0-113-7-3 and 0-113-6,rename node, add association, interview done for AGE\",\n\t\t\"created\": \"2022-06-17 00:00:00\"\n\t}]\n}\n"
  },
  {
    "path": "modules/Zigbee/index.js",
    "content": "/*** Zigbee Binding module ********************************************************\n\nVersion: 1.0.0\n-------------------------------------------------------------------------------\nAuthor: Serguei Poltorak <ps@z-wave.me>\nCopyright: (c) Z-Wave.Me, 2022\n\n******************************************************************************/\n\nif (!String.prototype.padStart) {\n\tString.prototype.padStart = function padStart(targetLength,padString) {\n\t\ttargetLength = targetLength>>0; //floor if number or convert non-number to 0;\n\t\tpadString = String(padString || ' ');\n\t\tif (this.length > targetLength) {\n\t\t\treturn String(this);\n\t\t}\n\t\telse {\n\t\t\ttargetLength = targetLength-this.length;\n\t\t\tif (targetLength > padString.length) {\n\t\t\t\tpadString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed\n\t\t\t}\n\t\t\treturn padString.slice(0,targetLength) + String(this);\n\t\t}\n\t};\n}\n\n\nfunction Zigbee(id, controller) {\n\n\t// if called without \"new\", return list of loaded Z-Bee instances\n\tif (!(this instanceof Zigbee))\n\t\treturn Zigbee.list();\n\n\tZigbee.super_.call(this, id, controller);\n\n\tthis.ZWAY_DEVICE_CHANGE_TYPES = {\n\t\t\"DeviceAdded\": 0x01,\n\t\t\"DeviceRemoved\": 0x02,\n\t\t\"EndPointAdded\": 0x04,\n\t\t\"EndPointRemoved\": 0x08,\n\t\t\"ClusterAdded\": 0x10,\n\t\t\"ClusterRemoved\": 0x20,\n\t\t\"ZDDXSaved\": 0x100,\n\t\t\"EnumerateExisting\": 0x200\n\t};\n\n\tthis.ZWAY_DATA_CHANGE_TYPE = {\n\t\t\"Updated\": 0x01, // Value updated or child created\n\t\t\"Invalidated\": 0x02, // Value invalidated\n\t\t\"Deleted\": 0x03, // Data holder deleted - callback is called last time before being deleted\n\t\t\"ChildCreated\": 0x04, // New direct child node created\n\n\t\t// ORed flags\n\t\t\"PhantomUpdate\": 0x40, // Data holder updated with same value (only updateTime changed)\n\t\t\"ChildEvent\": 0x80 // Event from child node\n\t};\n\n\tthis.CC = {\n\t\t\"OnOff\": 0x0006,\n\t\t\"LevelControl\": 0x0008,\n\t\t\"DoorLock\": 0x0101,\n\t\t\"WindowCovering\": 0x0102,\n\t\t\"ColorControl\": 0x0300,\n\t\t\"TemperatureMeasurement\": 0x0402,\n\t\t\"PressureMeasurement\": 0x0403,\n\t\t\"RelativeHumidityMeasurement\": 0x0405,\n\t\t\"OccupancySensing\": 0x0406,\n\t\t\"IasZone\": 0x0500,\n\t\t\"Metering\": 0x0702,\n\t};\n}\n\n// Module inheritance and setup\n\ninherits(Zigbee, AutomationModule);\n\n_module = Zigbee;\n\nObject.defineProperty(Zigbee, \"list\", {\n\tvalue: function(__, req) {\n\t\t// show in the list if called directly (not via web) or role is admin or API is public\n\t\treturn Object.keys(Zigbee).filter(function(name) {\n\t\t\treturn !req || req.role == controller.auth.ROLE.ADMIN || Zigbee[name].publicAPI;\n\t\t});\n\t},\n\tenumerable: false,\n\twritable: false,\n\tconfigurable: false\n});\n\nws.allowExternalAccess(\"Zigbee.list\", controller.auth.ROLE.ANONYMOUS); // we handle role inside the handler\n\nZigbee.prototype.updateList = function() {\n\tthis.controller.setNamespace(\"zbees\", this.controller.namespaces, Zigbee.list().map(function(name) {\n\t\treturn {\n\t\t\tzbeeName: name\n\t\t};\n\t}));\n};\n\nZigbee.prototype.loadObject = function(name) {\n\ttry {\n\t\treturn loadObject(this.config.name + \"_\" + name);\n\t} catch (e) {\n\t\tthis.addNotification('warning','Error in storage file: '+ name + ' detected. Unable to load data - ERROR: '+ e.toString() + ' File will be rewritten if possible.','z-wave');\n\t\treturn null;\n\t}\n};\n\nZigbee.prototype.saveObject = function(name, obj, immediate) {\n\treturn saveObject(this.config.name + \"_\" + name, obj, immediate);\n};\n\nZigbee.prototype.init = function(config) {\n\tZigbee.super_.prototype.init.call(this, config);\n\n\tvar self = this;\n\n\tthis.restartBindingCounter = 0;\n\n\tthis.startBinding();\n\tif (!this.zbee) {\n\t\treturn;\n\t}\n\n\tthis._dataBind = function(dataBindings, zbeeName, nodeId, endpointId, clusterId, path, func, type) {\n\t\tif (zbeeName === self.config.name && self.zbee) {\n\t\t\tself.dataBind(dataBindings, self.zbee, nodeId, endpointId, clusterId, path, func, type);\n\t\t}\n\t};\n\tthis._dataUnbind = function(dataBindings) {\n\t\tself.dataUnbind(dataBindings);\n\t};\n\n\tthis.controller.on(\"Zigbee.dataBind\", this._dataBind);\n\tthis.controller.on(\"Zigbee.dataUnbind\", this._dataUnbind);\n\n\tthis.controller.emit(\"Zigbee.register\", this.config.name);\n};\n\nZigbee.prototype.startBinding = function() {\n\tvar self = this;\n\n\ttry {\n\t\tthis.zbee = new ZigbeeBinding(this.config.name, this.config.port, this.config.speed || 115200, {\n\t\t\tconfigFolder: this.config.config || 'config',\n\t\t\ttranslationsFolder: this.config.translations || 'translations',\n\t\t\tzddxFolder: this.config.ZDDX || 'ZDDX',\n\t\t\tterminationCallback: function() {\n\t\t\t\tself.terminating.call(self);\n\t\t\t}\n\t\t});\n\n\t\ttry {\n\t\t\tthis.zbee.discover();\n\t\t} catch (e1) {\n\t\t\tthis.zbee.stop();\n\t\t\tconsole.log(e1.toString());\n\t\t\treturn;\n\t\t}\n\t} catch (e) {\n\t\tthis.zbee = null;\n\t\tconsole.log(e.toString());\n\t\tthis.tryRestartLater(e);\n\t\treturn;\n\t}\n\n\t// started\n\tthis.restartBindingCounter = 0;\n\n\tthis.fastAccess = false;\n\tif (!global.zbee) {\n\t\t// this is the first zbee - make fast shortcut\n\t\tthis.fastAccess = true;\n\t}\n\n\tglobal.Zigbee[this.config.name] = {\n\t\t\"zbee\": this.zbee,\n\t\t\"port\": this.config.port,\n\t\t\"publicAPI\": this.config.publicAPI,\n\t\t\"fastAccess\": this.fastAccess\n\t};\n\tthis.updateList();\n\n\tthis.stopped = false;\n\n\tif (this.config.enableAPI !== false) {\n\t\tthis.defineHandlers();\n\t}\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIAllow();\n\t\t}\n\t\tglobal[\"zbee\"] = this.zbee; // global variable\n\t\tglobal[\"ZigbeeAPI\"] = this.ZigbeeAPI;\n\t}\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIAllow(this.config.name);\n\t}\n\t_.extend(global[\"Zigbee\"][this.config.name], this.ZigbeeAPI);\n\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStart();\n\t}\n\n\tthis.timeUpdaterStart();\n\n\t// save data every hour for hot start\n\tthis.saveDataXMLTimer = setInterval(function() {\n\t\tself.zbee.devices.SaveData();\n\t}, 3600 * 1000);\n\n\tvar uartSpeed = function(type) {\n\t\tvar data = this;\n\n\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE[\"Updated\"])\n\t\tif (self.config.speed !== data.value) {\n\t\t\tself.config.speed = data.value;\n\t\t\tself.saveConfig();\n\t\t\tself.zbee.stop();\n\t\t\tself.tryRestartLater();\n\t\t}\n\n\t}\n\t//TODO//this.zbee.controller.data.hardware.uartSpeed.bind(uartSpeed);\n};\n\nZigbee.prototype.stop = function() {\n\tconsole.log(\"--- Zigbee.stop()\");\n\tZigbee.super_.prototype.stop.call(this);\n\n\tthis.stopBinding();\n\n\tif (this._dataBind) {\n\t\tthis.controller.off(\"Zigbee.dataBind\", this._dataBind);\n\t}\n\tif (this._dataUnbind) {\n\t\tthis.controller.off(\"Zigbee.dataUnbind\", this._dataUnbind);\n\t}\n};\n\nZigbee.prototype.stopBinding = function() {\n\tthis.controller.emit(\"Zigbee.unregister\", this.config.name);\n\n\tthis.networkReorganization = null;\n\n\tif (this.config.createVDev !== false) {\n\t\tthis.gateDevicesStop();\n\t}\n\n\tthis.timeUpdaterStop();\n\n\tif (this.fastAccess) {\n\t\tif (this.config.enableAPI !== false) {\n\t\t\tthis.externalAPIRevoke();\n\t\t}\n\t\tif (global.zbee) {\n\t\t\tdelete global[\"zbee\"];\n\t\t\tdelete global[\"ZigbeeAPI\"];\n\t\t}\n\t}\n\n\tif (this.config.enableAPI !== false) {\n\t\tthis.externalAPIRevoke(this.config.name);\n\t}\n\n\tif (global.Zigbee) {\n\t\tdelete global.Zigbee[this.config.name];\n\t\tthis.updateList();\n\t}\n\n\tif (this.saveDataXMLTimer) {\n\t\tclearInterval(this.saveDataXMLTimer);\n\t\tthis.saveDataXMLTimer = undefined;\n\t}\n\n\tthis.stopped = true;\n\tif (this.zbee) {\n\t\ttry {\n\t\t\tthis.zbee.stop();\n\t\t} catch (e) {\n\t\t\t// Z-Bee has already gone\n\t\t}\n\t\tthis.zbee = null;\n\t}\n};\n\nZigbee.prototype.tryRestartLater = function(e) {\n\tvar delay = 10;\n\n\tif (this.restartBindingCounter < 5) {\n\t\tvar self = this;\n\n\t\tconsole.log(\"Trying to restart Zigbee binding (\" + this.config.name + \") in \" + delay + \" seconds\");\n\t\tthis.restartBindingCounter++;\n\n\t\tsetTimeout(function() {\n\t\t\t// retry open after N seconds\n\t\t\tconsole.log(\"Restarting Zigbee binding (\" + self.config.name + \")\");\n\t\t\tself.startBinding();\n\t\t}, delay * 1000);\n\n\t} else {\n\t\tvar langFile = this.loadModuleLang();\n\n\t\tconsole.log(\"Tried \" + this.restartBindingCounter + \" times without success. Stopping tries.\");\n\t\tthis.addNotification(\"critical\", langFile.err_binding_start + e.toString(), \"z-wave\");\n\t}\n};\n\nZigbee.prototype.terminating = function() {\n\tif (!this.stopped) {\n\t\tconsole.log(\"Terminating Zigbee binding\");\n\t\tthis.stopBinding();\n\t\tthis.tryRestartLater();\n\t}\n};\n\n\n// --------------- Public HTTP API -------------------\n\n\nZigbee.prototype.externalAPIAllow = function(name) {\n\tvar _name = !!name ? (\"Zigbee.\" + name) : \"ZigbeeAPI\";\n\n\tws.allowExternalAccess(_name, this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Run\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Data\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".InspectQueue\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\t/*\n\tws.allowExternalAccess(_name + \".Backup\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".Restore\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".FirmwareUpdate\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMELicense\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMEFirmwareUpgrade\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".ZMEBootloaderUpgrade\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\tws.allowExternalAccess(_name + \".EncryptionKeys\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n\t*/\n\t// -- see below -- // ws.allowExternalAccess(_name + \".JSONtoXML\", this.config.publicAPI ? this.controller.auth.ROLE.ANONYMOUS : this.controller.auth.ROLE.ADMIN);\n};\n\nZigbee.prototype.externalAPIRevoke = function(name) {\n\tvar _name = !!name ? (\"Zigbee.\" + name) : \"ZigbeeAPI\";\n\n\tws.revokeExternalAccess(_name);\n\tws.revokeExternalAccess(_name + \".Run\");\n\tws.revokeExternalAccess(_name + \".Data\");\n\tws.revokeExternalAccess(_name + \".InspectQueue\");\n\t/*\n\tws.revokeExternalAccess(_name + \".Backup\");\n\tws.revokeExternalAccess(_name + \".Restore\");\n\tws.revokeExternalAccess(_name + \".FirmwareUpdate\");\n\tws.revokeExternalAccess(_name + \".ZMELicense\");\n\tws.revokeExternalAccess(_name + \".ZMEFirmwareUpgrade\");\n\tws.revokeExternalAccess(_name + \".ZMEBootloaderUpgrade\");\n\tws.revokeExternalAccess(_name + \".EncryptionKeys\");\n\t*/\n\t// -- see below -- // ws.revokeExternalAccess(_name + \".JSONtoXML\");\n};\n\nZigbee.prototype.defineHandlers = function() {\n\tvar zbee = this.zbee; // for with() statement in Run and other APIs\n\tvar self = this;\n\n\tthis.ZigbeeAPI = function() {\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Bad ZigbeeAPI request \"\n\t\t};\n\t};\n\n\tthis.ZigbeeAPI.list = function() {\n\t\ttry {\n\t\t\treturn Zigbee.list() || [];\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.Run = function(url) {\n\t\turl = \"with(zbee) { \" + url.substring(1) + \" }\";\n\t\ttry {\n\t\t\tvar r = eval(url);\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t},\n\t\t\t\tbody: r\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.Data = function(url) {\n\t\tvar timestamp = parseInt(url.substring(1), 10) || 0;\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zbee.data(timestamp)\n\t\t};\n\t};\n\n\tthis.ZigbeeAPI.InspectQueue = function(url) {\n\t\treturn {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t},\n\t\t\tbody: zbee.InspectQueue()\n\t\t};\n\t};\n\n\t/*\n\tthis.ZigbeeAPI.Backup = function(url, request) {\n\t\tvar now = new Date();\n\n\t\t// create a timestamp in format yyyy-MM-dd-HH-mm\n\t\tvar ts = getHRDateformat(now);\n\n\t\ttry {\n\n\t\t\t// do backup\n\t\t\tvar data = zbee.controller.Backup();\n\t\t\tvar filename = \"z-way-backup-\" + ts + \".zbk\"\n\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/x-download\",\n\t\t\t\t\t\"Content-Disposition\": \"attachment; filename=\" + filename\n\t\t\t\t},\n\t\t\t\tbody: data\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.Restore = function(url, request) {\n\t\tif (request.method === \"POST\" && request.data && request.data && request.data.config_backup) {\n\t\t\tvar full = false;\n\t\t\tif (request.query && request.query.hasOwnProperty(\"restore_chip_info\")) {\n\t\t\t\tvar rci = request.query[\"restore_chip_info\"];\n\t\t\t\tfull = (rci === \"yes\" || rci === \"true\" || rci === \"1\");\n\t\t\t}\n\n\t\t\tvar file = request.data.config_backup;\n\t\t\tif (file endpointof Array) {\n\t\t\t\tfile = file[0];\n\t\t\t}\n\t\t\tif (file.name && file.content && file.length > 0) {\n\t\t\t\t// valid file object detected\n\t\t\t\ttry {\n\t\t\t\t\tzbee.controller.Restore(file.content, full);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\"Content-Type\": \"application/json\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbody: null\n\t\t\t\t\t};\n\t\t\t\t} catch (e) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tbody: e.toString()\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tstatus: 400,\n\t\t\tbody: \"Invalid request\"\n\t\t};\n\t};\n\n\tthis.ZigbeeAPI.FirmwareUpdate = function(url, request) {\n\t\ttry {\n\t\t\tvar deviceId = parseInt(url.substring(1), 10);\n\t\t\tif (!deviceId) {\n\t\t\t\tthrow \"Invalid device id\";\n\t\t\t}\n\n\t\t\tvar fwUpdate = zbee.devices[deviceId].FirmwareUpdate;\n\t\t\tif (!fwUpdate) {\n\t\t\t\tthrow \"Device doesn't support FW Update\";\n\t\t\t}\n\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar manufacturerId = fwUpdate.data.manufacturerId.value;\n\t\t\tvar targetId = parseInt(data.targetId);\n\t\t\tvar firmwareId = targetId == 0 ? fwUpdate.data.firmwareId.value : fwUpdate.data[\"firmware\" + targetId].value;\n\t\t\t\n\t\t\tif (!manufacturerId && manufacturerId !== 0 || !firmwareId && firmwareId !== 0) {\n\t\t\t\tthrow \"Either manufacturer or firmware id is not present\";\n\t\t\t}\n\n\t\t\tif (targetId === 0 && !fwUpdate.data.upgradeable.value) {\n\t\t\t\tthrow \"Firmware is not upgradeable\";\n\t\t\t}\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\t// update firmware from file\n\t\t\t\tvar fw;\n\t\t\t\tif (data.file.content.substr(0, 1) === \":\") {\n\t\t\t\t\t// this is a .hex file\n\t\t\t\t\tfw = IntelHex2bin(data.file.content);\n\t\t\t\t} else {\n\t\t\t\t\tfw = data.file.content;\n\t\t\t\t}\n\t\t\t\tfwUpdate.Perform(manufacturerId, firmwareId, targetId, fw);\n\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: \"Initiating update\"\n\t\t\t\t};\n\t\t\t} else if (data.url) {\n\t\t\t\tvar result = {\n\t\t\t\t\tstatus: 'in progress'\n\t\t\t\t};\n\t\t\t\tvar d = Date.now() + 300000; // wait no more than 5 min\n\t\t\t\t// update firmware from url\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tcontentType: \"application/octet-stream\", // enforce binary response,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tsuccess: function(res) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tvar data = new Uint8Array(res.data);\n\t\t\t\t\t\t\tvar data_str = \"\";\n\t\t\t\t\t\t\tfor (var i = 0; i < data.length; i++) {\n\t\t\t\t\t\t\t\tdata_str += String.fromCharCode(data[i]);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar fw;\n\t\t\t\t\t\t\tif (data_str.substr(0, 1) === \":\") {\n\t\t\t\t\t\t\t\t// this is a .hex file\n\t\t\t\t\t\t\t\tfw = IntelHex2bin(data_str);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfw = data_str;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfwUpdate.Perform(manufacturerId, firmwareId, targetId, fw);\n\n\t\t\t\t\t\t\tresult.status = 'done';\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tresult.error = 'Firmware download successful. Parsing has failed: ' + e.toString();\n\t\t\t\t\t\t\tresult.status = 'fail';\n\t\t\t\t\t\t\tthrow ('Firmware download successful. Parsing has failed: ' + e.toString());\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tresult.error = 'Failed to download firmware: ' + res.statusText;\n\t\t\t\t\t\tresult.status = 'fail';\n\t\t\t\t\t\tthrow ('Failed to download firmware: ' + res.statusText);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\twhile (Date.now() < d && result.status === \"in progress\") {\n\t\t\t\t\tprocessPendingCallbacks();\n\t\t\t\t}\n\n\t\t\t\tresult.status = result.status === 'in progress' ? 'fail' : result.status;\n\n\t\t\t\tif (result.status === 'fail') {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\tbody: result.error\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 200,\n\t\t\t\t\t\tbody: \"Initiating update\"\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.ZMELicense = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data || !data.license) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\t\t\t\n\t\t\tvar func, lic;\n\t\t\tif (parseFloat(zbee.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\tfunc = zbee.ZMELicenseSet;\n\t\t\t\tlic = data.license.match(/.{2}/g).map(function(i, v) { return parseInt(i, 16); });\n\t\t\t} else {\n\t\t\t\tfunc = zbee.ZMECapabilities;\n\t\t\t\tlic = data.license.split(\",\").map(function(i) { return parseInt(i, 10); });\n\t\t\t}\n\t\t\t\n\t\t\tfunc.call(zbee, lic, function() {\n\t\t\t\tresult = \"done\";\n\t\t\t}, function() {\n\t\t\t\tresult = \"failed\";\n\t\t\t});\n\n\t\t\tvar d = Date.now() + 20000; // wait not more than 20 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.ZMEFirmwareUpgrade = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tif (zbee.controller.data.SDK.value === null) {\n\t\t\t\tconsole.log(\"Unknown SDK version - update Z-Way\");\n\t\t\t\tthrow \"Unknown SDK version - update Z-Way\";\n\t\t\t}\n\n\t\t\tvar L = 32,\n\t\t\t\taddr,\n\t\t\t\tskip1800;\n\n\t\t\tif (parseFloat(zbee.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t// ZGM130S/ZG14\n\t\t\t\tskip1800 = false;\n\t\t\t\taddr = 0x3A000;\n\t\t\t} else {\n\t\t\t\t// ZM5101/SD3503/ZM5202\n\t\t\t\tif (zbee.controller.data.manufacturerId.value === 0) { // Z-Wave.Me Hub\n\t\t\t\t\tskip1800 = true;\n\t\t\t\t\taddr =  0x7800; // M25PE10\n\t\t\t\t} else {\n\t\t\t\t\tskip1800 =\n\t\t\t\t\t\tzbee.controller.data.bootloader.crc.value !== 0x8aaa // bootloader for RaZberry 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzbee.controller.data.bootloader.crc.value !== 0x7278 // bootloader for UZB 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzbee.controller.data.bootloader.crc.value !== 0x9d04 // bootloader for UZB 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tzbee.controller.data.bootloader.crc.value !== 0x8b4b // bootloader for Z-Box 6.70\n\t\t\t\t\t\t&&\n\t\t\t\t\t\tparseFloat(zbee.controller.data.SDK.value.substr(0, 4)) < 6.71; // bootloader for 6.71 SDK\n\t\t\t\t\taddr = skip1800 ? 0x7800: 0x20000; // M25PE40 on old and new SDKs\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\tconsole.log(\"Fetching firmware from file \" + data.file.name);\n\n\t\t\t\tvar buf = new ArrayBuffer(data.file.content.length);\n\t\t\t\tvar bufView = new Uint8Array(buf);\n\t\t\t\tfor (var i = 0; i < data.file.content.length; i++) {\n\t\t\t\t\tbufView[i] = data.file.content.charCodeAt(i);\n\t\t\t\t}\n\n\t\t\t\tvar data = skip1800 ? buf.slice(0x1800) : buf;\n\n\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t}\n\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t}\n\n\t\t\t\tzbee.NVMExtWriteLongBuffer(addr - 2, [0, 1], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tzbee.SerialAPISoftReset(function() {\n\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\tzbee.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t} else if (data.url) {\n\t\t\t\tconsole.log(\"Fetching firmware from \" + data.url);\n\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcontentType: \"application/octet-stream\",\n\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\tvar data = skip1800 ? response.data.slice(0x1800) : response.data;\n\n\t\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr - 2, [0, 1], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\tzbee.SerialAPISoftReset(function() {\n\t\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\t\tzbee.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tconsole.error(\"Failed to download firmware: \" + res.statusText);\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Wrong request. Failed to apply firmware.\");\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 300 * 1000; // wait not more than 5 minutes\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.ZMEBootloaderUpgrade = function(url, request) {\n\t\ttry {\n\t\t\tvar data = request && request.data;\n\t\t\tif (!data) {\n\t\t\t\tthrow \"Invalid request\";\n\t\t\t}\n\n\t\t\tvar result = \"in progress\";\n\n\t\t\tif (data.file && data.file.content) {\n\t\t\t\tconsole.log(\"Fetching bootloader from file \" + data.file.name);\n\t\t\t\t\n\t\t\t\tvar buf = new ArrayBuffer(data.file.content.length);\n\t\t\t\tvar bufView = new Uint8Array(buf);\n\t\t\t\tfor (var i = 0; i < data.file.content.length; i++) {\n\t\t\t\t\tbufView[i] = data.file.content.charCodeAt(i);\n\t\t\t\t}\n\t\t\t\tvar data = buf;\n\n\t\t\t\tif (parseFloat(zbee.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t\tvar arr = (new Uint8Array(data.slice(0, 30)));\n\t\t\t\t\tzbee.ZMEBootloaderLoadFlash(data.slice(0, 5), function() {\n\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\tzbee.stop(); // to force re-start Z-Way\n\t\t\t\t\t}, function() {\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tvar L = 32,\n\t\t\t\t\t\tseg = 6, // Функция бутлодера принимает номер сегмента\n\t\t\t\t\t\taddr = seg * 0x800; // ==12k\n\n\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t}\n\t\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t}\n\n\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr - 2, [0, 0], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t//Вызываем перезапись bootloder\n\t\t\t\t\t\t\tzbee.ZMEBootloaderFlash(seg, function() {\n\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\tzbee.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (data.url) {\n\t\t\t\thttp.request({\n\t\t\t\t\turl: data.url,\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcontentType: \"application/octet-stream\",\n\t\t\t\t\tsuccess: function(response) {\n\t\t\t\t\t\tif (parseFloat(zbee.controller.data.SDK.value.substr(0, 4)) >= 7.12) {\n\t\t\t\t\t\t\tzbee.ZMEBootloaderLoadFlash(data, function() {\n\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\tzbee.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar L = 32,\n\t\t\t\t\t\t\t\tseg = 6, // Функция бутлодера принимает номер сегмента\n\t\t\t\t\t\t\t\taddr = seg * 0x800, // ==12k\n\t\t\t\t\t\t\t\tdata = response.data;\n\n\t\t\t\t\t\t\tfor (var i = 0; i < data.byteLength; i += L) {\n\t\t\t\t\t\t\t\tvar arr = (new Uint8Array(data.slice(i, i + L)));\n\t\t\t\t\t\t\t\tif (arr.length == 1) {\n\t\t\t\t\t\t\t\t\tarr = [arr[0]]\n\t\t\t\t\t\t\t\t\tarr.push(0xff); // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr + i, arr);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tzbee.NVMExtWriteLongBuffer(addr - 2, [0, 0], // we only need one byte, but a due to some error single byte is not read\n\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t//Вызываем перезапись bootloder\n\t\t\t\t\t\t\t\t\tzbee.ZMEBootloaderFlash(seg, function() {\n\t\t\t\t\t\t\t\t\t\tresult = \"done\";\n\t\t\t\t\t\t\t\t\t\tzbee.stop(); // to force re-start Z-Way\n\t\t\t\t\t\t\t\t\t}, function() {\n\t\t\t\t\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\terror: function(res) {\n\t\t\t\t\t\tconsole.error(\"Failed to download bootloader: \" + res.statusText);\n\t\t\t\t\t\tresult = \"failed\";\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.error(\"Wrong request. Failed to apply bootloader.\");\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\n\t\t\tvar d = Date.now() + 60 * 1000; // wait not more than 60 seconds\n\n\t\t\twhile (Date.now() < d && result === \"in progress\") {\n\t\t\t\tprocessPendingCallbacks();\n\t\t\t}\n\n\t\t\tif (result === \"in progress\") {\n\t\t\t\tresult = \"failed\";\n\t\t\t}\n\t\t\treturn (result === \"done\") ? {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: \"Done\"\n\t\t\t} : {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: \"Failed\"\n\t\t\t};\n\t\t} catch (e) {\n\t\t\treturn {\n\t\t\t\tstatus: 500,\n\t\t\t\tbody: e.toString()\n\t\t\t};\n\t\t}\n\t};\n\n\tthis.ZigbeeAPI.EncryptionKeys = function () {\n\t\tvar filename = ('00000000' + (zbee.controller.data.homeId.value + (zbee.controller.data.homeId.value < 0 ? 0x100000000 : 0)).toString(16)).slice(-8)\n\t\tvar reply = {\n\t\t\tstatus: 200,\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"text/plain\", // application/x-download octet-stream\n\t\t\t\t\"Content-Disposition\": \"attachment; filename=\" + filename.toUpperCase() + \".txt\",\n\t\t\t},\n\t\t\tbody: null,\n\t\t\terror: null,\n\t\t\tmessage: null\n\t\t};\n\t\tvar networkKeys = [zbee.devices[zbee.controller.data.nodeId.value].data.networkKey.value];\n\t\tvar keys = zbee.devices[zbee.controller.data.nodeId.value].data.networkKeys;\n\t\tif (keys) {\n\t\t\tnetworkKeys.push(keys.S2Unauthenticated.value, keys.S2Authenticated.value, keys.S2Access.value);\n\t\t}\n\t\tif (keys.S2AuthenticatedLR) {\n\t\t\tnetworkKeys.push(keys.S2AuthenticatedLR.value, keys.S2AccessLR.value)\n\t\t}\n\n\t\treply.body = networkKeys.map(function (key, index) {\n\t\t\treturn (index ? '9F' : '98') + ';' + (key ? key : new Array(16).fill(0))\n\t\t\t\t.map(function (e) {return (+e).toString(16).padStart(2, '0').toUpperCase()}).join('') + ';1';\n\t\t}).join('\\r\\n');\n\n\t\treturn reply;\n\t}\n\t*/\n};\n\n\n// ------------- Data Binding --------------\n\nZigbee.prototype._dataBind = function(dataBindings, zbeeName, nodeId, endpointId, clusterId, path, func, type) {\n\tif (zbeeName === this.config.name) {\n\t\tthis.dataBind(dataBindings, this.zbee, nodeId, endpointId, clusterId, path, func, type);\n\t}\n}\nZigbee.prototype.dataBind = function(dataBindings, zbee, nodeId, endpointId, clusterId, path, func, type) {\n\t// three prototypes:\n\t//  (dataBindings, zbee, nodeId, endpointId, clusterId, path, func, type)\n\t//  (dataBindings, zbee, nodeId,                             path, func)\n\t//  (dataBindings, zbee,                                     path, func) // bind to controller data\n\n\tvar pathArr = [],\n\t\tdata = null,\n\t\tctrlBind = is_function(endpointId),\n\t\tdevBind = is_function(clusterId);\n\n\tif (ctrlBind) {\n\t\tpath = nodeId;\n\t\tfunc = endpointId;\n\t\tnodeId = undefined;\n\t\tendpointId = undefined;\n\t\tclusterId = undefined;\n\t\tdata = zbee.controller.data;\n\t} else if (devBind) {\n\t\tpath = endpointId;\n\t\tfunc = clusterId;\n\t\tendpointId = undefined;\n\t\tclusterId = undefined;\n\t\tdata = zbee.devices[nodeId].data;\n\t} else {\n\t\tdata = zbee.devices[nodeId].endpoints[endpointId].clusters[clusterId].data;\n\t}\n\n\tif (path) {\n\t\tpathArr = path.split(\".\");\n\t}\n\n\tif (!func) {\n\t\tconsole.log(\"Function passed to dataBind is undefined\");\n\t\treturn;\n\t}\n\n\twhile (pathArr.length) {\n\t\tdata = data[pathArr.shift()];\n\t\tif (!data) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tif (data) {\n\t\tif (ctrlBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zbee\": zbee,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, false)\n\t\t\t});\n\t\t} else if (devBind) {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zbee\": zbee,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, nodeId, false)\n\t\t\t});\n\t\t} else {\n\t\t\tdataBindings.push({\n\t\t\t\t\"zbee\": zbee,\n\t\t\t\t\"nodeId\": nodeId,\n\t\t\t\t\"endpointId\": endpointId,\n\t\t\t\t\"clusterId\": clusterId,\n\t\t\t\t\"path\": path,\n\t\t\t\t\"func\": data.bind(func, null, type === \"child\")\n\t\t\t});\n\t\t\tif (type === \"value\") {\n\t\t\t\tfunc.call(data, this.ZWAY_DATA_CHANGE_TYPE.Updated);\n\t\t\t}\n\t\t}\n\t} else {\n\t\tconsole.log(\"Can not find data path:\", nodeId, endpointId, clusterId, path);\n\t}\n};\n\nZigbee.prototype.dataUnbind = function(dataBindings) {\n\tdataBindings.forEach(function(item) {\n\t\tvar ctrlBind = !(\"nodeId\" in item),\n\t\t\tdevBind = !(\"endpointId\" in item);\n\n\t\tif (item.zbee && item.zbee.isRunning() && (ctrlBind || (item.zbee.devices[item.nodeId] && (devBind || (item.zbee.devices[item.nodeId].endpoints[item.endpointId] && item.zbee.devices[item.nodeId].endpoints[item.endpointId].clusters[item.clusterId]))))) {\n\t\t\tvar data = ctrlBind ? item.zbee.controller.data : (devBind ? item.zbee.devices[item.nodeId].data : item.zbee.devices[item.nodeId].endpoints[item.endpointId].clusters[item.clusterId].data),\n\t\t\t\tpathArr = item.path ? item.path.split(\".\") : [];\n\n\t\t\twhile (pathArr.length) {\n\t\t\t\tdata = data[pathArr.shift()];\n\t\t\t\tif (!data) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (data) {\n\t\t\t\tdata.unbind(item.func);\n\t\t\t} else {\n\t\t\t\tconsole.log(\"Can not find data path:\", item.nodeId, item.endpointId, item.clusterId, item.path);\n\t\t\t}\n\t\t}\n\t});\n\tdataBindings = null;\n};\n\n// ------------- Update time every day -----\n\nZigbee.prototype.timeUpdaterStart = function() {\n\tvar self = this;\n\t\n\tthis.controller.emit(\"cron.addTask\", \"ZigbeeTimeUpdater.poll\", {\n\t\tminute: 0,\n\t\thour: 3,\n\t\tweekDay: null,\n\t\tday: null,\n\t\tmonth: null\n\t});\n\n\t// add event listener\n\tthis.timeUpdater = function() {\n\t\tvar devices = Object.keys(self.zbee.devices);\n\t\tdevices.forEach(function(nodeId) {\n\t\t\tif (nodeId == self.zbee.controller.data.nodeId.value) return; // not a strict === since nodeId is a string index, but number in DH\n\t\t\t\n\t\t\tif (self.zbee.devices[nodeId].TimeParameters)\n\t\t\t\tself.zbee.devices[nodeId].TimeParameters.Set();\n\t\t\tif (self.zbee.devices[nodeId].Clock)\n\t\t\t\tself.zbee.devices[nodeId].Clock.Set();\n\t\t});\n\t};\n\n\tthis.controller.on(\"ZigbeeTimeUpdater.poll\", this.timeUpdater);\n};\n\nZigbee.prototype.timeUpdaterStop = function() {\n\tthis.controller.emit(\"cron.removeTask\", \"ZigbeeTimeUpdater.poll\");\n\n\tif (this.timeUpdater)\n\t\tthis.controller.off(\"ZigbeeTimeUpdater.poll\", this.timeUpdater);\n}\n\n// ----------------- Devices Creator ---------------\n\n\nZigbee.prototype.gateDevicesStart = function() {\n\n\tvar self = this,\n\t\tfixesDone = [];\n\n\tthis.gateDataBinding = [];\n\n\t// Bind to all future ClusterClasses changes\n\tthis.gateBinding = this.zbee.bind(function(type, nodeId, endpointId, clusterId) {\n\t\tif (type === self.ZWAY_DEVICE_CHANGE_TYPES[\"ClusterAdded\"]) {\n\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"interviewDone\", function(type) {\n\t\t\t\tif (this.value === true && type !== self.ZWAY_DATA_CHANGE_TYPE[\"Deleted\"]) {\n\n\t\t\t\t\tvar create = true,\n\t\t\t\t\t\tchangeVDev = {},\n\t\t\t\t\t\tdeviceData = self.zbee.devices[nodeId].data,\n\t\t\t\t\t\tdeviceEndPoints = self.zbee.devices[nodeId].endpoints,\n\t\t\t\t\t\tdeviceCC = deviceEndPoints[endpointId].clusters[clusterId],\n\t\t\t\t\t\tc = self.zbee.controller,\n\t\t\t\t\t\tmC = deviceData.manufacturerCode.value ? deviceData.manufacturerCode.value : null,\n\t\t\t\t\t\t//appMajor = deviceData.applicationMajor.value ? deviceData.applicationMajor.value : null,\n\t\t\t\t\t\t//appMinor = deviceData.applicationMinor.value ? deviceData.applicationMinor.value : null,\n\t\t\t\t\t\tgivenName = null,\n\t\t\t\t\t\tdevId,\n\t\t\t\t\t\t//appMajorId,\n\t\t\t\t\t\t//appMajorMinorId,\n\t\t\t\t\t\tpostFix;\n\t\t\t\t\t\t//fixes = self.postfix.fixes ? self.postfix.fixes : self.postfix;\n\n\t\t\t\t\t// try to get fix by manufacturerProductId and application Version\n\t\t\t\t\t/* TODO - commented since mC and appMajor are to be implemented in the future\n\t\t\t\t\tif (!!mId && !!mPT && !!mPId && !!self.postfix) {\n\n\t\t\t\t\t\tdevId = mId + '.' + mPT + '.' + mPId;\n\t\t\t\t\t\tappMajorId = devId + '.' + appMajor;\n\t\t\t\t\t\tappMajorMinorId = devId + '.' + appMajor + '.' + appMinor;\n\t\t\t\t\t\tpostFix = fixes.filter(function(fix) {\n\t\t\t\t\t\t\treturn \tfix.p_id === mId.toString() || //search by manufacturerId\n\t\t\t\t\t\t\t\tfix.p_id === devId || //search by manufacturerProductId\n\t\t\t\t\t\t\t\tfix.p_id === appMajorId || //search by applicationMajor\n\t\t\t\t\t\t\t\tfix.p_id === appMajorMinorId; //search by applicationMajor and applicationMinor\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\t*/\n\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\t\t\t\t\t// --- postfix functions\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\n\t\t\t\t\t// add SwitchController support by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... endpoint ID\n\t\t\t\t\t// cluster ... Cluster Class ID\n\t\t\t\t\t// minBtnNr ... starting button number\n\t\t\t\t\t// maxBtnNr ... maximum button number\n\t\t\t\t\t// type ... 'S' for 'scene' and 'B' for 'button' or 'switchControl'\n\t\t\t\t\tfunction scenesSupport(instId, cluster, minBtnNr, maxBtnNr, type) {\n\t\t\t\t\t\tvar trapArray = [],\n\t\t\t\t\t\t\tcluster = cluster || null;\n\n\t\t\t\t\t\ttrapArray = self.controller.endpoints.filter(function(endpoint) {\n\t\t\t\t\t\t\treturn endpoint.moduleId === 'SwitchControlGenerator';\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (instId === endpointId && clusterId === cluster && deviceCC && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\tmaxBtnNr = (deviceCC.data.maxScenes && deviceCC.data.maxScenes.value && deviceCC.data.maxScenes.value <= maxBtnNr ? deviceCC.data.maxScenes.value : maxBtnNr) || 0\n\n\t\t\t\t\t\t\tif (trapArray[0].params.generated.indexOf('ZBeeVDev_zbee_Remote_' + nodeId + '-' + endpointId + '-0-1') === -1) {\n\t\t\t\t\t\t\t\tfor (i = minBtnNr; i <= maxBtnNr; i++) {\n\t\t\t\t\t\t\t\t\tthis.controller.emit('SwitchControlGenerator.register', 'ZBee', self.config.name, nodeId, endpointId, '0', i, type);\n\t\t\t\t\t\t\t\t\tconsole.logJS(i, minBtnNr, maxBtnNr);\n\n\t\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\t\tconsole.log('#######################', 'ADD SWITCHCONTROLGENERATOR SUPPORT TO #' + nodeId, '###############################');\n\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Add support for endpoint ' + instId + ':');\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'CC:', cluster);\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Set maximum number of buttons / secnes to :', maxBtnNr);\n\t\t\t\t\t\t\t\t\tconsole.log('###', 'Add virtual devices as type button (B) or scene (S):', type);\n\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\tconsole.log('############################################################################################################');\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// set device config by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... endpoint ID\n\t\t\t\t\t// parameter ... id of the parameter that should be changed. Can be 0 ... 0xff\n\t\t\t\t\t// value ... new value. Can be 0 ... 0xffffffff\n\t\t\t\t\t// size ... 0 for auto or 1, 2, 4 (Byte)\n\t\t\t\t\tfunction setConfig(instId, parameter, value, size) {\n\t\t\t\t\t\tvar parameter = Number.isInteger(parseInt(parameter)) ? parseInt(parameter) : null,\n\t\t\t\t\t\t\tvalue = Number.isInteger(parseInt(value)) ? parseInt(value) : null,\n\t\t\t\t\t\t\tsize = parseInt(size) || null;\n\n\t\t\t\t\t\tif (instId === endpointId && parameter !== null && !!value !== null && size !== null) {\n\t\t\t\t\t\t\t// set config after inclusion only and if it doesn't exist or isn't equal\n\t\t\t\t\t\t\tif (clusterId === 112 && deviceCC && c.data.lastIncludedDevice.value === nodeId && (!deviceCC.data[parameter] || (deviceCC.data[parameter] && deviceCC.data[parameter].val.value !== value))) {\n\t\t\t\t\t\t\t\tdeviceCC.Set(parameter, value, size);\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'CHANGE CONFIGURATION OF #' + nodeId, '###############################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change configuration of endpoint ' + instId + ':');\n\t\t\t\t\t\t\t\tconsole.log('###', 'parameter:', parameter);\n\t\t\t\t\t\t\t\tconsole.log('###', 'value:', value);\n\t\t\t\t\t\t\t\tconsole.log('###', 'size:', size);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change CC entries by entering (runs once after inclusion):\n\t\t\t\t\t// instId ... endpoint ID\n\t\t\t\t\t// cluster ... Cluster Class ID\n\t\t\t\t\t// dataType ... data type object that should be changed -e.g. security, version, interviewDone\n\t\t\t\t\t// key ... of this data type object\n\t\t\t\t\t// value ... new value\n\t\t\t\t\tfunction setCCData(instId, cluster, dataType, key, value) {\n\t\t\t\t\t\tvar cluster = parseInt(cluster, 10);\n\n\t\t\t\t\t\tif (clusterId === cluster &&\n\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster] &&\n\t\t\t\t\t\t\tc.data.lastIncludedDevice.value === nodeId) {\n\n\t\t\t\t\t\t\t// set value\n\t\t\t\t\t\t\tif (typeof value !== 'undefined' &&\n\t\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster].data[dataType] &&\n\t\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster].data[dataType][key] !== value) {\n\n\t\t\t\t\t\t\t\tdeviceEndPoints[instId].clusters[cluster].data[dataType][key] = value;\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'SET COMMANDCLASS DATA OF:', devId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change CC entry of endpoint ' + instId + ':');\n\t\t\t\t\t\t\t\tconsole.log('###', 'CC:', cluster);\n\t\t\t\t\t\t\t\tconsole.log('###', 'data type object that has changed:', dataType);\n\t\t\t\t\t\t\t\tconsole.log('###', 'new value for ' + key + ':', value);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('##############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change device entries by entering (runs once after inclusion):\n\t\t\t\t\t// dataType ... data type object that should be changed -e.g. security, version, interviewDone\n\t\t\t\t\t// key ... of this data type object\n\t\t\t\t\t// value ... new value\n\t\t\t\t\tfunction setDeviceData(dataType, key, value) {\n\t\t\t\t\t\tif (c.data.lastIncludedDevice.value === nodeId) {\n\n\t\t\t\t\t\t\t// set value\n\t\t\t\t\t\t\tif (typeof value !== 'undefined' &&\n\t\t\t\t\t\t\t\tdeviceData[dataType] &&\n\t\t\t\t\t\t\t\tdeviceData[dataType][key] !== value) {\n\n\t\t\t\t\t\t\t\tdeviceData[dataType][key] = value;\n\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'SET DEVICE DATA OF:', devId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'Change Device entry:');\n\t\t\t\t\t\t\t\tconsole.log('###', 'data type object that has changed:', dataType);\n\t\t\t\t\t\t\t\tconsole.log('###', 'new value for ' + key + ':', value);\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('##############################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// change the node name (runs once after inclusion):\n\t\t\t\t\tfunction renameNode(nodeName) {\n\n\t\t\t\t\t\tif (nodeName !== deviceData.givenName.value) {\n\n\t\t\t\t\t\t\t// do something\n\t\t\t\t\t\t\tdeviceData.givenName.value = nodeName && nodeName !== '' && !!nodeName ? nodeName : deviceData.givenName.value;\n\n\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\tconsole.log('#######################', 'Apply postfix #' + nodeId, '################################');\n\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\tconsole.log('###', 'Change node name to: ', nodeName);\n\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\tconsole.log('######################################################################################');\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\t\t\t\t\t// --- END\n\t\t\t\t\t// ----------------------------------------------------------------------------\n\n\t\t\t\t\tif (postFix) {\n\t\t\t\t\t\tif (postFix.length > 0) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t// works of course only during inclusion - after restart hidden elements are visible again\n\t\t\t\t\t\t\t\tif (!!nodeId && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\tvar intDone = deviceCC.data.interviewDone.value;\n\t\t\t\t\t\t\t\t\tintDelay = Date.now() + 5 * 1000; // wait not more than 5 seconds for single interview\n\n\t\t\t\t\t\t\t\t\t// wait till interview is done\n\t\t\t\t\t\t\t\t\twhile (Date.now() < intDelay && intDone === false) {\n\t\t\t\t\t\t\t\t\t\tintDone = deviceCC.data.interviewDone.value;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif (intDone === false) {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\t// call preInteview functions from postfix.json\n\t\t\t\t\t\t\t\t\t\t\tpostFix.forEach(function(fix) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (!!fix.preInterview && fix.preInterview && fix.preInterview.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tfix.preInterview.forEach(function(func) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teval(func);\n\t\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('##############', 'INTERVIEW-HAS-FAILED-----PREFIX-HAS-FAILED:', '#' + nodeId, '#######################');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###', 'ERROR:', e.toString());\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\t\t\t\tconsole.log('######################################################################################################');\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// call postInterview functions from postfix.json\n\t\t\t\t\t\t\t\tpostFix.forEach(function(fix) {\n\t\t\t\t\t\t\t\t\tif (!!fix.postInterview && fix.postInterview && fix.postInterview.length > 0) {\n\t\t\t\t\t\t\t\t\t\tfix.postInterview.forEach(function(entry) {\n\t\t\t\t\t\t\t\t\t\t\tvar splittedEntry = entry.split(','),\n\t\t\t\t\t\t\t\t\t\t\t\tdevICC = endpointId + '-' + clusterId;\n\n\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry.length > 0) {\n\t\t\t\t\t\t\t\t\t\t\t\tswitch (splittedEntry[0]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'rename':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'hide':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'deactivate':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'icon':\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'probeType':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1 && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) / postFix type / value - fallback true for hide / deactivate\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId][splittedEntry[0]] = splittedEntry[2] ? splittedEntry[2] : true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'discreteState':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1 && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]['discreteState']) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['discreteState'] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) / postFix type / scene + keyAttribute / value - fallback undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['discreteState'][splittedEntry[2]] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcnt: splittedEntry[3] ? splittedEntry[3] : undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taction: splittedEntry[4] ? splittedEntry[4] : undefined,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: splittedEntry[5] ? splittedEntry[5] : undefined\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'noVDev':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// devId (instId-CC-sCC-eT) without creation\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].noVDev = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'renameNode':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && c.data.lastIncludedDevice.value === nodeId) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trenameNode(splittedEntry[1]);\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'emulateOff':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[2]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].emulateOff = splittedEntry[2];\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'configVDev':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t// configVDev, i, cfg#, type, func1, func2, title\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[2] && splittedEntry[3] && splittedEntry[4] && splittedEntry[5]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1] + '-112';\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]['configVDev']) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['configVDev'] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId]['configVDev'][splittedEntry[2]] = {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttype: splittedEntry[3],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tp2v: splittedEntry[4],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tv2p: splittedEntry[5],\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttitle: splittedEntry[6] || ('Config #' + splittedEntry[2])\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'tilt':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].tilt = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\tcase 'notificationStatus':\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (splittedEntry[1] && splittedEntry[1].indexOf(devICC) > -1) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvar nId = nodeId + '-' + splittedEntry[1];\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t//add devId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif (!changeVDev[nId]) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId] = {};\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tchangeVDev[nId].notificationStatus = true;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t\t\t\teval(entry);\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\t\t// console output\n\t\t\t\t\t\t\t\tconsole.log('#######################', 'PRE-OR-POSTFIX-ERROR:', '#' + nodeId, '################################');\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('###', 'ERROR:', e.toString());\n\t\t\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\t\t\tconsole.log('#################################################################################################');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar ccId = nodeId + '-' + endpointId + '-' + clusterId;\n\n\t\t\t\t\tif (!changeVDev[ccId] || (changeVDev[ccId] && !changeVDev[ccId].noVDev)) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, false, changeVDev);\n\t\t\t\t\t} else if (changeVDev[ccId] && changeVDev[ccId].noVDev) {\n\t\t\t\t\t\tvar devId = \"ZBeeVDev_\" + self.config.name + \"_\" + nodeId + '-' + ccId;\n\t\t\t\t\t\t// console output\n\t\t\t\t\t\tconsole.log('#######################', 'Apply postfix for:', devId, '################################');\n\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\tconsole.log('###', 'not created');\n\t\t\t\t\t\tconsole.log('###');\n\t\t\t\t\t\tconsole.log('########################################################################################');\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!deviceData.givenName.value || deviceData.givenName.value == '') {\n\t\t\t\t\t\t// set givenName\n\t\t\t\t\t\tdeviceData.givenName.value = givenName? givenName : self.nodeNameByType(nodeId, deviceData);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tself.parseDelClusterClass(nodeId, endpointId, clusterId);\n\t\t\t\t}\n\t\t\t}, \"value\");\n\t\t} else {\n\t\t\tself.parseDelClusterClass(nodeId, endpointId, clusterId);\n\t\t}\n\t}, this.ZWAY_DEVICE_CHANGE_TYPES[\"ClusterAdded\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"ClusterRemoved\"] | this.ZWAY_DEVICE_CHANGE_TYPES[\"EnumerateExisting\"]);\n\n\tself.dataBind(self.gateDataBinding, self.zbee, \"lastExcludedDevice\", function(type) {\n\t\tvar _id = this.value,\n\t\t\t_toRemove = self.controller.devices.filter(function(el) {\n\t\t\t\treturn el.id.indexOf(\"ZBeeVDev_\" + self.config.name + \"_\" + _id + '-') === 0;\n\t\t\t}).map(function(el) {\n\t\t\t\treturn el.id;\n\t\t\t}).concat(\n\t\t\t\tObject.keys(self.controller.vdevInfo).filter(function(__id) {\n\t\t\t\t\treturn __id.indexOf(\"ZBeeVDev_\" + self.config.name + \"_\" + _id + '-') === 0;\n\t\t\t\t})\n\t\t\t);\n\n\t\t_toRemove.forEach(function(name) {\n\t\t\tself.controller.devices.remove(name);\n\t\t\tself.controller.devices.cleanup(name);\n\t\t});\n\t}, \"\");\n};\n\nZigbee.prototype.gateDevicesStop = function() {\n\tvar self = this;\n\n\t// delete devices\n\tthis.controller.devices.map(function(el) {\n\t\treturn el.id;\n\t}).filter(function(el) {\n\t\treturn el.indexOf(\"ZBeeVDev_\" + self.config.name + \"_\") === 0;\n\t}).forEach(function(el) {\n\t\ttry {\n\t\t\tself.controller.devices.remove(el);\n\t\t} catch (e) {\n\t\t\t// do nothing - this is to prevent Stop abort to make sure we release zbee context in C\n\t\t}\n\t});\n\n\t// releasing bindings\n\ttry {\n\t\tif (this.gateDataBinding) {\n\t\t\tthis.dataUnbind(this.gateDataBinding);\n\t\t}\n\t\tif (this.zbee) {\n\t\t\tthis.zbee.unbind(this.gateBinding);\n\t\t}\n\t} catch (e) {\n\t\t// Z-Bee already gone, skip deallocation\n\t\t//this.zbee = null;\n\t}\n};\n\nZigbee.prototype.addVDevInfo = function(info, nodeId) {\n\tvar manufacturerName = \"\", modelIdentifier = \"\", swBuildId = \"\";\n\tif (this.zbee.devices[nodeId].endpoints[1] && this.zbee.devices[nodeId].endpoints[1].Basic) {\n\t\tvar basicData = this.zbee.devices[nodeId].endpoints[1].Basic.data;\n\t\tmanufacturerName = basicData.manufacturerName ? basicData.manufacturerName.value : \"\";\n\t\tmodelIdentifier = basicData.modelIdentifier ? basicData.modelIdentifier.value : \"\";\n\t\tswBuildId = basicData.swBuildId ? basicData.swBuildId.value : \"\";\n\t}\n\t_.extend(info, {\n\t\ttechnology: \"Zigbee\",\n\t\tbindingName: this.config.name,\n\t\tnodeId: nodeId,\n\t\tmanufacturer: manufacturerName,\n\t\tproduct: modelIdentifier,\n\t\tfirmware: swBuildId,\n\t\tlocation: 0,\n\t});\n}\n\nZigbee.prototype.compileTitle = function(nodeId, endpointId, title, type, addVendor) { // accepts more arguments, see code\n\tvar sortArgs = [];\n\n\t// add vendor name\n\tif (addVendor === undefined || addVendor === true) {\n\t\tif (this.zbee.devices[nodeId].endpoints[1] && this.zbee.devices[nodeId].endpoints[1].Basic) {\n\t\t\tvar vendorName = this.zbee.devices[nodeId].endpoints[1].Basic.data.manufacturerName ? this.zbee.devices[nodeId].endpoints[1].Basic.data.manufacturerName.value : \"\";\n\t\t\tif (vendorName) {\n\t\t\t\tsortArgs.push(vendorName);\n\t\t\t}\n\t\t}\n\t}\n\n\tsortArgs.push(title);\n\n\t// add probeType\n\tif (type) {\n\t\tsortArgs.push(type);\n\t}\n\n\t// add id\n\tsortArgs.push(\"(\" + nodeId + (endpointId ? \".\" + endpointId : \"\") + \")\");\n\n\treturn sortArgs.join(' ');\n};\n\nZigbee.prototype.applyPostfix = function(defaultObj, changeObj, nodeId, endpointId, title, type, addVendor) {\n\tthis.addVDevInfo(defaultObj, nodeId);\n\t\n\tdefaultObj.metrics.title = this.compileTitle(nodeId, endpointId, title, type, addVendor);\n\t\n\tif (changeObj) {\n\t\tif (changeObj.noVDev) return false;\n\t\t\n\t\tif (changeObj.probeType)\n\t\t\tdefaultObj.probeType = changeObj.probeType;\n\t\tif (changeObj.icon)\n\t\t\tdefaultObj.metrics.icon = changeObj.icon;\n\t\tif (changeObj.rename)\n\t\t\tdefaultObj.metrics.title = this.compileTitle(nodeId, endpointId, changeObj.rename, undefined, false);\n\t\tdefaultObj.visibility = changeObj.hide ? false : true;\n\t\tdefaultObj.permanently_hidden = changeObj.deactivate ? true : false;\n\t\n\t\tif (changeObj.discreteState && !_.isEmpty(changeObj.discreteState) && defaultObj.metrics.discreteStates) {\n\t\t\tdefaultObj.metrics.discreteStates = changeObj.discreteState;\n\t\t}\n\t}\n\treturn true;\n};\n\nZigbee.prototype.parseAddClusterClass = function(nodeId, endpointId, clusterId, scaleAdded, changeVDev) {\n\tnodeId = parseInt(nodeId, 10);\n\tendpointId = parseInt(endpointId, 10);\n\tclusterId = parseInt(clusterId, 10);\n\n\t// avoid errors during binding stop and device exclusion\n\tif (!this.zbee || !this.zbee.devices[nodeId]) {\n\t\treturn;\n\t}\n\n\tvar self = this,\n\t\tendpoint = this.zbee.devices[nodeId].endpoints[endpointId],\n\t\tendpointClusterClasses = Object.keys(endpoint.clusters).map(function(x) {\n\t\t\treturn parseInt(x);\n\t\t}),\n\t\tcc = endpoint.clusters[clusterId],\n\t\tsepar = \"-\",\n\t\tvDevIdPrefix = \"ZBeeVDev_\" + this.config.name + \"_\",\n\t\tvDevIdNI = nodeId + separ + endpointId,\n\t\tvDevIdC = clusterId,\n\t\tvDevId = vDevIdPrefix + vDevIdNI + separ + vDevIdC,\n\t\tchangeDevId = vDevIdNI + separ + vDevIdC,\n\t\tdefaults;\n\t// vDev is not in this scope, but in {} scope for each type of device to allow reuse it without closures\n\n\ttry {\n\t\tif (!cc) {\n\t\t\treturn; // do not handle destroyed Cluster Classes\n\t\t}\n\n\t\tif (!cc.data.inDirection.value) {\n\t\t\treturn; // do not handle unsupported Cluster Classes\n\t\t}\n\n\t\tif (this.CC[\"OnOff\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar icon = \"switch\";\n\t\t\tvar probeType = \"switch\";\n\n\t\t\t//TODO How to guess the icon type?\n\t\t\t/*\n\t\t\tswitch (this.zbee.devices[nodeId].data.specificType.value) {\n\t\t\t\tcase 0x01:\n\t\t\t\t\tprobeType = \"power_switch_binary\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x03:\n\t\t\t\t\tprobeType = \"scene_switch_binary\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x04:\n\t\t\t\t\tprobeType = \"power_strip\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x05:\n\t\t\t\t\ticon = \"siren\";\n\t\t\t\t\tprobeType = \"siren\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x06:\n\t\t\t\t\ticon = \"valve\";\n\t\t\t\t\tprobeType = \"valve\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tprobeType = \"switch\";\n\t\t\t\t\tbreak;\n\t\t\t};\n\t\t\t*/\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Switch')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\tcc.Set(true);\n\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\tcc.Set(false);\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', this.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tthis.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"onOff\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"LevelControl\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\t\t\tvar icon = 'multilevel';\n\t\t\tvar title = 'Dimmer';\n\t\t\tvar probeType = 'multilevel';\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, title)) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Blinds\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = Math.round(parseInt(args.level, 10) * 255 / 99, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal > 255) {\n\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tcc.StepOnOff(0, 10);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tcc.StepOnOff(1, 10);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"stop\" === command) { // Commands for Blinds\n\t\t\t\t\t\tcc.StopOnOff();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\tcc.MoveOnOff(0);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\tcc.MoveOnOff(1);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.MoveToLevelOnOff(newVal, args.duration);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.MoveToLevelOnOff(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"currentLevel\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", Math.round(this.value * 99 / 255, 10));\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"ColorControl\"] === clusterId) {\n\t\t\tvar\n\t\t\t\t// TODO COLOR_SOFT_WHITE = 0,\n\t\t\t\t// TODO COLOR_COLD_WHITE = 1,\n\t\t\t\tCOLOR_RED = 2,\n\t\t\t\tCOLOR_GREEN = 3,\n\t\t\t\tCOLOR_BLUE = 4;\n\n\t\t\tvar ccLevelControl = endpoint.clusters[this.CC[\"LevelControl\"]];\n\t\t\tif (!ccLevelControl) return;\n\n\t\t\tif (!self.controller.devices.get(vDevId + separ + \"rgb\")) {\n\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: \"switchRGBW\",\n\t\t\t\t\tprobeType: 'switchColor_rgb',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\tcolor: HSVtoRGB(\n\t\t\t\t\t\t\tcc.data.currentHue.value,\n\t\t\t\t\t\t\tcc.data.currentSaturation.value,\n\t\t\t\t\t\t\tccLevelControl.data.currentLevel.value\n\t\t\t\t\t\t),\n\t\t\t\t\t\tlevel: 'off',\n\t\t\t\t\t\toldColor: {},\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Color')) return;\n\n\t\t\t\tvar vDev_rgb = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId + separ + \"rgb\",\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\tvar color = {\n\t\t\t\t\t\t\t\tr: 0,\n\t\t\t\t\t\t\t\tg: 0,\n\t\t\t\t\t\t\t\tb: 0\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\toldColor = vDev_rgb.get('metrics:oldColor');\n\t\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\t\tif (!_.isEmpty(oldColor)) {\n\t\t\t\t\t\t\t\tcolor = oldColor;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcolor.r = color.g = color.b = 255;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (command === \"off\") {\n\t\t\t\t\t\t\tcolor.r = color.g = color.b = 0;\n\t\t\t\t\t\t} else if (command === \"exact\") {\n\t\t\t\t\t\t\tcolor.r = parseInt(args.red, 10);\n\t\t\t\t\t\t\tcolor.g = parseInt(args.green, 10);\n\t\t\t\t\t\t\tcolor.b = parseInt(args.blue, 10);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:oldColor\", color);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tvar hsv = RGBtoHSV(color.r, color.g, color.b);\n\t\t\t\t\t\t\n\t\t\t\t\t\tconsole.logJS(hsv);\n\t\t\t\t\t\tcc.MoveToHueAndSaturation(hsv.h, hsv.s, 0);\n\t\t\t\t\t\tccLevelControl.MoveToLevel(hsv.v);\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: this.id\n\t\t\t\t});\n\n\t\t\t\tfunction HSVtoRGB(h, s, v) {\n\t\t\t\t\tvar r, g, b, i, f, p, q, t;\n\t\t\t\t\t\n\t\t\t\t\th = h / 255.0;\n\t\t\t\t\ts = s / 255.0;\n\t\t\t\t\tv = v / 255.0;\n\t\t\t\t\t\n\t\t\t\t\ti = Math.floor(h * 6);\n\t\t\t\t\tf = h * 6 - i;\n\t\t\t\t\tp = v * (1 - s);\n\t\t\t\t\tq = v * (1 - f * s);\n\t\t\t\t\tt = v * (1 - (1 - f) * s);\n\t\t\t\t\t\n\t\t\t\t\tswitch (i % 6) {\n\t\t\t\t\t\tcase 0: r = v, g = t, b = p; break;\n\t\t\t\t\t\tcase 1: r = q, g = v, b = p; break;\n\t\t\t\t\t\tcase 2: r = p, g = v, b = t; break;\n\t\t\t\t\t\tcase 3: r = p, g = q, b = v; break;\n\t\t\t\t\t\tcase 4: r = t, g = p, b = v; break;\n\t\t\t\t\t\tcase 5: r = v, g = p, b = q; break;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn {\n\t\t\t\t\t\tr: Math.round(r * 255),\n\t\t\t\t\t\tg: Math.round(g * 255),\n\t\t\t\t\t\tb: Math.round(b * 255)\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfunction RGBtoHSV(r, g, b) {\n\t\t\t\t\tvar max = Math.max(r, g, b), min = Math.min(r, g, b),\n\t\t\t\t\t\td = max - min,\n\t\t\t\t\t\th,\n\t\t\t\t\t\ts = (max === 0 ? 0 : d / max),\n\t\t\t\t\t\tv = max / 255;\n\t\t\t\t\t\n\t\t\t\t\tswitch (max) {\n\t\t\t\t\t\tcase min: h = 0; break;\n\t\t\t\t\t\tcase r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;\n\t\t\t\t\t\tcase g: h = (b - r) + d * 2; h /= 6 * d; break;\n\t\t\t\t\t\tcase b: h = (r - g) + d * 4; h /= 6 * d; break;\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\treturn {\n\t\t\t\t\t\th: Math.round(h * 255),\n\t\t\t\t\t\ts: Math.round(s * 255),\n\t\t\t\t\t\tv: Math.round(v * 255)\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tfunction handleColor(type, arg) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar isOn = ccLevelControl.data.currentLevel.value > 0;\n\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + 'rgb');\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvar color = HSVtoRGB(\n\t\t\t\t\t\t\t\tcc.data.currentHue.value,\n\t\t\t\t\t\t\t\tcc.data.currentSaturation.value,\n\t\t\t\t\t\t\t\tccLevelControl.data.currentLevel.value\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:color\", color);\n\t\t\t\t\t\t\tvDev_rgb.set(\"metrics:level\", isOn ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\tconsole.log(e.toString());\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (vDev_rgb) {\n\t\t\t\t\tvDev_rgb.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"currentHue\", handleColor, \"value\");\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"currentSaturation\", handleColor, \"value\");\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, this.CC[\"LevelControl\"], \"currentLevel\", handleColor, \"value\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"WindowCovering\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\t\t\t// Lift\n\t\t\t\n\t\t\tvar icon = 'blinds';\n\t\t\tvar title = 'Blind';\n\t\t\tprobeType = 'motor';\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, title)) return;\n\n\t\t\tvar vDevLift = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Blinds\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"stop\" === command) { // Commands for Blinds\n\t\t\t\t\t\tcc.Stop();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\tcc.UpOpen();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\tcc.DownClose();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.GoToLiftPercentage(newVal); // no exactSmooth for WindowCovering\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.GoToLiftPercentage(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDevLift) {\n\t\t\t\tvDevLift.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"currentPositionLiftPercentage\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDevLift.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t\t\n\t\t\t// Tilt\n\t\t\t\n\t\t\tvar icon = 'blinds';\n\t\t\tvar title = 'Tilt';\n\t\t\tprobeType = 'motor';\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\tprobeType: probeType,\n\t\t\t\tmetrics: {\n\t\t\t\t\ticon: icon,\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId + separ + \"tilt\"], nodeId, endpointId, title)) return;\n\n\t\t\tvar vDevTilt = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId + separ + \"tilt\",\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command, args) {\n\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t// up, down for Tilt\n\t\t\t\t\tif (\"on\" === command || \"up\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"off\" === command || \"down\" === command) {\n\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t} else if (\"max\" === command || \"upMax\" === command) {\n\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t} else if (\"exact\" === command || \"exactSmooth\" === command) {\n\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t} else if (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (newVal > 100) {\n\t\t\t\t\t\t\tnewVal = 100;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (\"stop\" === command) { // Ignore Blind Commands for Tilt\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startUp\" === command) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"startDown\" === command) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\tif (\"exactSmooth\" === command)\n\t\t\t\t\t\t\tcc.GoToTiltPercentage(newVal); // no exactSmooth for WindowCovering\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcc.GoToTiltPercentage(newVal);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDevTilt) {\n\t\t\t\tvDevTilt.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"currentPositionTiltPercentage\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDevTilt.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"Metering\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorMultilevel',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'meter',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\t[\"instantaneousDemand\", \"metric\"].forEach(function(dhName) {\n\n\t\t\t\t\tif (cc.data[dhName] && !self.controller.devices.get(vDevId + separ + dhName)) {\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + dhName;\n\t\t\t\t\t\t\n\t\t\t\t\t\tswitch (dhName) {\n\t\t\t\t\t\t\tcase \"instantaneousDemand\":\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_kilowatt_hour';\n\t\t\t\t\t\t\t\tdefaults.metrics.probeTitle = \"Meter\";\n\t\t\t\t\t\t\t\tdefaults.metrics.scaleTitle = \"W\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\tcase \"metric\":\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_watt';\n\t\t\t\t\t\t\t\tdefaults.metrics.probeTitle = \"Meter\";\n\t\t\t\t\t\t\t\tdefaults.metrics.scaleTitle = \"kWh\";\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t/*\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_kilovolt_ampere_hour';\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_pulse_count';\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_voltage';\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_ampere';\n\t\t\t\t\t\t\t\tdefaults.probeType = 'meterElectric_power_factor';\n\t\t\t\t\t\t\t\t*/\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Meter', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + dhName,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, dhName, function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + dhName);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} /* else if (this.CC[\"SoundSwitch\"] === clusterId) {\n\t\t\tif (cc.data) {\n\t\t\t\t// tones\n\t\t\t\tdefaults = {\n\t\t\t\t\tdeviceType: 'toggleButton',\n\t\t\t\t\tmetrics: {\n\t\t\t\t\t\ticon: 'scene',\n\t\t\t\t\t\tlevel: 'on',\n\t\t\t\t\t\ttitle: '',\n\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\t\n\t\t\t\tfor(var toneId = 0; toneId <= cc.data.tonesNumber.value; toneId++) {\n\t\t\t\t\t(function(toneId) {\n\t\t\t\t\t\tif ((toneId == 0 || cc.data[toneId]) && !self.controller.devices.get(vDevId + separ + toneId)) {\n\t\t\t\t\t\t\tvar cVDId = changeDevId + separ + toneId;\n\n\t\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, toneId ? cc.data[toneId].toneName.value : 'Mute')) return;\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\t\tdeviceId: vDevId + separ + toneId,\n\t\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\t\tif (command === \"on\") {\n\t\t\t\t\t\t\t\t\t\tcc.TonePlaySet(toneId);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, toneId + \".toneName\", function(type) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + toneId);\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"tonesNumber\", function(type) {\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + \"0\");\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t})(toneId);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (!this.controller.devices.get(vDevId)) {\n\t\t\t\t\t// volume\n\t\t\t\t\tdefaults = {\n\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\tprobeType: 'volume',\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: 'multilevel',\n\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Volume')) return;\n\n\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\tvar newVal = this.get('metrics:level');\n\t\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t} else if (\"min\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 10;\n\t\t\t\t\t\t\t} else if (\"max\" === command) {\n\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t} else if (\"increase\" === command) {\n\t\t\t\t\t\t\t\tnewVal = newVal + 10;\n\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (newVal > 99) {\n\t\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"decrease\" === command) {\n\t\t\t\t\t\t\t\tnewVal = newVal - 10;\n\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (0 !== newVal % 10) {\n\t\t\t\t\t\t\t\t\tnewVal = Math.round(newVal / 10) * 10;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"exact\" === command) {\n\t\t\t\t\t\t\t\tnewVal = parseInt(args.level, 10);\n\t\t\t\t\t\t\t\tif (newVal < 0) {\n\t\t\t\t\t\t\t\t\tnewVal = 0;\n\t\t\t\t\t\t\t\t} else if (newVal === 255) {\n\t\t\t\t\t\t\t\t\tnewVal = 255;\n\t\t\t\t\t\t\t\t} else if (newVal > 99) {\n\t\t\t\t\t\t\t\t\tif (newVal === 100) {\n\t\t\t\t\t\t\t\t\t\tnewVal = 99;\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tnewVal = null;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if (\"update\" === command) {\n\t\t\t\t\t\t\t\tcc.ConfigurationGet();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (0 === newVal || !!newVal) {\n\t\t\t\t\t\t\t\tcc.ConfigurationSet(0, newVal);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"defaultVolume\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"SensorBinary\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\ticon: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(vDevId + separ + sensorTypeId)) {\n\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\t\t\t\t\t\t\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[sensorTypeId].sensorTypeString.value;\n\t\t\t\t\t\t// aivs // Motion icon for Sensor Binary by default\n\t\t\t\t\t\tdefaults.metrics.icon = \"motion\";\n\t\t\t\t\t\tdefaults.probeType = \"general_purpose\";\n\n\t\t\t\t\t\tif (sensorTypeId === 2) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"smoke\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 3 || sensorTypeId === 4) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 6) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"flood\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 7) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"cooling\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 8) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"tamper\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t} else if (sensorTypeId === 10) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"door\";\n\t\t\t\t\t\t\tdefaults.probeType = \"door-window\";\n\t\t\t\t\t\t} else if (sensorTypeId === 12) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"motion\";\n\t\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + sensorTypeId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tif (changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\tvDev.__emulateOff_timeout = parseInt(changeVDev[cVDId].emulateOff, 10);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, sensorTypeId + \".level\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId);\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\t\tif (vDev.__emulateOff_timeout) {\n\t\t\t\t\t\t\t\t\t\t\t\tif (this.value) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tif (vDev.get(\"metrics:level\") !== \"on\" || !vDev.__emulateOff_timer) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"on\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer && clearTimeout(vDev.__emulateOff_timer);\n\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", \"off\");\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tvDev.__emulateOff_timer = 0;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}, vDev.__emulateOff_timeout);\n\t\t\t\t\t\t\t\t\t\t\t\t} // off from the sensor is ignored\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\n\t\t\t\t\t\t\tif (changeVDev[cVDId] && changeVDev[cVDId].emulateOff) {\n\t\t\t\t\t\t\t\t// on start we need to kick the timer\n\t\t\t\t\t\t\t\tif (vDev.get(\"metrics:level\") === \"on\") {\n\t\t\t\t\t\t\t\t\tself.zbee.devices[nodeId].endpoints[endpointId].clusters[clusterId].data[sensorTypeId].level.value = true;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t} else if (this.CC[\"SensorMultilevel\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: '',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: '',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (cc.data) {\n\t\t\t\tObject.keys(cc.data).forEach(function(sensorTypeId) {\n\n\t\t\t\t\tsensorTypeId = parseInt(sensorTypeId, 10);\n\t\t\t\t\tif (!isNaN(sensorTypeId) && !self.controller.devices.get(vDevId + separ + sensorTypeId)) {\n\n\t\t\t\t\t\tvar cVDId = changeDevId + separ + sensorTypeId;\n\n\t\t\t\t\t\tdefaults.metrics.probeTitle = cc.data[sensorTypeId].sensorTypeString.value;\n\t\t\t\t\t\tdefaults.metrics.scaleTitle = cc.data[sensorTypeId].scaleString.value;\n\n\t\t\t\t\t\tif (sensorTypeId === 1) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"temperature\";\n\t\t\t\t\t\t} else if (sensorTypeId === 3) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"luminosity\";\n\t\t\t\t\t\t} else if (sensorTypeId === 4 || sensorTypeId === 15 || sensorTypeId === 16) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"energy\";\n\t\t\t\t\t\t} else if (sensorTypeId === 5) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"humidity\";\n\t\t\t\t\t\t} else if (sensorTypeId === 9) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"barometer\";\n\t\t\t\t\t\t} else if (sensorTypeId === 12) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"rain\";\n\t\t\t\t\t\t} else if (sensorTypeId === 17) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co2\";\n\t\t\t\t\t\t} else if (sensorTypeId === 25) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"seismic\";\n\t\t\t\t\t\t} else if (sensorTypeId === 27) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"ultraviolet\";\n\t\t\t\t\t\t} else if (sensorTypeId === 40) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"co\";\n\t\t\t\t\t\t} else if (sensorTypeId === 52) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_x\";\n\t\t\t\t\t\t} else if (sensorTypeId === 53) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_y\";\n\t\t\t\t\t\t} else if (sensorTypeId === 54) {\n\t\t\t\t\t\t\tdefaults.metrics.icon = \"acceleration_z\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tdefaults.probeType = defaults.metrics.icon;\n\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevId + separ + sensorTypeId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, sensorTypeId + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId + separ + sensorTypeId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!scaleAdded) {\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"\", function(type) {\n\t\t\t\t\tif (type !== self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\tself.parseAddClusterClass(nodeId, endpointId, clusterId, true, changeVDev);\n\t\t\t\t\t}\n\t\t\t\t}, \"child\");\n\t\t\t}\n\t\t else if (this.CC[\"MeterPulse\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorMultilevel',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'meterElectric_pulse_count',\n\t\t\t\t\tscaleTitle: '',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'meter',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.controller.devices.get(vDevId)) {\n\t\t\t\tvar cVDId = changeDevId;\n\t\t\t\t\n\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, 'Meter Pulse')) return;\n\n\t\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId,\n\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\n\t\t\t\tif (vDev) {\n\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"val\", function(type) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}, \"value\");\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (this.CC[\"Battery\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'battery',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: 'Battery',\n\t\t\t\t\tscaleTitle: '%',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'battery',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Battery')) return;\n\n\t\t\tvar vDev = this.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"last\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? 0 : this.value);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}*/ else if (this.CC[\"DoorLock\"] === clusterId) {\n\t\t\tdefaults_lock = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tdefaults_door = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\ttitle: 'Door State',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tvar lockType = cc.data.lockType.value;\n\n\t\t\tswitch (lockType) {\n\t\t\t\tcase 0x00:\n\t\t\t\t\ttitle = \"Dead bolt\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x01:\n\t\t\t\t\ttitle = \"Magnetic\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x02:\n\t\t\t\t\ttitle = \"Other\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x03:\n\t\t\t\t\ttitle = \"Mortise\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x04:\n\t\t\t\t\ttitle = \"Rim\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x05:\n\t\t\t\t\ttitle = \"Latch Bolt\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x06:\n\t\t\t\t\ttitle = \"Cylindrical Lock\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x07:\n\t\t\t\t\ttitle = \"Tubular Lock\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x08:\n\t\t\t\t\ttitle = \"Interconnected\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x09:\n\t\t\t\t\ttitle = \"Dead Latch\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x0A:\n\t\t\t\t\ttitle = \"Door Furniture\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\ttitle = \"Door Lock\"\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (!this.applyPostfix(defaults_lock, changeVDev[changeDevId], nodeId, endpointId, 'Door Lock', title)) return;\n\t\t\tif (!this.applyPostfix(defaults_door, changeVDev[changeDevId], nodeId, endpointId, 'Door Lock')) return;\n\n\t\t\tif (cc.data.lockState) {\n\t\t\t\tvar vDev_lock = this.controller.devices.create({\n\t\t\t\t\tdeviceId: vDevId + separ + \"lock\",\n\t\t\t\t\tdefaults: defaults_lock,\n\t\t\t\t\toverlay: {},\n\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\t\tcc.LockDoor(\"\");\n\t\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\t\tcc.UnlockDoor(\"\");\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tmoduleId: self.id\n\t\t\t\t});\n\t\t\t\t\n\t\t\t\tif (cc.data.doorState) {\n\t\t\t\t\tvar vDev_door = this.controller.devices.create({\n\t\t\t\t\t\tdeviceId: vDevId + separ + \"door\",\n\t\t\t\t\t\tdefaults: defaults_door,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\t\t\tcc.LockDoor(\"\");\n\t\t\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\t\t\tcc.UnlockDoor(\"\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (vDev_door && vDev_lock) {\n\t\t\t\t\t\tvDev_door.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"doorState\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tswitch (this.value) {\n\t\t\t\t\t\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\t\t\t\t\t\tvDev_door.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tvDev_door.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  ERROR JAMMED)\n\t\t\t\t\t\t\t\t\t\t\t//vDev.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x03:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  ERROR FORCED OPENED)\n\t\t\t\t\t\t\t\t\t\t\tvDev_door.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x04:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  ERROR UNSPECIFIED)\n\t\t\t\t\t\t\t\t\t\t\t//vDev.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\t\t\t\t\t\t// TODO(Notifing  UNDEFINED)\n\t\t\t\t\t\t\t\t\t\t\t//vDev.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\n\t\t\t\t\t\t\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"lockState\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tswitch (this.value) {\n\t\t\t\t\t\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Not fully locked\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Undefined lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t// TODO self.addNotification(\"error\", \"Unknown lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tif (vDev_lock) {\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"lockState\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tswitch (this.value) {\n\t\t\t\t\t\t\t\t\t\tcase 0x00:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Not fully locked\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x01:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"open\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tcase 0x02:\n\t\t\t\t\t\t\t\t\t\t\tvDev_lock.set(\"metrics:level\", \"close\");\n\t\t\t\t\t\t\t\t\t\tcase 0xFF:\n\t\t\t\t\t\t\t\t\t\t\t//TODO self.addNotification(\"error\", \"Undefined lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t\t\t\t// TODO self.addNotification(\"error\", \"Unknown lock state\", \"module\");\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} /*else if (this.CC[\"BarrierOperator\"] === clusterId && !self.controller.devices.get(vDevId)) {\n\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'doorlock',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: 'lock',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Garage Door')) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (\"open\" === command) {\n\t\t\t\t\t\tcc.Set(255);\n\t\t\t\t\t} else if (\"close\" === command) {\n\t\t\t\t\t\tcc.Set(0);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"state\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value === 255 ? \"open\" : \"close\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t} else if (this.CC[\"ThermostatMode\"] === clusterId || this.CC[\"ThermostatSetPoint\"] === clusterId) {\n\t\t\tvar\n\t\t\t\twithMode = in_array(endpointClusterClasses, this.CC[\"ThermostatMode\"]) && endpoint.ThermostatMode.data.supported.value,\n\t\t\t\twithTemp = in_array(endpointClusterClasses, this.CC[\"ThermostatSetPoint\"]) && endpoint.ThermostatSetPoint.data.supported.value,\n\t\t\t\tdeviceNamePrefix = \"ZBeeVDev_\" + this.config.name + \"_\" + nodeId + separ + endpointId + separ;\n\n\t\t\tif ((withMode && !endpoint.ThermostatMode.data.interviewDone.value) || (withTemp && !endpoint.ThermostatSetPoint.data.interviewDone.value)) {\n\t\t\t\treturn; // skip not finished interview\n\t\t\t}\n\n\t\t\tvar MODE_OFF = 0,\n\t\t\t\tMODE_HEAT = 1,\n\t\t\t\tMODE_COOL = 2;\n\n\t\t\t// Handle Mode with proper changeVDev\n\t\t\tif (withMode && !self.controller.devices.get(deviceNamePrefix + this.CC[\"ThermostatMode\"])) {\n\t\t\t\tvar withModeOff = !!endpoint.ThermostatMode.data[MODE_OFF],\n\t\t\t\t\twithModeHeat = !!endpoint.ThermostatMode.data[MODE_HEAT],\n\t\t\t\t\twithModeCool = !!endpoint.ThermostatMode.data[MODE_COOL];\n\n\t\t\t\tif (withModeOff && (withModeHeat || withModeCool)) {\n\n\t\t\t\t\tdefaults = {\n\t\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\t\tprobeType: 'thermostat_mode',\n\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t\t\n\t\t\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Thermostat operation')) return;\n\n\t\t\t\t\tvar m_vDev = this.controller.devices.create({\n\t\t\t\t\t\tdeviceId: deviceNamePrefix + this.CC[\"ThermostatMode\"],\n\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\thandler: function(command) {\n\t\t\t\t\t\t\tif (\"on\" === command) {\n\t\t\t\t\t\t\t\tvar lastMode = withModeHeat ? MODE_HEAT : MODE_COOL;\n\n\t\t\t\t\t\t\t\t// modes are not always same in ThermostatSetPoint and in ThermostatMode, but here they are same\n\t\t\t\t\t\t\t\tif (withModeHeat && withModeCool && endpoint.ThermostatSetPoint && endpoint.ThermostatSetPoint.data[MODE_HEAT] && endpoint.ThermostatSetPoint.data[MODE_COOL]) {\n\t\t\t\t\t\t\t\t\tlastMode = endpoint.ThermostatSetPoint.data[MODE_HEAT].setVal.updateTime > endpoint.ThermostatSetPoint.data[MODE_COOL].setVal.updateTime ? MODE_HEAT : MODE_COOL;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tendpoint.ThermostatMode.Set(lastMode);\n\t\t\t\t\t\t\t} else if (\"off\" === command) {\n\t\t\t\t\t\t\t\tendpoint.ThermostatMode.Set(MODE_OFF);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t});\n\n\t\t\t\t\tif (m_vDev) {\n\t\t\t\t\t\tm_vDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, this.CC[\"ThermostatMode\"], \"mode\", function(type) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tif (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\tm_vDev.set(\"metrics:level\", this.value != MODE_OFF ? \"on\" : \"off\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle Set Point with proper changeVDev\n\t\t\tif (withTemp) {\n\t\t\t\tvar withTempHeat = endpoint.ThermostatSetPoint.data[MODE_HEAT],\n\t\t\t\t\twithTempCool = endpoint.ThermostatSetPoint.data[MODE_COOL],\n\t\t\t\t\tmodes = [];\n\n\t\t\t\twithTempHeat && modes.push(MODE_HEAT);\n\t\t\t\twithTempCool && modes.push(MODE_COOL);\n\n\t\t\t\tvar t_vDev = [];\n\t\t\t\tmodes.forEach(function(mode) {\n\t\t\t\t\tvar cVDId = changeDevId + separ + mode;\n\t\t\t\t\t\n\t\t\t\t\tvar DH = endpoint.ThermostatSetPoint.data[mode],\n\t\t\t\t\t\t_vDevId = deviceNamePrefix + self.CC[\"ThermostatSetPoint\"] + \"-\" + mode;\n\n\t\t\t\t\tif (!self.controller.devices.get(_vDevId)) {\n\n\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\tdeviceType: \"thermostat\",\n\t\t\t\t\t\t\tprobeType: 'thermostat_set_point',\n\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\tscaleTitle: DH.scaleString.value,\n\t\t\t\t\t\t\t\tlevel: DH.val.value,\n\t\t\t\t\t\t\t\tmin: DH.min && DH.min.value ? DH.min.value : (DH.scale.value === 0 ? 5 : 41),\n\t\t\t\t\t\t\t\tmax: DH.max && DH.max.value ? DH.max.value : (DH.scale.value === 0 ? 40 : 104),\n\t\t\t\t\t\t\t\ticon: 'thermostat',\n\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!self.applyPostfix(defaults, changeVDev[cVDId], nodeId, endpointId, \"Thermostat \" + (mode === MODE_HEAT ? \"Heat\" : \"Cool\"))) return;\n\n\t\t\t\t\t\tt_vDev[mode] = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: _vDevId,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t\t// first set the setpoint temperature and then apply the mode\n\t\t\t\t\t\t\t\tif (command === \"exact\") {\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatSetPoint.Set(mode, args.level);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (command === \"on\" || command === \"exact\") {\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatMode && endpoint.ThermostatMode.data.supported.value && endpoint.ThermostatMode.Set(mode == MODE_HEAT ? MODE_HEAT : MODE_COOL); // modes are not always same in ThermostatSetPoint and in ThermostatMode, but here they are same\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatSetPoint.Get(mode);\n\t\t\t\t\t\t\t\t\tendpoint.ThermostatMode && endpoint.ThermostatMode.data.supported.value && endpoint.ThermostatMode.Get();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (t_vDev[mode]) {\n\t\t\t\t\t\t\tt_vDev[mode].set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, self.CC[\"ThermostatSetPoint\"], mode + \".setVal\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tdelete t_vDev[mode];\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(_vDevId);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tt_vDev[mode].set(\"metrics:level\", this.value);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t*/\n\t\telse if (this.CC[\"TemperatureMeasurement\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: \"temperature\",\n\t\t\t\t\tscaleTitle: 'C',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: \"temperature\",\n\t\t\t\t\ttitle: 'Temperature',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!self.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"measuredValue\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value / 100);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t\t\n\t\t}\n\t\telse if (this.CC[\"PressureMeasurement\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: \"barometer\",\n\t\t\t\t\tscaleTitle: 'kPa',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: \"barometer\",\n\t\t\t\t\ttitle: 'Barometer',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!self.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"measuredValue\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value / 10);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\telse if (this.CC[\"RelativeHumidityMeasurement\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: \"sensorMultilevel\",\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tprobeTitle: \"humidity\",\n\t\t\t\t\tscaleTitle: '%',\n\t\t\t\t\tlevel: '',\n\t\t\t\t\ticon: \"humidity\",\n\t\t\t\t\ttitle: 'Relative Humidity',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tif (!self.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Sensor', defaults.metrics.probeTitle)) return;\n\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get(sensorTypeId);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\n\t\t\tif (vDev) {\n\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"measuredValue\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\",  this.value / 100);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\telse if (this.CC[\"OccupancySensing\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ticon: 'motion',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\n\t\t\tvar title = \"Occupancy\";\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Alarm', title)) return;\n\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\t//TODO isFailed a_vDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"occupancy\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", this.value ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\telse if (this.CC[\"IasZone\"] === clusterId) {\n\t\t\tdefaults = {\n\t\t\t\tdeviceType: 'sensorBinary',\n\t\t\t\tprobeType: '',\n\t\t\t\tmetrics: {\n\t\t\t\t\tlevel: 'off',\n\t\t\t\t\ttitle: '',\n\t\t\t\t\tisFailed: false\n\t\t\t\t}\n\t\t\t};\n\t\t\t\n\t\t\tvar zoneType = cc.data.zoneType.value;\n\t\t\tvar zoneStatus = cc.data.zoneStatus.value;\n\t\t\tvar title = \"\";\n\t\t\t\n\t\t\tswitch (zoneType) {\n\t\t\t\tcase 0x0000:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\tdefaults.probeType = 'general_purpose';\n\t\t\t\t\ttitle = \"\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x000d:\n\t\t\t\t\tdefaults.metrics.icon = 'motion';\n\t\t\t\t\tdefaults.probeType = 'motion';\n\t\t\t\t\ttitle = \"Motion\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x0028:\n\t\t\t\t\tdefaults.metrics.icon = 'smoke';\n\t\t\t\t\tdefaults.probeType = 'smoke';\n\t\t\t\t\ttitle = \"Smoke\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002b:\n\t\t\t\t\tdefaults.metrics.icon = 'co';\n\t\t\t\t\tdefaults.probeType = 'co';\n\t\t\t\t\ttitle = \"CO\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002a:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm_flood';\n\t\t\t\t\tdefaults.probeType = 'flood';\n\t\t\t\t\ttitle = \"Flood\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x0015:\n\t\t\t\t\tdefaults.metrics.icon = 'door';\n\t\t\t\t\tdefaults.probeType = 'door';\n\t\t\t\t\ttitle = \"Door\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002d:\n\t\t\t\tcase 0x0226:\n\t\t\t\t\tdefaults.metrics.icon = 'burglar';\n\t\t\t\t\tdefaults.probeType = 'burglar';\n\t\t\t\t\ttitle = \"Burglar\";\n\t\t\t\t\tbreak;\n\t\t\t\tcase 0x002c:\n\t\t\t\tcase 0x0225:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\tdefaults.probeType = 'emergency';\n\t\t\t\t\ttitle = \"Emergency\";\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tdefaults.metrics.icon = 'alarm';\n\t\t\t\t\tdefaults.probeType = 'general_purpose';\n\t\t\t\t\ttitle = \"\";\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\t\n\t\t\tif (!this.applyPostfix(defaults, changeVDev[changeDevId], nodeId, endpointId, 'Alarm', title)) return;\n\n\t\t\t\n\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\tdeviceId: vDevId,\n\t\t\t\tdefaults: defaults,\n\t\t\t\toverlay: {},\n\t\t\t\thandler: function(command) {\n\t\t\t\t\tif (command === \"update\") {\n\t\t\t\t\t\tcc.Get();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tmoduleId: self.id\n\t\t\t});\n\t\t\t\n\t\t\tif (vDev) {\n\t\t\t\t//TODO isFailed a_vDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, \"zoneStatus\", function(type) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\tself.controller.devices.remove(vDevId);\n\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\tvDev.set(\"metrics:level\", (this.value & 0x01) ? \"on\" : \"off\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch (e) {}\n\t\t\t\t}, \"value\");\n\t\t\t}\n\t\t}\n\t\t/*\n\t\telse if (this.CC[\"Configuration\"] === clusterId) {\n\t\t\tif (changeVDev[changeDevId]) {\n\t\t\t\tObject.keys(changeVDev[changeDevId]['configVDev']).forEach(function(param) {\n\t\t\t\t\tvar vDevIdParam = vDevId + '-' + param,\n\t\t\t\t\tvDevConfig = changeVDev[changeDevId]['configVDev'][param];\n\t\t\t\t\t\n\t\t\t\t\tif (!self.controller.devices.get(vDevIdParam)) {\n\t\t\t\t\t\tvar icon, probeType;\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (vDevConfig.type == \"switchBinary\") {\n\t\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\t\tdeviceType: \"switchBinary\",\n\t\t\t\t\t\t\t\tprobeType: \"switch\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: vDevConfig.title,\n\t\t\t\t\t\t\t\t\ticon: \"switch\",\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (vDevConfig.type == \"switchMultilevel\") {\n\t\t\t\t\t\t\tdefaults = {\n\t\t\t\t\t\t\t\tdeviceType: \"switchMultilevel\",\n\t\t\t\t\t\t\t\tprobeType: \"multilevel\",\n\t\t\t\t\t\t\t\tmetrics: {\n\t\t\t\t\t\t\t\t\ttitle: vDevConfig.title,\n\t\t\t\t\t\t\t\t\ticon: \"multilevel\",\n\t\t\t\t\t\t\t\t\tisFailed: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tself.addNotification(\"error\", \"Unknown vDev type for config parameter \" + param, \"module\");\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t\n\t\t\t\t\t\teval('vDevConfig.v2p_script = function(command, args, vdev) { \"use strict\";' + vDevConfig.v2p + '};');\n\t\t\t\t\t\teval('vDevConfig.p2v_script = function(value) { \"use strict\";' + vDevConfig.p2v + '};');\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (!cc.data[param] || !cc.data[param].size.value) { // make sure the size of the parameter is known, so Set works\n\t\t\t\t\t\t\tcc.Get(param);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar vDev = self.controller.devices.create({\n\t\t\t\t\t\t\tdeviceId: vDevIdParam,\n\t\t\t\t\t\t\tdefaults: defaults,\n\t\t\t\t\t\t\toverlay: {},\n\t\t\t\t\t\t\thandler: function(command, args) {\n\t\t\t\t\t\t\t\tif (\"update\" === command || !cc.data[param] || !cc.data[param].size.value) { // make sure the size of the parameter is known, so Set works\n\t\t\t\t\t\t\t\t\tcc.Get(param);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tvar val = vDevConfig.v2p_script(command, args, vDev);\n\t\t\t\t\t\t\t\t\tif (val !== null && val !== undefined) {\n\t\t\t\t\t\t\t\t\t\tcc.Set(param, val);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tmoduleId: self.id\n\t\t\t\t\t\t});\n\t\t\t\t\t\t\n\t\t\t\t\t\tif (vDev) {\n\t\t\t\t\t\t\tvDev.set('metrics:isFailed', self.zbee.devices[nodeId].data.isFailed.value);\n\t\t\t\t\t\t\tself.dataBind(self.gateDataBinding, self.zbee, nodeId, endpointId, clusterId, param + \".val\", function(type) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tif (type === self.ZWAY_DATA_CHANGE_TYPE.Deleted) {\n\t\t\t\t\t\t\t\t\t\tself.controller.devices.remove(vDevIdParam);\n\t\t\t\t\t\t\t\t\t} else if (!(type & self.ZWAY_DATA_CHANGE_TYPE[\"Invalidated\"])) {\n\t\t\t\t\t\t\t\t\t\tvDev.set(\"metrics:level\", vDevConfig.p2v_script(this.value));\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t\t\t}, \"value\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\t*/\n\t} catch (e) {\n\t\tvar langFile = this.loadModuleLang(),\n\t\t\tvalues = nodeId + \"-\" + endpointId + \"-\" + clusterId + \": \" + e.toString();\n\n\t\tthis.addNotification(\"error\", langFile.err_dev_create + values, \"core\");\n\t\tconsole.log(e.stack);\n\t}\n};\n\nZigbee.prototype.parseDelClusterClass = function(nodeId, endpointId, clusterId) {\n\tnodeId = parseInt(nodeId, 10);\n\tendpointId = parseInt(endpointId, 10);\n\tclusterId = parseInt(clusterId, 10);\n\n\tvar self = this,\n\t\tsepar = \"-\",\n\t\tvDevIdPrefix = \"ZBeeVDev_\" + this.config.name + \"_\",\n\t\tvDevIdNI = nodeId + separ + endpointId,\n\t\tvDevIdC = clusterId,\n\t\tvDevId = vDevIdPrefix + vDevIdNI + separ + vDevIdC;\n\n\tthis.controller.devices.remove(vDevId);\n};\n\nZigbee.prototype.nodeNameByType = function (nodeId, nodeData) {\n\n\tvar name = 'Device ' + nodeId,\n\t\ttype = '',\n\t\tnode = nodeData;\n\n\tif (node){\n\t\tvar isSleepy = false; // TODO wait for isSleepy to be moved on device // node.isSleepy.value;\n\n\t\tif (isSleepy) {\n\t\t\ttype = 'Battery';\n\t\t} else {\n\t\t\ttype = 'Mains';\n\t\t}\n\t\tname = type + name;\n\t}\n\n\treturn name;\n};\n"
  },
  {
    "path": "modules/Zigbee/lang/de.json",
    "content": "{\n\t\"m_title\":\"Zigbee Netzwerksteuerung\",\n\t\"m_descr\":\"Diese App bildet die Information zu Ihrem Zigbee Netzwerk in Ihrer UI ab. Infolgedessen muss dieses während der ganzen Zeit aktiviert sein, in welcher Sie mit dem Zigbee Geräte arbeiten wollen. In der Verwendung mit diesem Modul kann sehr viel falsch gemacht werden, daher lassen Sie es unberührt, solange es nicht wirklich benötigt wird.\",\n\t\"l_port\":\"Serieller Port der verwendet werden soll:\",\n\t\"h_port\":\"Example: /dev/ttyUSB1 or /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012082E1-if01-port0\",\n\t\"l_speed\":\"Serial Port speed in bits/s (automatically updated on speed change)\",\n\t\"l_name\":\"Interner Name\",\n\t\"h_name\":\"Dies sollte ein valider JS key String sein. Achtung! Nur ändern, wenn Sie wissen was Sie tun.\",\n\t\"rl_enableAPI\":\"Aktiviere Zigbee API\",\n\t\"h_enableAPI\":\"Erlaubt HTTP anfragen zu /ZigbeeAPI/* and /Zigbee/&lt;internal zway name&gt;/*\",\n\t\"rl_publicAPI\":\"Aktiviere öffentlichen Zugang zur Zigbee API\",\n\t\"h_publicAPI\":\"Keine authentifiziereung zur Zigbee API notwendig.\",\n\t\"rl_createVDev\":\"Erzeuge virtuelle Geräte in der Home Automation Engine\",\n\t\"h_createVDev\":\"Wenn diese Einstellung nicht aktiv ist, sind Zigbee Geräte nur in der Expert UI und über die Zigbee API sicht- bzw. benutzbar.\",\n\t\"l_config\":\"Pfad zum Ordner /config\",\n\t\"l_translations\":\"Pfad zum Ordner /dictionaries\",\n\t\"l_zddx\":\"Pfad zur ZDDX Datenbank\",\n\t\"err_binding_start\":\"Fehler beim Starten der Zigbee Bindung: \",\n\t\"err_connct\":\"Verbindung verloren zur Zigbee Geräte-ID: \",\n\t\"err_reset\": \"Benutzer zurückgesetzt Zigbee-Gerät ID: \",\n\t\"dev_btl\":\"Zigbee Geräte-ID ist wieder verbunden: \",\n\t\"err_dev_create\":\"vDev konnte mit den folgenden Daten nicht erstellt werden: \",\n\t\"main\":\"strombetriebenen Geräte\",\n\t\"battery\":\"batteriebetriebenen Geräte\"\n}"
  },
  {
    "path": "modules/Zigbee/lang/en.json",
    "content": "{\n\t\"m_title\":\"Zigbee Network Access\",\n\t\"m_descr\":\"Z-Way controls one Zigbee network with up to 232 devices. This app will combine multiple Z-Way entities into one User Interface. Essentially the app is mapping the data of another Z-Way powered Gateway into your gateway. The elements are displayed and can be used like the local ones. Please note that the function of the second gateway remains untouched. This means that this second gateway will not see the elements for your first gateway but can control and access their own elements without and further restrictions: <br><br> Settings: <br><ul><li>You need to set the IP address of the Remote Box including the port number. </li><li>You need to define the polling interval. Once second in a quite good choice.</li> <li>You need to manage the remove device to be included into you UI.</li></ul>\",\n\t\"l_port\":\"Serial port to Zigbee dongle\",\n\t\"h_port\":\"Example: /dev/ttyUSB1 or /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012082E1-if01-port0\",\n\t\"l_speed\":\"Serial port speed in bits/s (automatically updated on speed change)\",\n\t\"l_name\":\"Internal name\",\n\t\"h_name\":\"Should be a valid JS key string. Don't change unless you know what you are doing\",\n\t\"rl_enableAPI\":\"Enable Zigbee API\",\n\t\"h_enableAPI\":\"Handler HTTP requests to /ZigbeeAPI/* and /Zigbee/&lt;internal zway name&gt;/*\",\n\t\"rl_publicAPI\":\"Allow public access to Zigbee API\",\n\t\"h_publicAPI\":\"Do not ask for authentication to access Zigbee API\",\n\t\"rl_createVDev\":\"Create virtual devices in Home Automation engine\",\n\t\"h_createVDev\":\"Without this Zigbee devices will be visible only in Expert UI and via Zigbee API\",\n\t\"l_config\":\"Path to config folder\",\n\t\"l_translations\":\"Path to dictionaries folder\",\n\t\"l_zddx\":\"Path to ZDDX database\",\n\t\"err_binding_start\":\"Cannot start Zigbee binding: \",\n\t\"err_connct\":\"Connection lost to Zigbee device ID: \",\n\t\"err_reset\": \"User reset to factory defaults Zigbee device ID: \",\n\t\"dev_btl\":\"Zigbee device ID is back to life: \",\n\t\"err_dev_create\":\"Cannot create vDev based on: \",\n\t\"main\":\"main powered devices\",\n\t\"battery\":\"battery powered devices\"\n}"
  },
  {
    "path": "modules/Zigbee/lang/ru.json",
    "content": "{\n\t\"m_title\":\"Zigbee движок\",\n\t\"m_descr\":\"Активация Zigbee движка.\",\n\t\"l_port\":\"Порт для Zigbee платы/стика\",\n\t\"h_port\":\"Пример: /dev/ttyUSB1 или /dev/serial/by-id/usb-Silicon_Labs_CP2105_Dual_USB_to_UART_Bridge_Controller_012082E1-if01-port0\",\n\t\"l_speed\":\"Скорость порта в бит/сек (автоматически обновляется при смене скорости)\",\n\t\"l_name\":\"Внутреннее имя\",\n\t\"h_name\":\"Должно быть допустимой JS строкой. Не изменяйте, если не знаете, что делаете\",\n\t\"rl_enableAPI\":\"Включить Zigbee API\",\n\t\"h_enableAPI\":\"Обрабатывать HTTP запросы /ZigbeeAPI/* и /Zigbee/&lt;внутреннее имя zway&gt;/*\",\n\t\"rl_publicAPI\":\"Разрешить доступ к Zigbee API без аутентификации\",\n\t\"h_publicAPI\":\"Не требовать аутентификации при обработке запросов к Zigbee API\",\n\t\"rl_createVDev\":\"Создавать виртуальные устройства домашней автоматизации\",\n\t\"h_createVDev\":\"Если отключить, то Zigbee устройства будут видны только в Экспертном интерфейсе и через Zigbee API\",\n\t\"l_config\":\"Путь к папке с настройками config/\",\n\t\"l_translations\":\"Путь к папке с переводами\",\n\t\"l_zddx\":\"Путь к базе устройств ZDDX\",\n\t\"err_binding_start\":\"Невозможно запустить Zigbee движок: \",\n\t\"err_connct\":\"Соединение потеряно с Zigbee устройством ID: \",\n\t\"err_reset\": \"Пользователь сбросил к заводским настройкам устройство ID: \",\n\t\"dev_btl\":\"Zigbee устройство ID снова доступно: \",\n\t\"err_dev_create\":\"Не возможно создать vDev основанное на: \",\n\t\"main\":\"main powered devices\",\n\t\"battery\":\"battery powered devices\"\n}"
  },
  {
    "path": "modules/Zigbee/module.json",
    "content": "{\n\t\"dependencies\": [],\n\t\"singleton\": false,\n\t\"category\": \"peripherals\",\n\t\"author\": \"Z-Wave.Me\",\n\t\"homepage\": \"http://z-wave.me\",\n\t\"icon\": \"icon.png\",\n\t\"moduleName\":\"Zigbee\",\n\t\"version\": \"1.0.0\",\n\t\"maturity\": \"stable\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"source\": \"https://github.com/Z-Wave-Me/home-automation\"\n\t},\n\t\"defaults\": {\n\t\t\"title\": \"__m_title__\",\n\t\t\"description\": \"__m_descr__\",\n\t\t\"name\": \"zbee\",\n\t\t\"port\": \"/dev/ttyUSB0\",\n\t\t\"speed\": 115200,\n\t\t\"enableAPI\": true,\n\t\t\"publicAPI\": false,\n\t\t\"createVDev\": true,\n\t\t\"config\": \"config\",\n\t\t\"translations\": \"translations\",\n\t\t\"ZDDX\": \"ZDDX\"\n\t},\n\t\"schema\": {\n\t\t\"type\": \"object\",\n\t\t\"properties\": {\n\t\t\t\"port\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"speed\": {\n\t\t\t\t\"type\": \"number\",\n\t\t\t\t\"required\": true,\n\t\t\t\t\"enum\": [ 1200, 2400, 1800, 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800, 921600 ],\n\t\t\t\t\"default\": 115200\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"boolean\",\n\t\t\t\t\"default\": true\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"translations\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t},\n\t\t\t\"ZDDX\": {\n\t\t\t\t\"type\": \"string\",\n\t\t\t\t\"required\": true\n\t\t\t}\n\t\t},\n\t\t\"required\": false\n\t},\n\t\"options\": {\n\t\t\"fields\": {\n\t\t\t\"port\": {\n\t\t\t\t\"label\": \"__l_port__\",\n\t\t\t\t\"helper\": \"__h_port__\"\n\t\t\t},\n\t\t\t\"speed\": {\n\t\t\t\t\"label\": \"__l_speed__\",\n\t\t\t\t\"type\": \"select\",\n\t\t\t\t\"optionLabels\": [ \"1200 bits/s\", \"2400 bits/s\", \"1800 bits/s\", \"4800 bits/s\", \"7200 bits/s\", \"9600 bits/s\", \"14400 bits/s\", \"19200 bits/s\", \"28800 bits/s\", \"38400 bits/s\", \"57600 bits/s\", \"115200 bits/s\", \"230400 bits/s\", \"460800 bits/s\", \"921600 bits/s\" ],\n\t\t\t\t\"sort\": false\n\t\t\t},\n\t\t\t\"name\": {\n\t\t\t\t\"label\": \"__l_name__\",\n\t\t\t\t\"helper\": \"__h_name__\"\n\t\t\t},\n\t\t\t\"enableAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_enableAPI__\",\n\t\t\t\t\"helper\": \"__h_enableAPI__\"\n\t\t\t},\n\t\t\t\"publicAPI\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_publicAPI__\",\n\t\t\t\t\"helper\": \"__h_publicAPI__\"\n\t\t\t},\n\t\t\t\"createVDev\": {\n\t\t\t\t\"type\": \"checkbox\",\n\t\t\t\t\"rightLabel\": \"__rl_createVDev__\",\n\t\t\t\t\"helper\": \"__h_createVDev__\"\n\t\t\t},\n\t\t\t\"config\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_config__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t},\n\t\t\t\"translations\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_translations__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t},\n\t\t\t\"ZDDX\": {\n\t\t\t\t\"hidden\": true,\n\t\t\t\t\"label\": \"__l_zddx__\",\n\t\t\t\t\"helper\": \"__h_change_sth__\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "modulesCategories.json",
    "content": "{\n\t\"de\": [\n\t\t{\n\t\t\t\"id\": \"basic_gateway_modules\",\n\t\t\t\"name\": \"Basis Module\",\n\t\t\t\"description\": \"Basis Gateway Module\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"legacy_products_workaround\",\n\t\t\t\"name\": \"Produkte / Workaround\",\n\t\t\t\"description\": \"Ältere Produkte / Workaround\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"support_external_ui\",\n\t\t\t\"name\": \"Ext. UI´s\",\n\t\t\t\"description\": \"Unterstützung externer UI´s\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"support_external_dev\",\n\t\t\t\"name\": \"Ext. Geräte/Dienste\",\n\t\t\t\"description\": \"Unterstützung von externen Geräten/Diensten\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"automation_basic\",\n\t\t\t\"name\": \"Automation Grundlagen\",\n\t\t\t\"description\": \"Automation Grundlagen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"device_enhancements\",\n\t\t\t\"name\": \"Geräte-Erweiterungen\",\n\t\t\t\"description\": \"Geräte-Erweiterungen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"developers_stuff\",\n\t\t\t\"name\": \"Entwickler Module\",\n\t\t\t\"description\": \"Entwickler Module\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"complex_applications\",\n\t\t\t\"name\": \"Komplexe Anwendungen\",\n\t\t\t\"description\": \"Komplexe Anwendungen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"automation\",\n\t\t\t\"name\": \"Automation\",\n\t\t\t\"description\": \"Automation \",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"security\",\n\t\t\t\"name\": \"Sicherheit\",\n\t\t\t\"description\": \"Verbessert Sicherheit\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"peripherals\",\n\t\t\t\"name\": \"Peripheriegeräte\",\n\t\t\t\"description\": \"Z-Wave und andere Peripheriegeräte\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"surveillance\",\n\t\t\t\"name\": \"Video Überwachung\",\n\t\t\t\"description\": \"Unterstützung für Kameras\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"logging\",\n\t\t\t\"name\": \"Datenspeicherung\",\n\t\t\t\"description\": \"Datenspeichern für Drittanbieter-anwendungen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"scripting\",\n\t\t\t\"name\": \"Skripte\",\n\t\t\t\"description\": \"Skripte\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"devices\",\n\t\t\t\"name\": \"Geräte\",\n\t\t\t\"description\": \"Geräte\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"scheduling\",\n\t\t\t\"name\": \"Ablaufsteuerung\",\n\t\t\t\"description\": \"Zeitgesteuerte Abläufe\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"climate\",\n\t\t\t\"name\": \"Klima\",\n\t\t\t\"description\": \"Klima\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"environment\",\n\t\t\t\"name\": \"Umgebung\",\n\t\t\t\"description\": \"Umgebungsbezogene Daten\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"scenes\",\n\t\t\t\"name\": \"Szenen\",\n\t\t\t\"description\": \"Lichtszenen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"notifications\",\n\t\t\t\"name\": \"Benachrichtigungen\",\n\t\t\t\"description\": \"SMS, E-mail und Push benachrichtigung\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"tagging\",\n\t\t\t\"name\": \"Markierung\",\n\t\t\t\"description\": \"Markieren/Taggen von Elementen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"wifiplug\",\n\t\t\t\"name\": \"Wifi Steckdosen\",\n\t\t\t\"description\": \"Unterstützung für Wifi Steckdosen\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"system\",\n\t\t\t\"name\": \"System\",\n\t\t\t\"description\": \"System Module\",\n\t\t\t\"icon\": \"\"\n\t\t}\n\t],\n\t\"en\": [\n\t\t{\n\t\t\t\"id\": \"basic_gateway_modules\",\n\t\t\t\"name\": \"Basic Modules\",\n\t\t\t\"description\": \"Basic Gateway Modules\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"legacy_products_workaround\",\n\t\t\t\"name\": \"Products / Workaround\",\n\t\t\t\"description\": \"Legacy Products / Workaround\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"support_external_ui\",\n\t\t\t\"name\": \"Ext. UIs\",\n\t\t\t\"description\": \"Support of external UIs\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"support_external_dev\",\n\t\t\t\"name\": \"Ext. Devices/Services\",\n\t\t\t\"description\": \"Support of external Devices/Services\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"automation_basic\",\n\t\t\t\"name\": \"Automation Basics\",\n\t\t\t\"description\": \"Automation Basics\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"device_enhancements\",\n\t\t\t\"name\": \"Device enhancements\",\n\t\t\t\"description\": \"Device enhancements\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"developers_stuff\",\n\t\t\t\"name\": \"Developers Stuff\",\n\t\t\t\"description\": \"Developers Stuff\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"complex_applications\",\n\t\t\t\"name\": \"Complex Applications\",\n\t\t\t\"description\": \"Complex Applications\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"automation\",\n\t\t\t\"name\": \"Automation\",\n\t\t\t\"description\": \"Create home automation rules\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"security\",\n\t\t\t\"name\": \"Security\",\n\t\t\t\"description\": \"Enhance security\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"peripherals\",\n\t\t\t\"name\": \"Peripherals\",\n\t\t\t\"description\": \"Z-Wave and other peripherals\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"surveillance\",\n\t\t\t\"name\": \"Video surveillance\",\n\t\t\t\"description\": \"Support for cameras\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"logging\",\n\t\t\t\"name\": \"Data logging\",\n\t\t\t\"description\": \"Logging to third party services\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"scripting\",\n\t\t\t\"name\": \"Scripting\",\n\t\t\t\"description\": \"Create custom scripts\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"devices\",\n\t\t\t\"name\": \"Devices\",\n\t\t\t\"description\": \"Create devices\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"scheduling\",\n\t\t\t\"name\": \"Schedulers\",\n\t\t\t\"description\": \"Time related functions\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"climate\",\n\t\t\t\"name\": \"Climate\",\n\t\t\t\"description\": \"Climate control\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"environment\",\n\t\t\t\"name\": \"Environment\",\n\t\t\t\"description\": \"Environment related data\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"scenes\",\n\t\t\t\"name\": \"Scenes\",\n\t\t\t\"description\": \"Light scenes\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"notifications\",\n\t\t\t\"name\": \"Notifications\",\n\t\t\t\"description\": \"SMS, E-mail and push notifications\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"tagging\",\n\t\t\t\"name\": \"Tagging\",\n\t\t\t\"description\": \"Tagging widgets\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"wifiplug\",\n\t\t\t\"name\": \"Wifi Plugs\",\n\t\t\t\"description\": \"Support for wifi plugs\",\n\t\t\t\"icon\": \"\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"system\",\n\t\t\t\"name\": \"System\",\n\t\t\t\"description\": \"System Modules\",\n\t\t\t\"icon\": \"\"\n\t\t}\n\t]\n}  "
  },
  {
    "path": "release.sh",
    "content": "#!/bin/bash\n\nLAST_TAG=`git describe --tags --match 'v*' --abbrev=0`\n\ngit pull || exit\n\nif [ -n \"$1\" ]; then\n\tTAG=\"$1\"\n\tif [ -z \"`grep -E '^## [0-9\\.]* '\"$TAG\"'$' CHANGELOG.md`\" ]; then\n\t\techo \"Please update CHANGELOG.md:\"\n\t\techo \"##\" `date +'%d.%m.%Y'` \"$TAG\"\n\t\techo \"New features:\"\n\t\techo \"Improvements:\"\n\t\techo \"Fixes:\"\n\t\t../../utils/git-log-since-tag.sh $LAST_TAG | awk '{print \"* \" $0}'\n\t\texit 1\n\tfi\n\t\n\tawk '/^## [0-9.]* v[0-9.]*$/ { first++ } { if (first == 1) {print }}' README.md\n\tread -p \"Commit and release? (y/N) \" ANSWER\n\tif [ \"$ANSWER\" != \"y\" ]; then\n\t\texit 2\n\tfi\n\t\n\techo \"Releasing $TAG\"\n\t\n\tgit add CHANGELOG.md &&\n\tgit commit -m \"dist\" && git tag \"$TAG\" &&\n\tgit push && git push --tags &&\n\tgit checkout master && git merge develop && git push && git checkout develop # merge with master\nelse\n\techo \"Last released version was $LAST_TAG\"\nfi\n"
  },
  {
    "path": "router.js",
    "content": "// Make this testable by pulling in underscore from the parent module\nif (typeof _ === \"undefined\" && typeof module !== \"undefined\" && module.parent) {\n  var _ = module.parent.exports._;\n}\n\nRouter = function(namespace) {\n  this.routes = {};\n  this.namespace = namespace || \"/v1\";\n};\n\nRouter.prototype = {\n  get: function(path, role, handler, preprocessors) {\n\treturn this.addRoute(\"GET\", path, role, handler, preprocessors);\n  },\n\n  post: function(path, role, handler, preprocessors) {\n\treturn this.addRoute(\"POST\", path, role, handler, preprocessors);\n  },\n\n  put: function(path, role, handler, preprocessors) {\n\treturn this.addRoute(\"PUT\", path, role, handler, preprocessors);\n  },\n\n  del: function(path, role, handler, preprocessors) {\n\treturn this.addRoute(\"DELETE\", path, role, handler, preprocessors);\n  },\n\n  addRoute: function(method, path, role, handler, preprocessors) {\n\tvar ns = this.routes[this.namespace] = this.routes[this.namespace] || {},\n\t\tpreprocessors = preprocessors || [],\n\t\troute;\n\n\tns[method] = ns[method] || {};\n\n\tif (ns[method][path]) {\n\t  console.error(\"Path already registered, ignoring...\");\n\t  return;\n\t}\n\n\tif (_.contains(path, \":\")) {\n\t  var route = this._parseRoute(path, preprocessors);\n\t  ns[method].patterns = ns[method].patterns || [];\n\t  ns[method].patterns.push(_.extend(route, {role: role, handler: handler, preprocessors: preprocessors}));\n\t} else {\n\t  ns[method][path] = {role: role, handler: handler, preprocessors: preprocessors};\n\t}\n\n\treturn this;\n  },\n\n  /**\n   * The assumption that we only support :variable_format, we will only check\n   * for alphanumeric and underscores.\n   */\n  _parseRoute: function(path, preprocessors) {\n\tvar parts = path.split(\"/\"),\n\t\tparameters = [];\n\n\tvar pattern = \"^\" + _.map(parts, function(segment, index) {\n\t  if (segment.length > 0 && segment.indexOf(':') !== -1) {\n\t\t// Keep track of the parameters we've replaced\n\t\tparameters.push(segment.slice(1));\n\t\treturn index == parts.length - 1 ? \"(.+)\" : \"([^/]+)\"; // last argument can contain /\n\t  }\n\t  return segment;\n\t}).join(\"/\");\n\n\treturn {params: parameters, pattern: new RegExp(pattern)};\n  },\n\n  dispatch: function(method, url) {\n\tvar parts = url.split(\"/\"),\n\t\tnamespace = _.first(parts, 2).join(\"/\"),\n\t\tpath = \"/\" + _.rest(parts, 2).join(\"/\"),\n\t\tlookup, role, handler, params, preprocessors;\n\n\tvar ns = this.routes[namespace];\n\tif (ns && ns[method]) {\n\t  handler = ns[method][path];\n\t  if (handler) {\n\t\treturn {role: handler.role, handler: handler.handler, params: []};\n\t  } else {\n\t\t_.find(ns[method].patterns, function(r) {\n\t\t  var matches = r.pattern.exec(path);\n\t\t  if (!!matches) {\n\t\t\tparams = matches.slice(1);\n\t\t\trole = r.role;\n\t\t\thandler = r.handler;\n\t\t\tpreprocessors = r.preprocessors;\n\t\t\treturn true;\n\t\t  }\n\t\t});\n\n\t\tif (params && handler) {\n\t\t  params = _.map(params, function(param, i) {\n\t\t\t  var proc = preprocessors[i] || _.identity;\n\t\t\t  return proc(param);\n\t\t  });\n\t\t  return {role: role, handler: handler, params: params};\n\t\t}\n\t  }\n\t}\n  }\n};\n\nif (typeof module !== \"undefined\" && module.exports) {\n  module.exports = Router;\n};\n"
  },
  {
    "path": "updateBackendConfig.js",
    "content": "// This script transforms old formats to new\n\n(function() {\n\tvar config,\n\t\tnotifications,\n\t\toldConfigJSON,\n\t\tskins = loadObject(\"userSkins.json\"),\n\t\tstorageContentList = loadObject(\"__storageContent\"),\n\t\tloadDefaultCfg = function(e) {\n\t\t\tvar cfg = null;\n\t\t\tvar error = e ? e : ''\n\t\t\tconsole.log(\"Error loading config.json from automation/storage! Using default config.json from automation/defaultConfigs:\", error.toString());\n\n\t\t\ttry {\n\t\t\t\tcfg = fs.loadJSON(\"defaultConfigs/config.json\");\n\t\t\t\tsaveObject(\"config.json\", cfg);\n\t\t\t} catch (e) {\n\t\t\t\tconsole.log(\"Error loading default config.json from automation/defaultConfigs:\" + e.toString());\n\t\t\t}\n\n\t\t\treturn cfg;\n\t\t};\n\n\t// cleanup notifications if too big (>1 MB)\n\tvar notificationCheck = fs.stat('storage/notifications-f37bd2f66651e7d46f6d38440f2bc5dd.json');\n\n\tif (!!notificationCheck && notificationCheck.size && notificationCheck.size > 1000000) {\n\t\tconsole.log('Reset notifications to avoid memory overkill ...')\n\t\tnotifications = [];\n\t\tsaveObject(\"notifications\", []);\n\t}\n\n\ttry {\n\t\tconfig = loadObject(\"config.json\");\n\t\toldConfigJSON = JSON.stringify(config);\n\n\t\tif (!config || config === null) {\n\t\t\tconfig = loadDefaultCfg();\n\t\t}\n\t} catch (e) {\n\t\tconfig = loadDefaultCfg(e);\n\t}\n\n\tif (config && !!config) {\n\t\t// Change profiles data\n\t\tif (config.hasOwnProperty('profiles') && Array.isArray(config.profiles) && config.profiles.length > 0) {\n\t\t\tconfig.profiles.forEach(function(profile) {\n\t\t\t\tif (profile.hasOwnProperty('groups')) {\n\t\t\t\t\tdelete profile.groups;\n\t\t\t\t}\n\n\t\t\t\tif (profile.hasOwnProperty('active')) {\n\t\t\t\t\tdelete profile.active;\n\t\t\t\t}\n\n\t\t\t\tif (Array.isArray(profile.positions)) {\n\t\t\t\t\tprofile.positions = profile.positions.filter(function(position) {\n\t\t\t\t\t\treturn typeof position === 'string';\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tprofile.positions = [];\n\t\t\t\t}\n\n\t\t\t\tif (!profile.email) {\n\t\t\t\t\tprofile.email = '';\n\t\t\t\t}\n\n\t\t\t\t//add nightMode\n\t\t\t\tif (!profile.night_mode) {\n\t\t\t\t\tprofile.night_mode = false;\n\t\t\t\t}\n\n\t\t\t\t// add default skin entry\n\t\t\t\tif (profile.skin) {\n\t\t\t\t\tdelete profile.skin;\n\t\t\t\t}\n\n\t\t\t\t//remove color\n\t\t\t\tif (profile.color) {\n\t\t\t\t\tprofile.color = '';\n\t\t\t\t\tdelete profile.color;\n\t\t\t\t}\n\n\t\t\t\t// remove qrcode\n\t\t\t\tif (profile.qrcode) {\n\t\t\t\t\tif (profile.qrcode !== \"\") {\n\t\t\t\t\t\tsaveObject(profile.qrcode, null);\n\t\t\t\t\t}\n\t\t\t\t\tprofile.qrcode = '';\n\t\t\t\t\tdelete profile.qrcode;\n\t\t\t\t}\n\n\t\t\t\t// add beta software functions flag\n\t\t\t\tif(!profile.hasOwnProperty('beta')) {\n\t\t\t\t\tprofile.beta = false;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t// add uuid to old profiles\n\t\t\t\tif (!profile.hasOwnProperty('uuid')) {\n\t\t\t\t\tprofile.uuid = crypto.guid();\n\t\t\t\t}\n\t\t\t});\n\n\t\t} else {\n\t\t\t// default profile\n\t\t\tconfig.profiles = [{\n\t\t\t\tid: 1,\n\t\t\t\trole: 1,\n\t\t\t\tlogin: 'admin',\n\t\t\t\tpassword: 'admin',\n\t\t\t\temail: '',\n\t\t\t\tname: 'Administrator',\n\t\t\t\tlang: 'en',\n\t\t\t\tdashboard: [],\n\t\t\t\tinterval: 2000,\n\t\t\t\trooms: [0],\n\t\t\t\texpert_view: false,\n\t\t\t\thide_all_device_events: false,\n\t\t\t\thide_system_events: false,\n\t\t\t\thide_single_device_events: [],\n\t\t\t\tbeta: false\n\t\t\t}, {\n\t\t\t\tid: 2,\n\t\t\t\trole: 3,\n\t\t\t\tlogin: 'local',\n\t\t\t\tpassword: 'local',\n\t\t\t\temail: '',\n\t\t\t\tname: 'Local User',\n\t\t\t\tlang: 'en',\n\t\t\t\tdashboard: [],\n\t\t\t\tinterval: 2000,\n\t\t\t\trooms: [],\n\t\t\t\texpert_view: false,\n\t\t\t\thide_all_device_events: false,\n\t\t\t\thide_system_events: false,\n\t\t\t\thide_single_device_events: [],\n\t\t\t\tbeta: false\n\t\t\t}];\n\t\t}\n\n\t\t// change location data\n\t\tif (config.hasOwnProperty('locations') && Array.isArray(config.locations)) {\n\n\t\t\t// add global location if not present\n\t\t\tif (config.locations.filter(function(location) {\n\t\t\t\t\treturn location.id === 0;\n\t\t\t\t}).length === 0) {\n\t\t\t\tconfig.locations.push({\n\t\t\t\t\tid: 0,\n\t\t\t\t\ttitle: \"globalRoom\",\n\t\t\t\t\tuser_img: \"\",\n\t\t\t\t\tdefault_img: \"\",\n\t\t\t\t\timg_type: \"\",\n\t\t\t\t\tmain_sensors: [],\n\t\t\t\t\tshow_background: false\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// loop through locations\n\t\t\tconfig.locations.forEach(function(location, index) {\n\n\t\t\t\t// add show_background param\n\t\t\t\tif (!location.hasOwnProperty('show_background')) {\n\t\t\t\t\tlocation.show_background = false;\n\t\t\t\t}\n\n\t\t\t\t// add empty main_sensors param\n\t\t\t\tif (!location.hasOwnProperty('main_sensors')) {\n\t\t\t\t\tlocation.main_sensors = [];\n\t\t\t\t}\n\n\t\t\t\tconfig.locations[index] = location;\n\t\t\t});\n\t\t}\n\n\n\t\t// Change instances data\n\t\tif (config.hasOwnProperty('instances') && Array.isArray(config.instances)) {\n\n\t\t\tif (config.instances.length > 0) {\n\t\t\t\tconfig.instances.forEach(function(instance) {\n\t\t\t\t\t// move title and description params\n\t\t\t\t\tif (instance.params) {\n\t\t\t\t\t\tif (instance.params.hasOwnProperty('title') || instance.params.hasOwnProperty('description')) {\n\t\t\t\t\t\t\tinstance.title = instance.params.title;\n\t\t\t\t\t\t\tinstance.description = instance.params.description;\n\t\t\t\t\t\t\tdelete instance.params.title;\n\t\t\t\t\t\t\tdelete instance.params.description;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// move status\n\t\t\t\t\t\tif (instance.params.hasOwnProperty('status')) {\n\t\t\t\t\t\t\tinstance.active = instance.params.status === 'enable';\n\t\t\t\t\t\t\tdelete instance.params.status;\n\t\t\t\t\t\t} else if (!instance.hasOwnProperty('active')) {\n\t\t\t\t\t\t\tinstance.active = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// delete userView\n\t\t\t\t\tif (instance.hasOwnProperty('userView')) {\n\t\t\t\t\t\tdelete instance.userView;\n\t\t\t\t\t}\n\n\t\t\t\t\t// delete state\n\t\t\t\t\tif (instance.hasOwnProperty('state')) {\n\t\t\t\t\t\tdelete instance.state;\n\t\t\t\t\t}\n\n\t\t\t\t\t// delete module\n\t\t\t\t\tif (instance.hasOwnProperty('module')) {\n\t\t\t\t\t\tdelete instance.module;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Remove Z-Wave Gate, Z-Wave Dead detection and add Z-Wave Binding\n\n\t\t\tif (config.instances.length > 0) {\n\t\t\t\tvar toDelete = [];\n\n\t\t\t\tconfig.instances.forEach(function(el, indx) {\n\t\t\t\t\tif (el.moduleId && (el.moduleId === \"ZWaveDeadDetection\" || el.moduleId === \"ZWaveGate\")) {\n\t\t\t\t\t\tconsole.log(\"Removing module \" + el.moduleId);\n\t\t\t\t\t\ttoDelete.push(indx)\n\t\t\t\t\t}\n\t\t\t\t\t// Transform Security module from version 1.1 to 2.0. Add new objects\n\t\t\t\t\telse if (el.moduleId && el.moduleId === \"Security\") {\n\t\t\t\t\t\tconsole.log(\"Transform Security module from version 1.1 to 2.0\");\n\t\t\t\t\t\tif (!config.instances[indx].params.inputArming) {\n\t\t\t\t\t\t\tconfig.instances[indx].params.inputArming = {};\n\t\t\t\t\t\t\tconfig.instances[indx].params.inputArming.table = [];\n\t\t\t\t\t\t\tconfig.instances[indx].params.inputArming.notification = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!config.instances[indx].params.armFailureAction) {\n\t\t\t\t\t\t\tconfig.instances[indx].params.armFailureAction = {};\n\t\t\t\t\t\t\tconfig.instances[indx].params.armFailureAction.table = [];\n\t\t\t\t\t\t\tconfig.instances[indx].params.armFailureAction.notification = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!config.instances[indx].params.entranceDetected) {\n\t\t\t\t\t\t\tconfig.instances[indx].params.entranceDetected = {};\n\t\t\t\t\t\t\tconfig.instances[indx].params.entranceDetected.table = [];\n\t\t\t\t\t\t\tconfig.instances[indx].params.entranceDetected.notification = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (config.instances[indx].params.input && config.instances[indx].params.input.table) {\n\t\t\t\t\t\t\tconfig.instances[indx].params.input.table.forEach(function(item, index) {\n\t\t\t\t\t\t\t\tif (!item.armCondition) {\n\t\t\t\t\t\t\t\t\tconfig.instances[indx].params.input.table[index].armCondition = \"on\";\n\t\t\t\t\t\t\t\t\tconfig.instances[indx].params.input.table[index].sensorAtTheEntrance = \"off\";\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t});\n\n\t\t\t\ttoDelete.reverse().forEach(function(el) {\n\t\t\t\t\tconfig.instances.splice(el, 1)\n\t\t\t\t});\n\n\t\t\t\tvar maxInstanceId = Math.max.apply(null, config.instances.map(function(el) {\n\t\t\t\t\treturn el.id;\n\t\t\t\t}));\n\n\t\t\t\tif (toDelete.length) {\n\t\t\t\t\tconsole.log(\"Adding module ZWave\");\n\t\t\t\t\tconfig.instances.push({\n\t\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\t\"name\": \"zway\",\n\t\t\t\t\t\t\t\"port\": \"/dev/ttyAMA0\",\n\t\t\t\t\t\t\t\"enableAPI\": true,\n\t\t\t\t\t\t\t\"publicAPI\": false,\n\t\t\t\t\t\t\t\"createVDev\": true,\n\t\t\t\t\t\t\t\"config\": \"config\",\n\t\t\t\t\t\t\t\"translations\": \"translations\",\n\t\t\t\t\t\t\t\"ZDDX\": \"ZDDX\",\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"active\": true,\n\t\t\t\t\t\t\"moduleId\": \"ZWave\",\n\t\t\t\t\t\t\"module\": \"Z-Wave Network Access\",\n\t\t\t\t\t\t\"state\": \"hidden\",\n\t\t\t\t\t\t\"title\": \"Z-Wave Network Access\",\n\t\t\t\t\t\t\"description\": \"Allows accessing Z-Wave devices from attached Z-Wave transceiver.\\n(Added by backend updater script)\",\n\t\t\t\t\t\t\"id\": maxInstanceId + 1\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove modules_categories from config\n\t\tif (config.hasOwnProperty('modules_categories')) {\n\t\t\tdelete config.modules_categories;\n\t\t}\n\n\t\t// Add permanently_hidden, h, visibility, hasHistory properties\n\t\tObject.keys(config.vdevInfo).forEach(function(id) {\n\t\t\tif (!config.vdevInfo[id].hasOwnProperty('permanently_hidden')) {\n\t\t\t\tconsole.log(\"Adding to VDev \" + id + \" new property permanently_hidden\");\n\t\t\t\tconfig.vdevInfo[id].permanently_hidden = false;\n\t\t\t}\n\t\t\tif (!config.vdevInfo[id].hasOwnProperty('h')) {\n\t\t\t\tvar hashCode = function(str) {\n\t\t\t\t\tvar hash = 0,\n\t\t\t\t\t\ti, chr, len;\n\t\t\t\t\tif (this.length === 0) {\n\t\t\t\t\t\treturn hash;\n\t\t\t\t\t}\n\t\t\t\t\tfor (i = 0, len = str.length; i < len; i++) {\n\t\t\t\t\t\tchr = str.charCodeAt(i);\n\t\t\t\t\t\thash = ((hash << 5) - hash) + chr;\n\t\t\t\t\t\thash = hash & hash; // Convert to 32bit integer\n\t\t\t\t\t}\n\t\t\t\t\treturn hash;\n\t\t\t\t};\n\t\t\t\tconfig.vdevInfo[id].h = hashCode(id);\n\t\t\t}\n\t\t\tif (!config.vdevInfo[id].hasOwnProperty('hasHistory')) {\n\t\t\t\tconfig.vdevInfo[id].hasHistory = false;\n\t\t\t}\n\t\t\tif (!config.vdevInfo[id].hasOwnProperty('visibility')) {\n\t\t\t\tconfig.vdevInfo[id].visibility = true;\n\t\t\t}\n\t\t\tif (config.vdevInfo[id].location == null) {\n\t\t\t\tconfig.vdevInfo[id].location = 0;\n\t\t\t}\n\t\t});\n\n\t\t// Change IDs to new notation\n\n\t\t{\n\t\t\tfunction getNewID(id) {\n\t\t\t\tvar pattern1 = /^ZWayVDev_([0-9]+(:[0-9]+)+)$/,\n\t\t\t\t\tpattern2 = /^Remote_[0-9]+_([0-9]+(:[0-9]+)+)$/,\n\t\t\t\t\tpattern3 = /^ZWayVDev_(.*)_Remote_[0-9]+-[0-9]+-[0-9]+$/,\n\t\t\t\t\tpattern4 = /^ZWayVDev_(.*)_Remote_[0-9]+-[0-9]+-[0-9]+-[0-9]+$/;\n\n\t\t\t\tif (id.match(pattern1)) {\n\t\t\t\t\t// replace : to - in Z-Way vDev\n\t\t\t\t\treturn id.replace(pattern1, \"ZWayVDev_zway_$1\").replace(/:/g, \"-\");\n\t\t\t\t} else if (id.match(pattern2)) {\n\t\t\t\t\t// replace : to - in Z-Way Remote vDev and add ZWayVDev_zway_ prefix (removing module id from name)\n\t\t\t\t\treturn id.replace(pattern2, \"ZWayVDev_zway_Remote_$1\").replace(/:/g, \"-\");\n\t\t\t\t} else if (id.match(pattern3)) {\n\t\t\t\t\t// add -B suffixes to ZWayVDev_zway_Remote (switchControl buttons)\n\t\t\t\t\treturn id.replace(pattern3, \"$&-B\");\n\t\t\t\t} else if (id.match(pattern4)) {\n\t\t\t\t\t// add -S suffixes to ZWayVDev_zway_Remote (toggleButton scenes)\n\t\t\t\t\treturn id.replace(pattern4, \"$&-S\");\n\t\t\t\t} else {\n\t\t\t\t\treturn id;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update IDs of devices created by SwitchControlGenerator and ZWaveGate\n\t\t\tObject.keys(config.vdevInfo).forEach(function(id) {\n\t\t\t\tvar _id = getNewID(id);\n\t\t\t\tif (id !== _id) {\n\t\t\t\t\tconsole.log(\"Changing VDev ID from \" + id + \" to \" + _id);\n\t\t\t\t\tconfig.vdevInfo[_id] = config.vdevInfo[id];\n\t\t\t\t\tdelete config.vdevInfo[id];\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Update IDs in profiles\n\t\t\tconfig.profiles && config.profiles.forEach(function(profile) {\n\t\t\t\tprofile.positions && profile.positions.forEach(function(id, index) {\n\t\t\t\t\tvar _id = getNewID(id);\n\t\t\t\t\tif (id !== _id) {\n\t\t\t\t\t\tconsole.log(\"Changing widget ID from \" + id + \" to \" + _id);\n\t\t\t\t\t\tprofile.positions[index] = _id;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\n\t\t\t// Update IDs in modules params\n\t\t\tfunction fixArray(arr) {\n\t\t\t\tarr.forEach(function(element, index) {\n\t\t\t\t\tif (typeof element === \"string\") {\n\t\t\t\t\t\tif (element != getNewID(element)) {\n\t\t\t\t\t\t\tconsole.log(\"Changing ID in params (array) from \" + element + \" to \" + getNewID(element));\n\t\t\t\t\t\t\tarr[index] = getNewID(element);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (typeof element === \"object\" && element && element.constructor && element.constructor === Array) {\n\t\t\t\t\t\tfixArray(element);\n\t\t\t\t\t} else if (typeof element === \"object\" && element) {\n\t\t\t\t\t\tfixObject(element);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfunction fixObject(obj) {\n\t\t\t\tfor (var key in obj) {\n\t\t\t\t\tif (typeof obj[key] === \"string\") {\n\t\t\t\t\t\tif (obj[key] != getNewID(obj[key])) {\n\t\t\t\t\t\t\tconsole.log(\"Changing ID in params (object) from \" + obj[key] + \" to \" + getNewID(obj[key]));\n\t\t\t\t\t\t\tobj[key] = getNewID(obj[key]);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (typeof obj[key] === \"object\" && obj[key] && obj[key].constructor && obj[key].constructor === Array) {\n\t\t\t\t\t\tfixArray(obj[key]);\n\t\t\t\t\t} else if (typeof obj[key] === \"object\" && obj[key]) {\n\t\t\t\t\t\tfixObject(obj[key]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (var indx in config.instances) {\n\t\t\t\tfixObject(config.instances[indx].params);\n\t\t\t}\n\t\t}\n\n\t\t// Transform profile to user profile\n\n\t\t{\n\t\t\tvar counter = 0;\n\t\t\tconfig.profiles && config.profiles.forEach(function(profile) {\n\t\t\t\tif (!profile.login) {\n\t\t\t\t\tprofile.login = \"admin\" + (counter++ ? counter.toString(10) : \"\");\n\t\t\t\t\tprofile.password = \"admin\";\n\t\t\t\t\tprofile.role = 1;\n\t\t\t\t\tprofile.lang = \"en\";\n\t\t\t\t\tprofile.default_ui = 1;\n\t\t\t\t\tprofile.dashboard = profile.positions;\n\t\t\t\t\tprofile.interval = 2000;\n\t\t\t\t\tprofile.rooms = [0];\n\t\t\t\t\tprofile.expert_view = false;\n\t\t\t\t\tprofile.hide_all_device_events = false;\n\t\t\t\t\tprofile.hide_system_events = false;\n\t\t\t\t\tprofile.hide_single_device_events = [];\n\n\t\t\t\t\tdelete profile.description;\n\t\t\t\t\tdelete profile.widgets;\n\t\t\t\t\tdelete profile.positions;\n\t\t\t\t}\n\n\t\t\t\t// delete profile.sid\n\t\t\t\tif (profile.sid) {\n\t\t\t\t\tdelete profile.sid;\n\t\t\t\t}\n\n\t\t\t\t// change MD5 hashed passwords back to string\n\t\t\t\t// replace it with profile.login or 'admin' as fallback\n\t\t\t\t// affects versions below rc39\n\t\t\t\tif (profile.password && /^[a-f0-9]{32}$/.test(profile.password)) {\n\t\t\t\t\tprofile.password = profile.login ? profile.login : 'admin';\n\t\t\t\t}\n\n\t\t\t\t// add room 0 if no rooms exists\n\t\t\t\tif (!profile.rooms) {\n\t\t\t\t\tprofile.rooms = [0];\n\t\t\t\t}\n\n\t\t\t\t// transform room if it is no array\n\t\t\t\tif (profile.rooms && !Array.isArray(profile.rooms)) {\n\t\t\t\t\tprofile.rooms = !isNaN(profile.rooms) && profile.rooms % 1 === 0 ? [profile.rooms] : [];\n\t\t\t\t}\n\n\t\t\t\t// add room 0 if rooms exists but room 0 is missing\n\t\t\t\tif (profile.role === 1 && profile.rooms && Array.isArray(profile.rooms)) {\n\t\t\t\t\tif (profile.rooms.indexOf(0) === -1) {\n\t\t\t\t\t\tprofile.rooms.push(0);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// remove room 0 form non admin profiles\n\t\t\t\tif (profile.role !== 1 && profile.rooms.indexOf(0) > -1) {\n\t\t\t\t\tprofile.rooms.splice(profile.rooms.indexOf(0), 1);\n\t\t\t\t}\n\n\t\t\t\t// transform positions into dashboard\n\t\t\t\tif (Array.isArray(profile.positions)) {\n\t\t\t\t\tvar unique = function(array) {\n\t\t\t\t\t\tvar a = array.concat();\n\t\t\t\t\t\tfor (var i = 0; i < a.length; ++i) {\n\t\t\t\t\t\t\tfor (var j = i + 1; j < a.length; ++j) {\n\t\t\t\t\t\t\t\tif (a[i] === a[j])\n\t\t\t\t\t\t\t\t\ta.splice(j--, 1);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn a;\n\t\t\t\t\t};\n\n\t\t\t\t\tprofile.dashboard = profile.dashboard ? unique(profile.dashboard.concat(profile.positions)) : (!profile.dashboard ? profile.positions : []);\n\n\t\t\t\t\tdelete profile.positions;\n\t\t\t\t}\n\n\t\t\t\tif (!profile.expert_view && (profile.role === 1 || profile.role === 3)) {\n\t\t\t\t\tprofile.expert_view = false;\n\t\t\t\t}\n\n\t\t\t\t// delete profile.passwordConfirm\n\t\t\t\tif (profile.passwordConfirm) {\n\t\t\t\t\tdelete profile.passwordConfirm;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// add local user if he not exists\n\t\t\tif (config.profiles && config.profiles.filter(function(profile) {\n\t\t\t\t\treturn profile.login === 'local';\n\t\t\t\t}).length === 0) {\n\t\t\t\tconfig.profiles.push({\n\t\t\t\t\tid: config.profiles.length + 1,\n\t\t\t\t\trole: 3,\n\t\t\t\t\tlogin: 'local',\n\t\t\t\t\tpassword: 'local',\n\t\t\t\t\tname: 'Local User',\n\t\t\t\t\tlang: 'en',\n\t\t\t\t\tdashboard: [],\n\t\t\t\t\tinterval: 2000,\n\t\t\t\t\trooms: [0],\n\t\t\t\t\texpert_view: false,\n\t\t\t\t\thide_all_device_events: false,\n\t\t\t\t\thide_system_events: false,\n\t\t\t\t\thide_single_device_events: []\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// convert password to a secure salted hash\n\t\t\tconfig.profiles.forEach(function(profile) {\n\t\t\t\tif (profile.login === \"admin\" && profile.password === \"admin\" || profile.login === \"local\" && profile.password === \"local\") return; // skip default profiles\n\t\t\t\tif (profile.salt && !!profile.salt) return; // skip already converted\n\n\t\t\t\tprofile.salt = generateSalt();\n\t\t\t\tprofile.password = hashPassword(profile.password, profile.salt);\n\t\t\t});\n\n\t\t\t// Add hide_single_device_events and devies to each profile\n\t\t\tconfig.profiles.forEach(function(profile) {\n\t\t\t\tif (!profile.hide_single_device_events)\n\t\t\t\t\tprofile.hide_single_device_events = [];\n\t\t\t\tif (!profile.devices)\n\t\t\t\t\tprofile.devices = [];\n\t\t\t});\n\n\t\t\t// Save changes\n\n\t\t\tif (oldConfigJSON !== JSON.stringify(config)) { // do we need to update the config?\n\t\t\t\ttry {\n\t\t\t\t\tsaveObject(\"config.json\", config);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.log(\"Error: can not write back config.json to storage: \", e);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// add new modules in v3.1.x (to be removed in 3.3.0 or 4.0.0)\n\t\t{\n\t\t\tvar hasNotificationFiltering = false,\n\t\t\t    hasMobileAppSupport = false,\n\t\t\t    oldMobileAppSupport = -1,\n\t\t\t    hasNotificationChannelEmail = false;\n\t\t\t\n\t\t\tconfig.instances.forEach(function(instance, index) {\n\t\t\t\tif (instance.moduleId === 'NotificationFiltering') hasNotificationFiltering = true;\n\t\t\t\tif (instance.moduleId === 'NotificationChannelEmail') hasNotificationChannelEmail = true;\n\t\t\t\tif (instance.moduleId === 'MobileAppSupport' && instance.params.devices) oldMobileAppSupport = index;\n\t\t\t\tif (instance.moduleId === 'MobileAppSupport' && !instance.params.devices) hasMobileAppSupport = true;\n\t\t\t});\n\n\t\t\tvar maxInstanceId = Math.max.apply(null, config.instances.map(function(el) {\n\t\t\t\treturn el.id;\n\t\t\t}));\n\t\t\t\n\t\t\tif (!hasNotificationChannelEmail) {\n\t\t\t\tconsole.log(\"Adding module NotificationChannelEmail\");\n\t\t\t\tconfig.instances.push({\n\t\t\t\t\t\"id\": ++maxInstanceId,\n\t\t\t\t\t\"moduleId\": \"NotificationFiltering\",\n\t\t\t\t\t\"active\": \"true\",\n\t\t\t\t\t\"title\": \"Notification Filtering\",\n\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\"rules\": [{\n\t\t\t\t\t\t\t\"recipient_type\": \"user\",\n\t\t\t\t\t\t\t\"user\": 1,\n\t\t\t\t\t\t\t\"logLevel\": \"errors,warnings\",\n\t\t\t\t\t\t\t\"devices\": []\n\t\t\t\t\t\t}],\n\t\t\t\t\t\t\"autogenOnDeviceListUpdate\": true,\n\t\t\t\t\t\t\"normalizeRules\": true\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tif (oldMobileAppSupport > -1) {\n\t\t\t\tconfig.instances.splice(oldMobileAppSupport, 1);\n\t\t\t}\n\t\t\t\n\t\t\tif (!hasMobileAppSupport) {\n\t\t\t\tconsole.log(\"Adding module MobileAppSupport\");\n\t\t\t\tconfig.instances.push({\n\t\t\t\t\t\"id\": ++maxInstanceId,\n\t\t\t\t\t\"moduleId\": \"MobileAppSupport\",\n\t\t\t\t\t\"active\": true,\n\t\t\t\t\t\"title\": \"Mobile App Support\",\n\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\"apps\": []\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\t\n\t\t\tif (!hasNotificationChannelEmail) {\n\t\t\t\tconsole.log(\"Adding module NotificationChannelEmail\");\n\t\t\t\tconfig.instances.push({\n\t\t\t\t\t\"id\": ++maxInstanceId,\n\t\t\t\t\t\"moduleId\": \"NotificationChannelEmail\",\n\t\t\t\t\t\"active\": true,\n\t\t\t\t\t\"title\": \"Notifications by E-mail\",\n\t\t\t\t\t\"params\": {\n\t\t\t\t\t\t\"subject\": \"Z-Way Notification\",\n\t\t\t\t\t\t\"channels\": []\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsaveObject('config.json', config);\n\t\t}\n\t} else {\n\t\tconsole.log(\"Error loading config.json! Unable to start z-way-sever. Check if automation/defaultConfigs directory includes config.json or automation/storage directory includes configjson-06b2d3b23dce96e1619d2b53d6c947ec.json. Checkout https://github.com/Z-Wave-Me/home-automation or contact Z-Wave.Me support for help.\");\n\t}\n\n\tif (skins) {\n\t\ttry {\n\n\t\t\tif (skins === null) {\n\t\t\t\tskins = [{\n\t\t\t\t\tname: \"default\",\n\t\t\t\t\ttitle: \"Default\",\n\t\t\t\t\tdescription: \"Default skin\",\n\t\t\t\t\tversion: \"1.0.3\",\n\t\t\t\t\ticon: true,\n\t\t\t\t\tauthor: \"Martin Vach\",\n\t\t\t\t\thomepage: \"http://www.zwave.eu\",\n\t\t\t\t\tactive: true\n\t\t\t\t}];\n\t\t\t} else {\n\t\t\t\tskins.forEach(function(skin) {\n\t\t\t\t\tif (skin.name === 'default' && !skin.hasOwnProperty('active')) {\n\t\t\t\t\t\tskin.active = true;\n\t\t\t\t\t} else if (!skin.hasOwnProperty('active')) {\n\t\t\t\t\t\tskin.active = false;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tsaveObject(\"userSkins.json\", skins);\n\t\t} catch (e) {\n\t\t\tconsole.log(\"Error: can not write userSkins.json to storage: \", e);\n\t\t}\n\t}\n\n\t// change notification property h into uts and delete h\n\tif (notifications) {\n\t\ttry {\n\t\t\tnotifications.forEach(function(notification) {\n\t\t\t\tif (notification.hasOwnProperty('id') && notification.id.toString().length === 10) {\n\t\t\t\t\tnotification.id = Math.floor(notification.id * 1000);\n\t\t\t\t}\n\n\t\t\t\tif (notification.hasOwnProperty('h')) {\n\t\t\t\t\tdelete notification.h;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tsaveObject('notifications', notifications);\n\t\t} catch (e) {\n\t\t\tconsole.log(\"Error: Cannot write notifications to storage: \", e.message);\n\t\t}\n\n\t}\n\n\t// remove null entries from list\n\tif (storageContentList && Array.isArray(storageContentList) && storageContentList.length > 0) {\n\t\tstorageContentList = storageContentList.filter(function(entry) {\n\t\t\treturn !!entry;\n\t\t});\n\n\t\tsaveObject('__storageContent', storageContentList);\n\t}\n})();"
  }
]