[
  {
    "path": ".eslintrc.json",
    "content": "{\n    \"env\": {\n        \"browser\": false,\n        \"commonjs\": false,\n        \"node\": true,\n        \"mocha\": true,\n        \"es2021\": true\n    },\n    \"globals\": {\n       \"assert\" : \"writeable\",\n       \"expect\" : \"writeable\",\n       \"sinon\" : \"writeable\",\n       \"ACC_EOL\" : \"readonly\",\n       \"DEVICE_EOL\" : \"readonly\",\n       \"FORMAT_EOL\" : \"readonly\",\n       \"UNITS_EOL\" : \"readonly\",\n       \"PERMS_EOL\" : \"readonly\",\n       \"DEVICE_DATA\" : \"readonly\",\n       \"ACC_DATA\" : \"readonly\",\n       \"CHAR_DATA\" : \"readonly\",\n       \"CMD4_CHAR_TYPE_ENUMS\" : \"readonly\",\n       \"CMD4_ACC_TYPE_ENUM\" : \"readonly\",\n       \"CMD4_DEVICE_TYPE_ENUM\" : \"readonly\",\n       \"cleanStatesDir\" : \"readonly\",\n       \"accEnumIndexToC\" : \"readonly\",\n       \"devEnumIndexToC\" : \"readonly\",\n       \"fs\" : \"writeable\",\n       \"HomebridgeAPI\" : \"writeable\",\n       \"Logger\" : \"writeable\",\n       \"platformAccessory_1\" : \"writeable\"\n    },\n    \"extends\": \"eslint:recommended\",\n    \"parserOptions\": {\n        \"ecmaVersion\": 12\n    },\n    \"rules\": {\n       \"no-fallthrough\": [\"error\", { \"commentPattern\": \"break[\\\\s\\\\w]*omitted\"}],\n       \"no-whitespace-before-property\": [\"error\"],\n       \"arrow-spacing\": [\"error\"]\n    }\n}\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "content": "---\nname: Bug Report\nabout: Raise a bug related report for cmd4.\ntitle: \"[Bug]\"\nlabels: bug\nassignees: ztalbot2000\n\n---\n** Cmd4 No longer supported:**\n<!-- As of September 2025, I will no longer be supporting Cmd4. Any bugs will most likely go into the bit bucket -->\n\n<!-- Provide a general summary in the Title above -->\n\n**Describe The Bug:**\n<!-- A clear and concise description of what problem you are experiencing. -->\n\n**To Reproduce:**\n<!-- Steps to reproduce the behaviour. -->\n\n**Expected Behaviour:**\n<!-- A clear and concise description of what you expected to happen. -->\n\n[**Link to Logs:**]()\n<!-- If using a gist, hastebin or pastebin; paste the link between the two () above -->\n<!-- If pasting log files directly, please instead do so between the ``` lines below -->\n<!-- If using hastebin/pastebin or other text sharing website please make the lifespan long-->\n<!-- Remove any sensitive information, passwords, etc. -->\n\n**Paste of Logs:**\n```\n\n```\n\n**Cmd4 Config:**\n<!-- Paste relevant output between the two ``` lines below -->\n<!-- Remove any sensitive information, passwords, etc. -->\n\n```json\n\n\n```\n\n**Screenshots:**\n<!-- If applicable, add screenshots to help explain your problem. -->\n\n**Environment:**\n\n* **Node.js Version**: <!-- node -v -->\n* **NPM Version**: <!-- npm -v -->\n* **Homebridge Version**: <!-- homebridge -V -->\n* **homebridge-cmd4 Version**: <!-- Check on homebridge-config-ui-x -->\n* **Operating System**: Raspbian / Ubuntu / Debian / Windows / macOS / Docker / other\n* **Process Supervisor**: Systemd / init.d / pm2 / launchctl / Docker / hb-service / other / none\n\n<!-- Click the \"Preview\" tab before you submit to ensure the formatting is correct. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "content": "---\nname: Feature Request\nabout: Suggest an idea or improvement for cmd4.\ntitle: \"[Feature Request]\"\nlabels: enhancement\nassignees: ztalbot2000\n\n---\n** Cmd4 No longer supported:**\n<!-- As of September 2025, I will no longer be supporting Cmd4. Any issues will most likely go into the bit bucket -->\n\n<!-- Provide a general summary in the Title above -->\n\n**Is your feature request related to a problem? Please describe:**\n<!-- A clear and concise description of what the problem is. E.g. John there needs to be a button to buy you a coffee. -->\n\n**Describe the solution you'd like:**\n<!-- A clear and concise description of what you want to happen. -->\n\n**Describe alternatives you've considered:**\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\n\n**Additional context:**\n<!-- Add any other context or screenshots about the feature request here. -->\n\n<!-- Click the \"Preview\" tab before you submit to ensure the formatting is correct. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/support-request.md",
    "content": "---\nname: Support Request\nabout: Stuck on one of the installation steps or having trouble with your script?\ntitle: \"[Support]\"\nlabels: help wanted\nassignees: ztalbot2000\n\n---\n** Cmd4 No longer supported:**\n<!-- As of September 2025, I will no longer be supporting Cmd4. Any requests will most likely go into the bit bucket -->\n\n<!-- Provide a general summary in the Title above -->\n\n<!-- Before opening an issue, please review the README for Installation Details and Basic Troubleshooting to ensure that this is a new issue, and alternatively search the closed issues for similar problems. -->\n\n**Describe Your Problem:**\n<!-- A clear and concise description of what problem you are experiencing or what installation step you are stuck on. -->\n\n[**Link to Logs:**]()\n<!-- If using a gist, hastebin or pastebin; paste the link between the two () above -->\n<!-- If pasting log files directly, please instead do so between the ``` lines below -->\n<!-- If using hastebin/pastebin or other text sharing website please make the lifespan long-->\n<!-- Remove any sensitive information, passwords, etc. -->\n\n**Paste of Logs:**\n```\n\n```\n\n**Cmd4 Config:**\n<!-- Paste relevant output between the two ``` lines below -->\n<!-- Remove any sensitive information, passwords, etc. -->\n\n```json\n\n\n```\n\n**Screenshots:**\n<!-- If applicable, add screenshots to help explain your problem. -->\n\n**Environment:**\n\n* **Node.js Version**: <!-- node -v -->\n* **NPM Version**: <!-- npm -v -->\n* **Homebridge Version**: <!-- homebridge -V -->\n* **homebridge-cmd4 Version**: <!-- Check on homebridge-config-ui-x -->\n* **Operating System**: Raspbian / Ubuntu / Debian / Windows / macOS / Docker / other\n* **Process Supervisor**: Systemd / init.d / pm2 / launchctl / Docker / hb-service / other / none\n\n<!-- Click the \"Preview\" tab before you submit to ensure the formatting is correct. -->\n"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "---\nname: Pull Request\nabout: Resolve an issue or add an improvement to cmd4.\ntitle: \"[Pull Request]\"\nlabels: pull-request\nassignees: ztalbot2000\n\n---\n\n<!-- Provide a general summary in the Title above -->\n\n**Is your pull request related to a problem? Please describe:**\n<!-- A clear and concise description of what the problem is. E.g. John there needs to be a button to buy you a coffee. -->\n\n**Describe the solution you'd have implemented:**\n<!-- A clear and concise description of what you your pull request is for. Explain the technical solution you have provided and how it addresses the issue. -->\n\n**Do your changes pass unit testing ( npm run test ) :**\n- [x] Yes\n- [ ] No\n\n**Do your changes pass lint testing ( npm run lint ) :**\n- [x] Yes\n- [ ] No\n\n**Additional context:**\n<!-- Add any other context or screenshots about the pull request here. -->\n\n<!-- Click the \"Preview\" tab before you submit to ensure the formatting is correct. -->\n"
  },
  {
    "path": ".gitignore",
    "content": "# Mac\n.DS_Store\n\n# Text editors\n*.swp\n\n# Stupid commits of npm package\n*.tgz\n\n# My favorite temp backup\n*.[0-9]\n*.save*\n*_save*\n*_bak*\n\n# Compiled Executables\njsmin\na.out\n\n# node\nnode_modules\nnpm-debug.log\n.node-version\n\ntest/tmp/*\n\n# Not a fan\npackage-lock.json\n\n# work in progress folder\nlocal\n"
  },
  {
    "path": ".npmignore",
    "content": ".eslintrc.json\n.gitignore\n.github\n.huskyrc\n.DS_Store\n*_save*\n*_bak*\n*.swp\ncommitlint.config.js\njsmin\nutils/indexOfEnumLintTest.js\nscreenshots\ntest\nnode_modules\nlocal\ntools\ndocs/autoGenerated\ndocs/images\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Homebridges-cmd4 - CMD4 Plugin for Homebridge - Supports ~All Accessory Types and now all Characteristics too!!\n#### 8.0.4 (2026-02-03)\n\n##### Bug Fixes\n\n*  Support Node v24 ([feb476b5](https://github.com/ztalbot2000/homebridge-cmd4/commit/feb476b5bbea98099f7ebaf4a8dcea03572dac82))\n\n\n"
  },
  {
    "path": "Cmd4Accessory.js",
    "content": "'use strict';\n\nconst moment = require( \"moment\" );\n\n// Settings, Globals and Constants\nlet settings = require( \"./cmd4Settings\" );\nconst constants = require( \"./cmd4Constants\" );\n\nlet Logger = require( \"./utils/Logger\" );\nconst { getAccessoryName, getAccessoryDisplayName\n      } = require( \"./utils/getAccessoryNameFunctions\" );\nlet getAccessoryUUID = require( \"./utils/getAccessoryUUID\" );\nconst { addQueue, queueExists } = require( \"./Cmd4PriorityPollingQueue\" );\n\n// Hierarchy variables\nlet HV = require( \"./utils/HV\" );\n\nlet createAccessorysInformationService = require( \"./utils/createAccessorysInformationService\" );\n\nlet lcFirst = require( \"./utils/lcFirst\" );\nlet trueTypeOf = require( \"./utils/trueTypeOf\" );\n\n// The sObject.defineProperty is to resolve a lint issue.\n// See utils/indexOfEnumLintTest.js for further information.\nlet indexOfEnum = require( \"./utils/indexOfEnum\" );\nObject.defineProperty( exports, \"indexOfEnum\", { enumerable: true, get: function ( ){ return indexOfEnum.indexOfEnum; } });\n\n// For changing validValue Constants to Values and back again\nvar { transposeConstantToValidValue,\n    } = require( \"./utils/transposeCMD4Props\" );\n\nlet isJSON = require( \"./utils/isJSON\" );\nlet isCmd4Directive = require( \"./utils/isCmd4Directive\" );\nlet isAccDirective = require( \"./utils/isAccDirective\" );\nlet isDevDirective = require( \"./utils/isDevDirective\" );\n\n// Pretty Colors\nvar chalk = require( \"chalk\" );\n\n// These would already be initialized by index.js\nlet CMD4_ACC_TYPE_ENUM = require( \"./lib/CMD4_ACC_TYPE_ENUM\" ).CMD4_ACC_TYPE_ENUM;\nlet CMD4_DEVICE_TYPE_ENUM = require( \"./lib/CMD4_DEVICE_TYPE_ENUM\" ).CMD4_DEVICE_TYPE_ENUM;\n\nconst Cmd4Storage = require( \"./utils/Cmd4Storage\" );\n\nlet FakeGatoHistoryService = null;\n\n// Only one TV is allowed per bridge. Circumvented by\n// publishing the TV externally.\nlet numberOfTVsPerBridge = 0;\n\n// Array Remove\nfunction removeFromArray( arr, val )\n{\n   for (let i = arr.length - 1; i >= 0; i--)\n   {\n      if (arr[i] === val)\n      {\n        // console.log(\"Removing %s\", val );\n        arr.splice(i, 1);\n      }\n   }\n   return arr;\n}\n\n// Accessory definitions - THE GOOD STUFF STARTs HERE\n//\n//    An Homebridge accessory by default is passed the following params\n//\n// @params:\n//   log        -  Logging functionality.\n//   config     -  The JSON description of the accessory.\n//   api        -  Homebridge API.\n//\n// @Optional params\n//   parentInfo -  Optionally passed from a parent as if this is a linked accessory,\n//                 or from a CMD4 Platform.\n//\n//\nclass Cmd4Accessory\n{\n   constructor( log, config, api, STORED_DATA_ARRAY, parentInfo )\n   {\n\n      // Non Platform accessories get called with homebridges Logger\n      // replace with ours\n      if ( typeof log.setOutputEnabled === \"function\" )\n      {\n         this.log = log;\n\n         // Carry the debug flag from the platform\n         settings.cmd4Dbg = log.debugEnabled;\n      }\n      else\n      {\n         this.log = new Logger( );\n\n         if ( config[ constants.DEBUG ]  == true ||\n              config[ \"Debug\" ]  == true ||\n              process.env.DEBUG == settings.PLATFORM_NAME )\n         {\n            settings.cmd4Dbg = true;\n         }\n\n      }\n      this.log.setDebugEnabled( settings.cmd4Dbg );\n\n      this.config = config;\n      this.api = api;\n      // keep a copy because traversing it for format checking can be slow.\n      this.Characteristic = api.hap.Characteristic;\n      this.parentInfo = parentInfo;\n\n      // Use parent values ( if any ) or these defaults.\n      // LEVEL is a number, possibly 0 which must be handled more precisely.\n      this.CMD4 = ( parentInfo && parentInfo.CMD4 ) ? parentInfo.CMD4 : constants.STANDALONE;\n      this.LEVEL = ( parentInfo && parentInfo.LEVEL !== undefined ) ? parentInfo.LEVEL + 1 : 0;\n      this.createdCmd4Accessories = ( parentInfo && parentInfo.createdCmd4Accessories ) ? parentInfo.createdCmd4Accessories : [ ];\n\n\n      let typeMsg =  [ \"\", \"Linked \", \"Added \" ][ this.LEVEL ] || \"\";\n\n      if ( settings.cmd4Dbg ) log.debug( chalk.blue ( `Creating ${ typeMsg }${ this.CMD4 } Accessory type for : ${ config.displayName } LEVEL: ${ this.LEVEL }` ) );\n\n      this.services = [ ];\n      this.linkedAccessories = [ ];\n      this.listOfVariables = { };\n      this.listOfConstants = { };\n\n      // Determines if the accessory is communicable\n      this.errorValue = 0;\n      this.errorString = \"init\";\n\n      // Used to determine missing related characteristics and\n      // to determine if the related characteristic is also polled.\n      this.listOfPollingCharacteristics = { };\n\n      // An extra flag\n      this.ServiceCreated = false;\n\n      // DisplayName and/or Name must be defined.\n      // No need to update config anymore as it is no longer cached, only the Characteristic values are.\n      this.name = getAccessoryName( this.config );\n      this.displayName = getAccessoryDisplayName( this.config );\n\n\n      // Everything that needs to talk to the device now goes through the queue\n      this.queue = null;\n\n\n      // Use the Hierarhy variables from the parent, if not create it.\n      this.hV = new HV( );\n      if ( parentInfo && parentInfo.hV )\n      {\n         this.hV.update( parentInfo.hV );\n      }\n\n      // In case it is not passed in.\n      if ( STORED_DATA_ARRAY == undefined || STORED_DATA_ARRAY == null )\n         this.STORED_DATA_ARRAY = [ ];\n      else\n         this.STORED_DATA_ARRAY = STORED_DATA_ARRAY;\n\n      let parseConfigShouldUseCharacteristicValues = true;\n      if ( ! Array.isArray( this.STORED_DATA_ARRAY ) )\n      {\n         this.log.warn( \"STORED_DATA_ARRAY passed in is not an array and should be reported.\" );\n         this.STORED_DATA_ARRAY = [ ];\n      }\n\n      // generate a unique id for the accessory this should be generated from\n      // something globally unique, but constant, for example, the device serial\n      // number or MAC address.\n      let uuid = getAccessoryUUID( config, this.api.hap.uuid );\n\n      // Handle case change\n      let existingDataU = this.STORED_DATA_ARRAY.find( data => data[ \"UUID\" ] === uuid );\n      if ( existingDataU )\n      {\n            //Z this.log.info( chalk.blue ( `THIS MSG TO BE REMOVED. RENAMING UUID for: ${ config.displayName } LEVEL: ${ this.LEVEL }` ) );\n            existingDataU[ \"uuid\" ] = existingDataU[ \"UUID\" ];\n            delete existingDataU[ \"UUID\" ];\n      }\n\n      // NOTE: We saved the data via lower case uuid.\n      let existingData = this.STORED_DATA_ARRAY.find( data => data[ constants.UUID ] === uuid );\n\n      if ( existingData )\n      {\n         //Z this.log.info( chalk.blue ( `THIS MSG TO BE REMOVED. Found existing data for: ${ this.displayName }` ) );\n         if ( settings.cmd4Dbg ) this.log.debug(`Cmd4Accessory: found existingData for ${ this.displayName }` );\n         if ( existingData.storedValuesPerCharacteristic )\n         {\n            //Z this.log.info( chalk.blue ( `THIS MSG TO BE REMOVED. Found old storedValuesPerCharacteristic for: ${ this.displayName }` ) );\n            if ( settings.cmd4Dbg ) this.log.debug( `Upgrading to cmd4Storage` );\n            this.cmd4Storage = new Cmd4Storage( this.log, existingData.storedValuesPerCharacteristic );\n            this.STORED_DATA_ARRAY.push( { [ constants.UUID ]: uuid,\n                                           [ constants.CMD4_STORAGE_lv ]: this.cmd4Storage\n                                         }\n                                        );\n            //this.STORED_DATA_ARRAY.remove( existingData );\n            removeFromArray( this.STORED_DATA_ARRAY, existingData );\n         } else if ( existingData.cmd4Storage )\n         {\n            //Z this.log.info( chalk.blue ( `THIS MSG TO BE REMOVED. Using existing cmd4Storage for: ${ this.displayName }` ) );\n            if ( settings.cmd4Dbg ) this.log.debug( `Using existing cmd4Storage` );\n            this.cmd4Storage = new Cmd4Storage( this.log, existingData.cmd4Storage );\n            this.STORED_DATA_ARRAY.push( { [ constants.UUID ]: uuid,\n                                           [ constants.CMD4_STORAGE_lv ]: this.cmd4Storage\n                                         }\n                                        );\n            //this.STORED_DATA_ARRAY.remove( existingData );\n            removeFromArray( this.STORED_DATA_ARRAY, existingData );\n         } else {\n            //Z log.info( chalk.blue ( `THIS MSG TO BE REMOVED. Unexpected empty cmd4Storage for: ${ this.displayName }` ) );\n            this.log.warn( `Unexpected empty cmd4Storage` );\n            this.cmd4Storage = new Cmd4Storage( this.log );\n            this.STORED_DATA_ARRAY.push( { [ constants.UUID ]: uuid,\n                                           [ constants.CMD4_STORAGE_lv ]: this.cmd4Storage\n                                         }\n                                        );\n            //this.STORED_DATA_ARRAY.remove( existingData );\n            removeFromArray( this.STORED_DATA_ARRAY, existingData );\n         }\n\n         // Do not read stored values from config.json\n         parseConfigShouldUseCharacteristicValues = false;\n      } else\n      {\n         //Z log.info( chalk.blue ( `THIS MSG TO BE REMOVED. Creating new cmd4Storage for: ${ this.displayName }` ) );\n         if ( settings.cmd4Dbg ) this.log.debug(`Cmd4Accessory: creating new cmd4Storage for ${ this.displayName }` );\n         // Instead of local variables for every characteristic, create an array to\n         // hold values for  all characteristics based on the size of all possible\n         // characteristics.  Placing them in .config will make them be cached over\n         // restarts.\n         this.cmd4Storage = new Cmd4Storage( this.log );\n\n         this.STORED_DATA_ARRAY.push( { [ constants.UUID ]: uuid,\n                                        [ constants.CMD4_STORAGE_lv ]: this.cmd4Storage\n                                      }\n                                    );\n      }\n\n      // Add the global constants to the listOfConstants\n      if ( this.parentInfo && this.parentInfo.globalConstants != null )\n      {\n         this.processConstants( this.parentInfo.globalConstants );\n         // Since linked accessories get processed first, The parentInfo they\n         // get is actually \"this\" and we need for the linked accessory to\n         // process the constants first in order to see them. i.e. ${IP}\n         this.globalConstants = this.parentInfo.globalConstants;\n      }\n\n      // Direct if polling should be set or false.\n      // You cannot copy polling from the parent because you would be copying the array\n      // of polled characteristics that the child does not have, or turning on polling\n      // for linked accessories too.\n      //this.polling = false;\n\n\n      // Init the Global Fakegato service once !\n      if ( FakeGatoHistoryService == null )\n         FakeGatoHistoryService = require( \"fakegato-history\" )( api );\n\n      // Get the supplied values from the accessory config.\n      this.parseConfig( this.config, parseConfigShouldUseCharacteristicValues  );\n\n      // Update the accessories namespace for stored variables\n      // like timeout, stateChangeResponseTime ... As it may require\n      // changes from parseConfig.\n      this.hV.update( this );\n\n      // Add any required characteristics of a device that are missing from\n      // a users config.json file.\n      this.addRequiredCharacteristicStoredValues( );\n\n      // The accessory cannot have the same UUID as any other\n      checkAccessoryForDuplicateUUID( this, this.uuid );\n\n      // The default response time is in seconds\n      if ( ! this.stateChangeResponseTime )\n         this.stateChangeResponseTime = CMD4_DEVICE_TYPE_ENUM.properties[ this.typeIndex ].devicesStateChangeDefaultTime;\n\n      // Check the polling config for characteristics that may be set there\n      // and not in the config.json.\n      this.checkPollingConfigForUnsetCharacteristics( this.polling );\n\n      // Convert the accessoriesConfig ( if any ) to an array of Cmd4Accessory\n      if ( this.accessoriesConfig && this.CMD4 == constants.PLATFORM && this.LEVEL == 0 )\n      {\n         log.info( `Creating accessories for: ${ this.displayName }` );\n\n         // Let me explain.\n         // Level 0 are standalone or platform.\n         // Level 1 is linked.\n         // Added accessories are on the same level as linked,\n         // but they are not linkedTypes, just added to the platform.\n         // For Example: TelevisionSpeaker.\n         let savedLevel = this.LEVEL;\n         this.LEVEL = 1; // will be incremented to 2.\n         this.accessories = this.accessoryTypeConfigToCmd4Accessories( this.accessoriesConfig, this );\n         this.LEVEL = savedLevel;\n      }\n\n      // Convert the linkedTypes ( if any ) to an array of Cmd4Accessory\n      // Linked Accessories can be on Standalone or Platform Accessories.\n      if ( this.linkedAccessoriesConfig && this.LEVEL == 0 )\n      {\n         log.info( `Creating linked accessories for: ${ this.displayName }` );\n         this.linkedAccessories = this.accessoryTypeConfigToCmd4Accessories( this.linkedAccessoriesConfig, this );\n      }\n\n      // This sets up which characteristics, if any, will be polled\n      // This can be done for only LEVEL 0 accessories and itself\n      if ( this.LEVEL == 0 )\n      {\n         // if ( settings.cmd4Dbg ) log.debug( \"CMD4=%s LEVEL=%s for %s\", accessory.CMD4, accessory.LEVEL, accessory.displayName );\n         // The linked accessory children are at different levels of recursion, so only\n         // allow what is posssible.\n         if ( this.linkedAccessories && this.linkedAccessories.length > 0 )\n         {\n            if ( settings.cmd4Dbg ) this.log.debug( `Setting up which characteristics will be polled for Linked Accessories of ${ this.displayName }` );\n\n            this.linkedAccessories.forEach( ( linkedAccessory ) =>\n            {\n               if ( linkedAccessory.polling != false )\n               {\n                  linkedAccessory.determineCharacteristicsToPollForAccessory( linkedAccessory );\n               }\n            });\n         }\n\n         // The Television Speaker Platform Example\n         if ( this.accessories && this.accessories.length > 0 )\n         {\n            if ( settings.cmd4Dbg ) this.log.debug( `Setting up which characteristics will be polled for Added Accessories of ${ this.displayName }` );\n            this.accessories.forEach( ( addedAccessory ) =>\n            {\n               if ( addedAccessory.polling )\n               {\n                  addedAccessory.determineCharacteristicsToPollForAccessory( addedAccessory );\n               }\n            });\n         }\n\n         if ( settings.cmd4Dbg ) this.log.debug( `Setting up which characteristics will be polled for ${ this.displayName }` );\n         this.determineCharacteristicsToPollForAccessory( this );\n      }\n\n      // Create all the services for the accessory, including fakegato and polling\n      // Only true Standalone accessories can have their services created and\n      // polling started. Otherwise the platform will have to do this.\n      if ( this.CMD4 == constants.STANDALONE && this.LEVEL == 0 )\n      {\n         if ( settings.cmd4Dbg ) log.debug( `Creating Standalone service for: ${ this.displayName }` );\n         this.createServicesForStandaloneAccessoryAndItsChildren( this )\n      }\n\n   } // Cmd4Accessory ( log, config, api, STORED_DATA_ARRAY, parentInfo )\n\n   identify( callback )\n   {\n      callback( );\n   }\n\n   getServices( )\n   {\n      //if ( this.services )\n      //{\n      //   if ( settings.cmd4Dbg ) this.log.debug( Fg.Red + \"ZZZZ Returning:%s number of services for:%s\" + Fg.Rm, this.services.length, this.displayName );\n      //} else {\n      //   if ( settings.cmd4Dbg ) this.log.debug( Fg.Red + \"ZZZZ Returning this.services:%s for:%s\" + Fg.Rm, this.services, this.displayName );\n      //}\n      return this.services;\n   }\n\n   // Any required characteristic of an accessory that is not in the accessories\n   // config will be added later by the existance of its stored value, so\n   // find the missing characteristics and add their value s here.\n   addRequiredCharacteristicStoredValues ( )\n   {\n      // Get the properties for this accessories device type\n      let properties = CMD4_DEVICE_TYPE_ENUM.properties[ this.typeIndex ];\n\n      // Check if required characteristics should be added, or TLV8 removed.\n      for ( let accTypeEnumIndex = 0 ; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex++ )\n      {\n         // Get the properties for this accessories device type\n         let devProperties = CMD4_DEVICE_TYPE_ENUM.properties[ this.typeIndex ];\n\n         // See if the characteristic index is in the required characteristics of the device\n         let requiredIndex = devProperties.requiredCharacteristics.indexOfEnum( i => i.type === accTypeEnumIndex );\n\n         let format = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].props.format;\n\n         // No matter what, remove it\n         if ( format == this.api.hap.Formats.TLV8 && this.hV.allowTLV8 == false )\n         {\n            if ( this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex ) != null )\n            {\n               this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, null );\n\n               this.log.warn( `****** Removing TLV8 required characteristic: ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n            }\n            continue;\n         }\n\n         // if it is required and not stored, add it\n         if ( requiredIndex != -1 && this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex ) == null )\n         {\n            this.log.warn( `**** Adding required characteristic ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type } for ${ this.displayName }` );\n            this.log.warn( `Not defining a required characteristic can be problematic` );\n\n            // Get the default value to store\n            let defaultValue = properties.requiredCharacteristics[ requiredIndex ].defaultValue;\n\n            // If ConfiguredName was not defined, then use the Accessories Name\n            if ( accTypeEnumIndex == CMD4_ACC_TYPE_ENUM.ConfiguredName )\n               defaultValue = getAccessoryName( this.config );\n\n            if ( settings.cmd4Dbg ) this.log.debug( `*****Adding default value ${ defaultValue } for: ${ this.displayName }` );\n\n            this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, defaultValue );\n         }\n      }\n   }\n\n   checkPollingConfigForUnsetCharacteristics( pollingConfig )\n   {\n      if ( trueTypeOf( pollingConfig ) != Array )\n         return;\n\n      if ( settings.cmd4Dbg ) this.log.debug( `Checking ${ this.displayName } for polling of unset characteristics.` );\n\n      pollingConfig.forEach( ( jsonPollingConfig ) =>\n      {\n         let value;\n         let valueToStore = null;\n         let accTypeEnumIndex = -1;\n         let key;\n\n         for ( key in jsonPollingConfig )\n         {\n            value = jsonPollingConfig[ key ];\n\n            let rcDirective = isCmd4Directive( key );\n            if ( rcDirective == null )\n            {\n               rcDirective = isCmd4Directive( key, true );\n               if ( rcDirective != null )\n               {\n                  // warn now\n                  this.log.warn( `The config.json Cmd4 Polling Directive: ${ key } is Capitalized.  It should be: ${ rcDirective.key }. In the near future this will be an error for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n                  // create the proper lower case value\n                  jsonPollingConfig[ rcDirective.key ] = value;\n                  // delete the upper case value\n                  delete jsonPollingConfig[ key ];\n\n                  //set the key\n                  key = rcDirective.key;\n               }\n            }\n            // Not finding the key is not an error as it could be a Characteristic\n\n\n            switch ( key )\n            {\n               case constants.TIMEOUT:\n               case constants.INTERVAL:\n               // break omitted\n               case constants.QUEUE:\n               {\n                  break;\n               }\n               case constants.QUEUETYPES:\n               {\n                  // This whole record is not a characteristic polling entry\n                  // continue to next ( via return )\n                  return;\n               }\n               case constants.CHARACTERISTIC:\n               {\n                  //2 checkPollingOfUnsetCharacteristics\n                  valueToStore = null;\n\n                  let rcDirective = isAccDirective( value, false );\n                  if ( rcDirective.accTypeEnumIndex == null )\n                  {\n                     rcDirective = isAccDirective( value, true );\n                     if ( rcDirective.accTypeEnumIndex == null )\n                        throw new Error( `No such polling characteristic: \"${ value }\" for: \"${ this.displayName }\".` );\n\n                     this.log.warn( `The config.json Polling characteristic: ${ value } is Capitalized it should be: ${ rcDirective.type }.  In the near future this will be an Error so that Cmd4 can use homebridge-ui.\\nTo remove this Warning, Please fix your config.json.` );\n                  }\n                  accTypeEnumIndex = rcDirective.accTypeEnumIndex;\n\n                  // We can do this as this is a new way to do things.\n                  let storedValue = this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex );\n                  if ( storedValue == undefined )\n                     throw new Error( `Polling for: \"${ value }\" requested, but characteristic is not in your config.json file for: \"${ this.displayName }\".` );\n\n                  // This makes thinks nice down below.\n                  valueToStore = storedValue;\n                  break;\n               }\n               default:\n               {\n                  // Is this still useful?\n                  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.indexOfEnum( key );\n\n                  if ( accTypeEnumIndex < 0  )\n                     // throw new Error( `OOPS: \"${ key }\" not found while parsing for characteristic polling. There something wrong with your config.json file?` );\n                     throw new Error( `OOPS: \"${ key }\" not found while parsing for characteristic polling of \"${ this.displayName }\". There something wrong with your config.json file?` );\n\n                  valueToStore = value;\n               }\n            }\n         }\n\n         if ( accTypeEnumIndex == -1 )\n            throw new Error( `No characteristic found while parsing for characteristic polling of: \"${ this.displayName }\". There something wrong with your config.json file?` );\n\n         if ( this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex ) == undefined )\n         {\n            this.log.warn( `Polling for: \"${ key }\" requested, but characteristic` );\n            this.log.warn( `is not in your config.json file for: ${ this.displayName }` );\n            this.log.warn( `This will be an error in the future.` );\n         }\n\n         this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, valueToStore );\n      });\n   }\n\n   createServicesForStandaloneAccessoryAndItsChildren( accessory )\n   {\n      if ( settings.cmd4Dbg ) accessory.log.debug( chalk.blue( `createServicesFor${ this.CMD4 }AccessoryAndItsChildren` ) );\n      if ( accessory.ServiceCreated == true )\n      {\n         if ( settings.cmd4Dbg ) accessory.log.debug( chalk.red( `SERVICES ALREADY CREATED FOR ${ this.displayName } ${ this.CMD4 } ${ this.LEVEL }` ) );\n         return;\n      } else {\n         accessory.ServiceCreated = true;\n      }\n\n\n\n      let properties = CMD4_DEVICE_TYPE_ENUM.properties[ accessory.typeIndex ];\n\n      //\n      // Standalone Accessory\n      //\n      // Create the accessory's service\n      accessory.service = new properties.service( accessory.name, accessory.subType )\n\n      if ( settings.cmd4Dbg ) accessory.log.debug( `Creating information service for standalone accessory: ${ accessory.displayName }` );\n\n\n      // Create the Standalone accessory's information service.\n      createAccessorysInformationService( accessory );\n\n      // Create the Standalone accessory's services for all its linked children\n      if ( accessory.linkedAccessories )\n      {\n         accessory.linkedAccessories.forEach( ( linkedAccessory ) =>\n         {\n            let properties = CMD4_DEVICE_TYPE_ENUM.properties[ linkedAccessory.typeIndex ];\n\n            // Standalone Step 4.\n            //    const hdmi1InputService = this.tvAccessory.addService( this.Service.InputSource, `hdmi1', 'HDMI 1' );\n            if ( settings.cmd4Dbg ) accessory.log.debug( `Standalone Step 4. linkedAccessory( ${ accessory.displayName } ).service = new Service( ${ linkedAccessory.name }, ${ linkedAccessory.subType } )` );\n            linkedAccessory.service = new properties.service( linkedAccessory.name, linkedAccessory.subType )\n            accessory.services.push( linkedAccessory.service );\n\n            // Hmmm Double Check this !!\n            // Create Information Service\n            //if ( settings.cmd4Dbg ) linkedAccessory.log.debug( \"Creating information service for linkedAccessory:%s\", linkedAccessory.displayName );\n            //createAccessorysInformationService( linkedAccessory );\n\n            if ( settings.cmd4Dbg ) accessory.log.debug( `Standalone Step 5. ${ accessory.displayName }.service.addLinkedService( ${ linkedAccessory.displayName }.service` );\n            // Standalone Step 5.\n            //    tvService.addLinkedService( hdmi1InputService ); // link to tv service\n            accessory.service.addLinkedService( linkedAccessory.service );\n\n            linkedAccessory.addAllServiceCharacteristicsForAccessory( linkedAccessory );\n\n            // Setup the fakegato service if defined in the config.json file\n            linkedAccessory.setupAccessoryFakeGatoService( linkedAccessory.fakegatoConfig );\n\n            // Move the information service to the top of the list\n            linkedAccessory.services.unshift( linkedAccessory.informationService );\n\n         });\n      }\n\n      accessory.addAllServiceCharacteristicsForAccessory( accessory );\n\n      // Setup the fakegato service if defined in the config.json file\n      accessory.setupAccessoryFakeGatoService( accessory.fakegatoConfig );\n\n      accessory.services.push( accessory.service );\n\n      // Move the information service to the top of the list\n      accessory.services.unshift( accessory.informationService );\n\n   }\n\n   // ***********************************************\n   //\n   // setCachedValue:\n   //   This methos will update the cached value of a\n   //   characteristic of a accessory.\n   //\n   // ***********************************************\n   setCachedValue( accTypeEnumIndex, characteristicString, value, callback )\n   {\n      let self = this;\n\n      if ( self.hV.statusMsg == \"TRUE\" )\n         self.log.info( chalk.blue( `Setting (Cached) ${ self.displayName } ${ characteristicString }` ) + ` ${ value }` );\n      else\n         if ( settings.cmd4Dbg ) self.log.debug( `setCachedvalue accTypeEnumIndex:( ${ accTypeEnumIndex } )-\"${ characteristicString }\" function for: ${ self.displayName } value: ${ value }` );\n\n\n      // Save the cached value.\n      // Fakegato does not need to be updated as that is done on a \"Get\".\n      self.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, value );\n\n      let relatedCurrentAccTypeEnumIndex = this.getDevicesRelatedCurrentAccTypeEnumIndex( accTypeEnumIndex );\n\n      // We are currently tring to set a cached characteristics \n      // like \"Target*\".\n      // There is no way for its relatedCurrentAccTypeEnumIndex characteristic like \"Current*\"\n      // to be set if cached or Polled (with the exception below).\n      if ( relatedCurrentAccTypeEnumIndex != null )\n      {\n         // We are in a \"Set\" but this applies to the \"Get\" for why we would need to\n         // set the relatedCurrentAccTypeEnumIndex Characteristic as well.\n\n         if ( self.listOfPollingCharacteristics[ relatedCurrentAccTypeEnumIndex ])\n         {\n            let relatedCharacteristicString = CMD4_ACC_TYPE_ENUM.properties[ relatedCurrentAccTypeEnumIndex ].type;\n            self.log.info( chalk.blue( `Also Setting (Cached) ${ self.displayName } ${ relatedCharacteristicString }` ) + ` ${ value }` );\n            self.cmd4Storage.setStoredValueForIndex( relatedCurrentAccTypeEnumIndex, value );\n         }\n      }\n\n      callback( null );\n   }\n\n   // ***********************************************\n   //\n   // GetCachedValue:\n   //   This methos will return an accessories cached\n   //   characteristic value.\n   //\n   // ***********************************************\n   getCachedValue( accTypeEnumIndex, characteristicString, callback )\n   {\n      let self = this;\n\n      let storedValue = self.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex );\n      if ( storedValue == null || storedValue == undefined )\n      {\n         self.log.warn( `getCachedValue ${ characteristicString } for: ${ self.displayName } has no cached value` );\n\n         callback( 10, null );\n      }\n\n      if ( settings.cmd4Dbg ) self.log.debug( `getCachedValue ${ characteristicString } for: ${ self.displayName } returned (CACHED) value: ${ storedValue }` );\n\n      callback( 0, storedValue );\n\n      // Store history using fakegato if set up\n      self.updateAccessoryAttribute( accTypeEnumIndex, storedValue );\n   }\n\n   // Check props to see if any characteristic properties\n   // are to be changed.  For example, currentTemperature\n   // minValue to be below zero.\n   configHasCharacteristicProps( accTypeEnumIndex )\n   {\n      if ( this.props == undefined )\n         return undefined;\n\n      if ( ! isJSON( this.props ) )\n         return undefined;\n\n      let characteristicProps = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].props;\n      let type = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( accTypeEnumIndex );\n      let ucType = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( accTypeEnumIndex );\n\n      let definitions;\n\n      if ( this.props[ type ] )\n         definitions = this.props[ type ];\n\n      if ( this.props[ ucType ] )\n         definitions = this.props[ ucType ];\n\n      if ( ! definitions )\n         return undefined;\n\n      let rc = definitions;\n      for ( let key in definitions )\n      {\n         // warn now\n         if ( key.charAt( 0 ) === key.charAt( 0 ).toUpperCase() )\n         {\n            this.log.warn( `The property definition key: ${ key } is Capitalized.  In the near future all characteristics will start with a lower case character for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n         }\n         let lcKey = lcFirst ( key );\n\n         if ( characteristicProps[ lcKey ] == undefined )\n            throw new Error( `props for key \"${ key }\" not in definition of \"${ type }\"` );\n\n\n         if ( typeof characteristicProps[ lcKey ] !=  typeof definitions[ lcKey ] )\n            throw new Error( `props for key \"${ key }\" type \"${ typeof definitions[ key ] }\" Not equal to definition of \"${ typeof characteristicProps[ key ] }\"` );\n\n      }\n\n      return rc;\n   }\n   checkCharacteristicNeedsFixing( accessory, accTypeEnumIndex )\n   {\n      // Hap keeps changing this where Current and Target don't match.\n      // We fix this here.\n      if ( accTypeEnumIndex == CMD4_ACC_TYPE_ENUM.CurrentHeatingCoolingState )\n      {\n         if ( settings.cmd4Dbg ) this.log.debug( \"fixing heatingCoolingState\" );\n         accessory.service.getCharacteristic(\n            CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].\n               characteristic ).setProps(\n                  {\n                    maxValue: 3,\n                    validValues: [ 0, 1, 2, 3 ]\n                });\n      }\n\n      return;\n   }\n\n   // ***********************************************\n   //\n   // addAllServiceCharacteristicsForAccessory:\n   //     Method to set up all services for those characteristics in the\n   //     config.json file.\n   //\n   //\n   // Explanation:\n   // If you are wondering why this is done this way as compared to\n   // other plugins that do the switch and a bind in their getServices\n   // section; It took a week to figure out why the security\n   // system was not getting updated after setting the target state.\n   // The get currentState needs to be called after the set targetState,\n   // but that was not enough. Something is different with their\n   // getServices bind implementation.  While everything works, for\n   // some reason the IOS HomeKit app and even the Eve app never gets\n   // the result of the get currentState.\n   // I could delve further into their implementation, but this works.\n   // It was one of many methods I tried after examining and trying\n   // many plugins.\n   // This method was taken from homebridge-real-fake-garage-doors by\n   // plasticrake.\n   // P.S  - This is probably more documentation of code anywhere\n   //        in Homebridge :-)    If you find it useful, send\n   //        me a like ;-)\n   //\n   //\n   // Note: This code wipes out 5K of duplicate code.\n   //       by using a bound function.  It appears\n   //       to work on my iMac.\n   //\n   // ***********************************************\n   addAllServiceCharacteristicsForAccessory( accessory )\n   {\n       if ( settings.cmd4Dbg ) accessory.log.debug( `Adding All Service Characteristics for: ${ accessory.displayName }` );\n\n       let perms = \"\";\n\n       // Check every possible characteristic\n       for ( let accTypeEnumIndex = 0; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex++ )\n       {\n          // For \"Get\" or \"Set\" commands, we send uppercase\n          let uCCharacteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( accTypeEnumIndex );\n\n          // If there is a stored value for this characteristic ( defined by the config file )\n          // Then we need to add the characteristic too\n          let storedValue = accessory.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex );\n          if ( storedValue != undefined )\n          {\n             if ( settings.cmd4Dbg ) accessory.log.debug( \"Found characteristic:%s value:%s for:%s\",\n                  uCCharacteristicString,\n                  storedValue,\n                  this.displayName );\n\n             // Find out if the characteristic is not part of the service\n             // and needs to be added.\n             if ( ! accessory.service.testCharacteristic(\n                  CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].characteristic ) )\n             {\n                //if ( settings.cmd4Dbg ) accessory.log.debug( \"Adding optional characteristic:%s for: %s\", CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type, this.displayName );\n                if ( settings.cmd4Dbg ) accessory.log.debug( \"Adding optional characteristic:%s for: %s\", uCCharacteristicString, this.displayName );\n\n                accessory.service.addCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].characteristic );\n             }\n\n             this.checkCharacteristicNeedsFixing( accessory, accTypeEnumIndex );\n\n\n             let props = accessory.configHasCharacteristicProps( accTypeEnumIndex );\n             if ( props )\n             {\n                if ( settings.cmd4Dbg ) accessory.log.debug( \"Overriding characteristic %s props for: %s \", CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type, this.displayName );\n                  accessory.service.getCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].\n                         characteristic )\n                  .setProps(\n                     // props is an object of name value pairs (characteristics)\n                     props\n                  );\n             }\n\n             // Get the permissions of characteristic ( Read/Write ... )\n             // Both are 100% the same.\n             // perms = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].props.perms\n             perms = accessory.service.getCharacteristic(\n                CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                .characteristic ).props.perms;\n\n\n             // Comment before change\n             // \"Read and or write, we need to set the value once.\n             // If the characteristic was optional and read only, this will add\n             //  it with the correct value.  You cannot add and set a read characteristic.\"\n             //\n\n             // What was happening was at startup all writeable characteristics were calling\n             // setValue and the MyAir was getting hammered.\n\n             // We need to check if the characteristic is readable but not writeable.\n             // Things this will set are like:\n             // - Name\n             // - CurrentTemperature\n             // - CurrentHeatingCoolingState\n             // - StatusFault\n             // Homebridge V2 removes Perms.READ && Perms.WRITE\n             if ( //perms.indexOf( this.api.hap.Perms.READ ) >= 0 &&\n                  //perms.indexOf( this.api.hap.Perms.WRITE ) == -1 ||\n                  perms.indexOf( this.api.hap.Perms.PAIRED_READ ) >= 0 &&\n                  perms.indexOf( this.api.hap.Perms.PAIRED_WRITE ) == -1 )\n             {\n                accessory.service.setCharacteristic(\n                   CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].characteristic,\n                      this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex ) );\n             }\n\n\n             // Add getValue via getCachedValue funtion to service\n             if ( accessory.service.getCharacteristic(\n                    CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                    .characteristic ).listeners( \"get\" ).length == 0 )\n             {\n                // Add Read services for characterisitcs, if possible\n                // Homebridge v2 removed Perms.READ\n                if ( // perms.indexOf( this.api.hap.Perms.READ ) != -1 ||\n                     perms.indexOf( this.api.hap.Perms.PAIRED_READ ) != -1 )\n                {\n\n                   // getCachedValue or getValue\n                   if ( ! accessory.polling ||\n                          accessory.listOfPollingCharacteristics[ accTypeEnumIndex ] == undefined\n                      )\n                   {\n                      if ( settings.cmd4Dbg ) this.log.debug( chalk.yellow( `Adding getCachedValue for ${ accessory.displayName } characteristic: ${ uCCharacteristicString } ` ) );\n                      //Get cachedValue\n                      accessory.service.getCharacteristic(\n                         CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                         .characteristic )\n                            .on( \"get\", accessory.getCachedValue.bind( accessory, accTypeEnumIndex, uCCharacteristicString ) );\n                  } else\n                  {\n                      if ( settings.cmd4Dbg ) this.log.debug( chalk.yellow( `Adding priorityGetValue for ${ accessory.displayName } characteristic: ${ uCCharacteristicString }` ) );\n\n                      let details = accessory.lookupAccessoryHVForPollingCharacteristic( accessory, accTypeEnumIndex );\n\n                      // Set parms are accTypeEnumIndex, value, callback\n                      // Get parms are accTypeEnumIndex, callback\n                      accessory.service.getCharacteristic(\n                         CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                         .characteristic )\n                            .on( \"get\", accessory.queue.priorityGetValue.bind( accessory, accTypeEnumIndex, uCCharacteristicString, details.timeout ) );\n                   }\n                }\n             }\n\n             // Add setValue function to service\n             if ( accessory.service.getCharacteristic(\n                  CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                  .characteristic ).listeners( \"set\" ).length == 0 )\n             {\n                // Add Write services for characterisitcs, if possible\n                // Homebridge V2 removes Perms.WRITE\n                if ( // perms.indexOf( this.api.hap.Perms.WRITE ) != -1 ||\n                     perms.indexOf( this.api.hap.Perms.PAIRED_WRITE ) != -1 )\n                {\n                   // setCachedValue or setValue\n                   if ( ! accessory.polling ||\n                        accessory.listOfPollingCharacteristics[ accTypeEnumIndex ] == undefined)\n                   {\n                      if ( settings.cmd4Dbg ) this.log.debug( chalk.yellow( `Adding setCachedValue for ${ accessory.displayName } characteristic: ${ uCCharacteristicString } ` ) );\n                      // setCachedValue has parameters:\n                      // accTypeEnumIndex, value, callback\n                      // The first bound value though is \"this\"\n                      let boundSetCachedValue = accessory.setCachedValue.bind( this, accTypeEnumIndex, uCCharacteristicString );\n                      accessory.service.getCharacteristic(\n                         CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                         .characteristic ).on( \"set\", ( value, callback ) => {\n                             boundSetCachedValue( value, callback );\n\n                      });\n\n                   } else {\n                      if ( settings.cmd4Dbg ) this.log.debug( chalk.yellow( `Adding prioritySetValue for ${ accessory.displayName } characteristic: ${ uCCharacteristicString } ` ) );\n\n                      let details = accessory.lookupAccessoryHVForPollingCharacteristic( accessory, accTypeEnumIndex );\n\n                      // Set parms are accTypeEnumIndex, value, callback\n                      // Get parms are accTypeEnumIndex, callback\n                      let boundSetValue = accessory.queue.prioritySetValue.bind( this, accTypeEnumIndex, uCCharacteristicString, details.timeout, details.stateChangeResponseTime );\n                         accessory.service.getCharacteristic(\n                         CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ]\n                         .characteristic ).on( \"set\", ( value, callback ) => {\n                             boundSetValue( value, callback );\n                      });\n                   }\n                }\n             }\n          }\n       }\n   }\n\n   updateAccessoryAttribute( accTypeEnumIndex, value )\n   {\n      if ( accTypeEnumIndex < 0 || accTypeEnumIndex > CMD4_ACC_TYPE_ENUM.EOL )\n      {\n         this.log.error( `Internal error: updateAccessoryAttribute - accTypeEnumIndex: ${ accTypeEnumIndex } for: ${ this.displayName } not found` );\n         return;\n      }\n\n      this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, value );\n\n      if ( this.loggingService )\n      {\n         let firstParm, secondParm, thirdParm;\n         let firstParmValue, secondParmValue, thirdParmValue = 0;\n         let firstParmDirective, secondParmDirective, thirdParmDirective;\n\n         switch ( this.eve )\n         {\n            case constants.FAKEGATO_TYPE_ENERGY:\n            {\n               firstParm   = this.fakegatoConfig[ constants.POWER ] || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.POWER }: ${ firstParmValue }` );\n               // Eve Energy ( Outlet service )\n               this.loggingService.addEntry(\n                  { [ constants.TIME ]  :  moment( ).unix( ),\n                    [ constants.POWER ] : firstParmValue\n                  });\n               break;\n            }\n            case constants.FAKEGATO_TYPE_ROOM:\n            {\n               firstParm       = this.fakegatoConfig[ constants.TEMP ]     || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n               secondParm      = this.fakegatoConfig[ constants.HUMIDITY ] || \"0\";\n               secondParmDirective = isAccDirective( secondParm, true );\n               thirdParm       = this.fakegatoConfig[ constants.PPM ]      || \"0\";\n               thirdParmDirective = isAccDirective( thirdParm, true );\n\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n               secondParmValue = ( this.cmd4Storage.testStoredValueForIndex( secondParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      secondParmValue : this.cmd4Storage.getStoredValueForIndex( secondParmDirective.accTypeEnumIndex );\n               thirdParmValue = ( this.cmd4Storage.testStoredValueForIndex( thirdParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      thirdParmValue : this.cmd4Storage.getStoredValueForIndex( thirdParmDirective.accTypeEnumIndex );\n\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.TEMP }:${ firstParmValue } ${constants.HUMIDITY }:${ secondParmValue } ${ constants.PPM }:${ thirdParmValue }` );\n               // Eve Room ( TempSensor, HumiditySensor and AirQuality Services )\n               this.loggingService.addEntry(\n                  { [ constants.TIME ]     : moment( ).unix( ),\n                    [ constants.TEMP ]     : firstParmValue,\n                    [ constants.HUMIDITY ] : secondParmValue,\n                    [ constants.PPM ]      : thirdParmValue\n                  });\n               break;\n            }\n            case constants.FAKEGATO_TYPE_WEATHER:\n            {\n               firstParm       = this.fakegatoConfig[ constants.TEMP ]     || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n               secondParm      = this.fakegatoConfig[ constants.PRESSURE ] || \"0\";\n               secondParmDirective = isAccDirective( secondParm, true );\n               thirdParm       = this.fakegatoConfig[ constants.HUMIDITY ] || \"0\";\n               thirdParmDirective = isAccDirective( thirdParm, true );\n\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n               secondParmValue = ( this.cmd4Storage.testStoredValueForIndex( secondParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      secondParmValue : this.cmd4Storage.getStoredValueForIndex( secondParmDirective.accTypeEnumIndex );\n               thirdParmValue = ( this.cmd4Storage.testStoredValueForIndex( thirdParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      thirdParmValue : this.cmd4Storage.getStoredValueForIndex( thirdParmDirective.accTypeEnumIndex );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.TEMP }: ${ firstParmValue } ${ constants.PRESSURE }: ${ secondParmValue } ${ constants.HUMIDITY }: ${ thirdParmValue }` );\n\n               // Eve Weather ( TempSensor Service )\n               this.loggingService.addEntry(\n                  { [ constants.TIME ]     : moment( ).unix( ),\n                    [ constants.TEMP ]     : firstParmValue,\n                    [ constants.PRESSURE ] : secondParmValue,\n                    [ constants.HUMIDITY ] : thirdParmValue\n                  });\n               break;\n            }\n            case constants.FAKEGATO_TYPE_DOOR:\n            {\n               firstParm   = this.fakegatoConfig[ constants.STATUS ] || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.STATUS } status: ${ firstParmValue }` );\n\n               this.loggingService.addEntry(\n                  { [ constants.TIME ]   : moment( ).unix( ),\n                    [ constants.STATUS ] : firstParmValue\n                  });\n               break;\n            }\n            case constants.FAKEGATO_TYPE_MOTION:\n            {\n               firstParm   = this.fakegatoConfig[ constants.STATUS ] || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.STATUS }: ${ firstParmValue }` );\n\n               this.loggingService.addEntry(\n                  { [ constants.TIME ]   : moment( ).unix( ),\n                    [ constants.STATUS ] : firstParmValue\n                  });\n               break;\n            }\n            case constants.FAKEGATO_TYPE_THERMO:\n            {\n               firstParm       = this.fakegatoConfig[ constants.CURRENTTEMP ]   || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n               secondParm      = this.fakegatoConfig[ constants.SETTEMP ]       || \"0\";\n               secondParmDirective = isAccDirective( secondParm, true );\n               thirdParm       = this.fakegatoConfig[ constants.VALVEPOSITION ] || \"0\";\n               thirdParmDirective = isAccDirective( thirdParm, true );\n\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n               secondParmValue = ( this.cmd4Storage.testStoredValueForIndex( secondParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      secondParmValue : this.cmd4Storage.getStoredValueForIndex( secondParmDirective.accTypeEnumIndex );\n               thirdParmValue = ( this.cmd4Storage.testStoredValueForIndex( thirdParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      thirdParmValue : this.cmd4Storage.getStoredValueForIndex( thirdParmDirective.accTypeEnumIndex );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.CURRENTTEMP }: ${ firstParmValue } ${ constants.SETTEMP }:${ secondParmValue } ${constants.VALVEPOSITION }:${ thirdParmValue } ` );\n\n               // Eve Thermo ( Thermostat service )\n               this.loggingService.addEntry(\n                  { [ constants.TIME ]          : moment( ).unix( ),\n                    [ constants.CURRENTTEMP ]   : firstParmValue,\n                    [ constants.SETTEMP ]       : secondParmValue,\n                    [ constants.VALVEPOSITION ] : thirdParmValue\n                  });\n               break;\n            }\n            case constants.FAKEGATO_TYPE_AQUA:\n            {\n               firstParm       = this.fakegatoConfig[ constants.STATUS ]      || \"0\";\n               firstParmDirective = isAccDirective( firstParm, true );\n               secondParm      = this.fakegatoConfig[ constants.WATERAMOUNT ] || \"0\";\n               secondParmDirective = isAccDirective( secondParm, true );\n\n               firstParmValue = ( this.cmd4Storage.testStoredValueForIndex( firstParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      firstParmValue : this.cmd4Storage.getStoredValueForIndex( firstParmDirective.accTypeEnumIndex );\n               secondParmValue = ( this.cmd4Storage.testStoredValueForIndex( secondParmDirective.accTypeEnumIndex ) == undefined ) ?\n                      secondParmValue : this.cmd4Storage.getStoredValueForIndex( secondParmDirective.accTypeEnumIndex );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Logging ${ constants.STATUS }: ${ firstParmValue } ${ constants.WATERAMOUNT }: ${ secondParmValue }` );\n\n               // Eve Aqua ( Valve service set to Irrigation Type )\n               this.LoggingService.addEntry(\n                  { [ constants.TIME ]        : moment( ).unix( ),\n                    [ constants.STATUS ]      : firstParmValue,\n                    [ constants.WATERAMOUNT ] : secondParmValue\n                  });\n               break;\n            }\n         }\n      }\n   }\n\n   setupAccessoryFakeGatoService( fakegatoConfig )\n   {\n      if ( fakegatoConfig == undefined )\n         return;\n\n      for ( let key in fakegatoConfig )\n      {\n         let value = fakegatoConfig[ key ];\n\n         let rcDirective = isCmd4Directive( key, false );\n         if ( rcDirective == null )\n         {\n            rcDirective = isCmd4Directive( key, true );\n            if ( rcDirective != null )\n            {\n               // warn now\n               this.log.warn( `The config.json FakeGato key: ${ key } is Capitalized. It should be: ${ rcDirective.key }. In the near future this will be an error for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n               // create the proper lower case value\n               fakegatoConfig[ rcDirective.key ] = value;\n               // delete the upper case value\n               fakegatoConfig[ key ].remove();\n\n               //set the key\n               key = rcDirective.key;\n            }\n         }\n\n         switch ( key )\n         {\n            case constants.EVE:\n               this.eve = fakegatoConfig[ key ];\n               switch( value )\n               {\n                   case constants.FAKEGATO_TYPE_ENERGY:\n                   case constants.FAKEGATO_TYPE_ROOM:\n                   case constants.FAKEGATO_TYPE_WEATHER:\n                   case constants.FAKEGATO_TYPE_DOOR:\n                   case constants.FAKEGATO_TYPE_MOTION:\n                   case constants.FAKEGATO_TYPE_THERMO:\n                   case constants.FAKEGATO_TYPE_AQUA:\n                      break;\n                   default:\n                      throw new Error( `Invalid fakegato eve type: \"${ value }\". It must be one of ( ${ constants.FAKEGATO_TYPE_ENERGY }, ${ constants.FAKEGATO_TYPE_ROOM }, ${ constants.FAKEGATO_TYPE_WEATHER }, ${ constants.FAKEGATO_TYPE_DOOR }, ${ constants.FAKEGATO_TYPE_MOTION }, ${ constants.FAKEGATO_TYPE_THERMO }, ${ constants.FAKEGATO_TYPE_AQUA } ). Check the Cmd4 README at: \"https://github.com/simont77/fakegato-history\".` );\n                }\n                break;\n            case constants.STORAGE:\n                this.storage = fakegatoConfig[ key ];\n                break;\n            case constants.STORAGEPATH:\n                this.storagePath = fakegatoConfig[ key ];\n                break;\n            case constants.KEYPATH:\n                this.keyPath = fakegatoConfig[ key ];\n                break;\n            case constants.FOLDER:\n                this.Folder = fakegatoConfig[ key ];\n                break;\n            case constants.STATUS:\n            case constants.TEMP:\n            case constants.SETTEMP:\n            case constants.HUMIDITY:\n            case constants.PPM:\n            case constants.POWER:\n            case constants.PRESSURE:\n            case constants.CURRENTTEMP:\n            case constants.VALVEPOSITION:\n            {\n               if ( value != \"0\" )\n               {\n                  let rcDirective = isAccDirective( value, false );\n                  if ( rcDirective.accTypeEnumIndex == null )\n                  {\n                     rcDirective = isAccDirective( value, true );\n                     if ( rcDirective.accTypeEnumIndex == null )\n                        throw new Error( `Invalid characteristic \"${ value }\" for fakegato to log of \"${ key }\".` );\n\n                    this.log.warn( `The config.json FakeGato characteristic: ${ value } is Capitalized it should be: ${ rcDirective.type }.  In the near future this will be an Error so that Cmd4 can use homebridge-ui.\\nTo remove this Warning, Please fix your config.json.` );\n                  }\n\n                  // Make sure the characteristic is being polled (Changing) so I do\n                  // not get any more tickets.\n                  if ( this.queue.isCharacteristicPolled( rcDirective.accTypeEnumIndex, this.queue, this ) == false )\n                     throw new Error(`Characteristic: \"${ value }\" for fakegato to log of \"${ key }\" is not being polled.\\nHistory can not be updated continiously.` );\n               }\n\n               break;\n            }\n            default:\n               throw new Error( `Invalid fakegato key: \"${ key }\" in json.config for: \"${ this.displayName }\".` );\n         }\n      }\n\n      // Optional\n      if ( this.storage != undefined )\n      {\n         if ( this.storage == constants.FS )\n         {\n            this.loggingService = new FakeGatoHistoryService\n            (\n               this.eve,\n               this.platform,\n               { [ constants.STORAGE ] : constants.FS,\n                 [ constants.PATH ]   : this.storagePath\n               }\n            );\n            this.services.push( this.loggingService );\n\n         } else if ( this.storage == constants.GOOGLE_DRIVE )\n         {\n            this.loggingService = new FakeGatoHistoryService\n            (\n               this.eve,\n               this.platform,\n               { [ constants.STORAGE ] : constants.GOOGLE_DRIVE,\n                 [ constants.FOLDER ]  : this.folder,\n                 [ constants.KEYPATH ] : this.keyPath }\n            );\n            this.services.push( this.loggingService );\n         } else\n         {\n            this.log.warn( chalk.yellow( \"WARNING\" ) + `: Cmd4 Unknown accessory config.storage:{ this.storage } Expected:${ constants.FS } or ${ constants.GOOGLEDRIVE } for: ${ this.displayName }` );\n         }\n      }\n\n      if ( this.loggingService )\n      {\n         if ( ! this.polling )\n         {\n            this.log.warn( `config.storage: ${ this.storage } for: ${ this.displayName } set but polling is not enabled.` );\n            this.log.warn( `      History will not be updated continiously.` );\n         }\n      }\n   }\n\n   validateStateCmd( state_cmd )\n   {\n      if ( typeof state_cmd != \"string\" )\n         throw new Error( `No state_cmd for: \"${ this.displayName }\".` );\n\n      // This was messy, did not like spaces. let the user be the judge of it.\n      return true;\n   }\n\n   // We are looking for things like Volume: <value>, Name: <value>, Mute: <value>\n   parseKeyForCharacteristics( key, value, parseConfigShouldUseCharacteristicValues )\n   {\n      // fix the their scripts, fix it here.\n      let rcDirective = isAccDirective( key, false );\n      if ( rcDirective.accTypeEnumIndex == null )\n      {\n         rcDirective = isAccDirective( key, true );\n         if ( rcDirective.accTypeEnumIndex == null )\n            throw new Error( `OOPS: \"${ key }\" not found for parsing characteristics in: \"${ this.displayName }\".` );\n\n         this.log.warn( `The config.json characteristic key: ${ key } is Capitalized.  It should be: ${ rcDirective.type }. In the near future this will be an error for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n      }\n\n\n      let characteristicString = rcDirective.type;\n      let accTypeEnumIndex = rcDirective.accTypeEnumIndex;\n\n      if ( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].deprecated == true )\n      {\n         this.log.warn( `The config.json characteristic: ${ characteristicString } is deprecated. It will be ignored.\\nTo remove this Warning, Please fix your config.json.` );\n         return;\n      }\n\n      // Do not update the stored values as it is being restored from cache\n      if ( parseConfigShouldUseCharacteristicValues == false )\n         return;\n\n      if ( Object.keys( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].validValues ).length > 0 )\n      {\n         // Even if outputConsts is not set, just in case, transpose it anyway.\n         value = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, value ) ;\n      }\n\n\n      // Return the appropriate type, by seeing what it is defined as in Homebridge,\n      let properValue = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value );\n      if ( properValue == undefined )\n      {\n         // If the value is not convertable, just return it.\n         this.log.warn( `parseKeyForCharacterisitcs: ${ this.displayName } ` + chalk.red( `Cannot convert value: ${ value } to ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].props.format } for ${ characteristicString }`  ) );\n\n         return;\n      }\n\n\n      //this.log.debug(\"Setting %s to %s\", characteristicString, properValue );\n      this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, properValue );\n   }\n\n   processRequires( requiresArray )\n   {\n      if ( ! Array.isArray ( requiresArray ) )\n         throw new Error( `requires must be an array of { \"require\": \"some requires string\" }` );\n\n      // Iterate over the groups of key/value constants in the array.\n      for ( let argIndex = 0; argIndex < requiresArray.length; argIndex++ )\n      {\n         let argEntry = requiresArray[ argIndex ];\n\n         if ( argEntry.require == undefined )\n            throw new Error( `Requires definition at index: \"${ argIndex }\" has no \"require\":\"SomeRequire\"` );\n\n         let required = argEntry.require;\n\n         if ( typeof required != \"string\" )\n            throw new Error( `Requires definition: \"${ required }\"  must be a string.` );\n         required = this.replaceConstantsInString( required );\n\n         if ( settings.cmd4Dbg ) this.log.debug( `Requiring ${ required }` );\n\n         require( required );\n      }\n   }\n\n   processConstants( constantsArgArray )\n   {\n      if ( ! Array.isArray ( constantsArgArray ) )\n         throw new Error( `Constants must be an array of { \"key\": \"\\${SomeKey}\", \"value\": \"some replacement string\" }` );\n\n\n      // Iterate over the groups of key/value constants in the array.\n      for ( let argIndex = 0; argIndex < constantsArgArray.length; argIndex++ )\n      {\n         let argEntry = constantsArgArray[ argIndex ];\n\n         if ( argEntry.key == undefined )\n            throw new Error( `Constant definition at index: \"${ argIndex }\" has no \"key\":\"\\${SomeKey}\"` );\n\n         if ( argEntry.value == undefined )\n            throw new Error( `Constant definition at index: \"${ argIndex }\" has no \"value\":\"Some replacement string` );\n\n         let keyToAdd = argEntry.key;\n         let valueToAdd = argEntry.value;\n         if ( ! keyToAdd.startsWith( \"${\" ) )\n            throw new Error( `Constant definition for: \"${ keyToAdd }\" must start with \"\\${\" for clarity.` );\n\n         if ( ! keyToAdd.endsWith( \"}\" ) )\n            throw new Error( `Constant definition for: \"${ keyToAdd }\" must end with \"}\" for clarity.` );\n\n         // remove any leading and trailing single quotes\n         // so that using it for replacement will be easier.\n         valueToAdd.replace(/^'/, \"\")\n         valueToAdd.replace(/'$/, \"\")\n\n         // Do not check for duplicates. Linked accessories add the same\n         // ${IP} for example\n         this.listOfConstants[ keyToAdd ] = valueToAdd;\n      }\n   }\n\n   processVariables( variablesArgArray )\n   {\n      if ( ! Array.isArray ( variablesArgArray ) )\n         throw new Error( `Variables must be an array of { \"key\": \"\\${SomeKey}\", \"value\": \"some replacement string\" }` );\n\n\n      // Iterate over the groups of key/value constants in the array.\n      for ( let argIndex = 0; argIndex < variablesArgArray.length; argIndex++ )\n      {\n         let argEntry = variablesArgArray[ argIndex ];\n\n         if ( argEntry.key == undefined )\n            throw new Error( `Variable definition at index: \"${ argIndex }\" has no \"key\":\"\\${SomeKey}\"` );\n\n         if ( argEntry.value == undefined )\n            throw new Error( `Variable definition at index: \"${ argIndex }\" has no \"value\":\"Some replacement string` );\n\n         let keyToAdd = argEntry.key;\n         let valueToAdd = argEntry.value;\n         if ( ! keyToAdd.startsWith( \"${\" ) )\n            throw new Error( `Variable definition for: \"${ keyToAdd }\" must start with \"\\${\" for clarity.` );\n\n         if ( ! keyToAdd.endsWith( \"}\" ) )\n            throw new Error( `Variable definition for: \"${ keyToAdd }\" must end with \"}\" for clarity.` );\n\n         // remove any leading and trailing single quotes\n         // so that using it for replacement will be easier.\n         valueToAdd.replace(/^'/, \"\")\n         valueToAdd.replace(/'$/, \"\")\n\n         this.listOfVariables[ keyToAdd ] = valueToAdd;\n      }\n   }\n\n   accessoryTypeConfigToCmd4Accessories( config, parentInfo )\n   {\n      if ( ! config )\n         return undefined;\n\n      let that = this;\n\n      if ( Array.isArray ( config ) )\n      {\n         let accessories = config.map( ( accessoryConfig ) => { return new Cmd4Accessory( that.log, accessoryConfig, this.api, this.STORED_DATA_ARRAY, this ) } );\n\n         // Put the accessories into their correct collection array.\n         parentInfo.createdCmd4Accessories.push( ...accessories );\n\n         return accessories;\n      }\n\n      let accessory = new Cmd4Accessory( that.log, config, this.api, this.STORED_DATA_ARRAY, this );\n\n      // Put the accessory into its correct collection array.\n      parentInfo.createdCmd4Accessories.push( accessory );\n\n      return [ accessory ];\n   }\n\n   processURL( url )\n   {\n      if ( typeof url != \"string\" )\n         throw new Error( `url must be a string: \"${ url }\".` );\n\n      this.url = this.replaceConstantsInString( url );\n   }\n\n   replaceConstantsInString( orig )\n   {\n      let finalAns = orig;\n\n      for ( let key in this.listOfConstants )\n      {\n          let replacementConstant = this.listOfConstants[ key ];\n          finalAns = finalAns.replace( key, replacementConstant );\n      }\n      return finalAns;\n   }\n\n   parseConfig( config, parseConfigShouldUseCharacteristicValues  )\n   {\n      let cmd4Mode = null;\n      for ( let key in config )\n      {\n         let value = config[ key ];\n\n         // warn now - Cmd4 Directives\n         let rcDirective = isCmd4Directive( key, false );\n         if ( rcDirective == null )\n         {\n            rcDirective = isCmd4Directive( key, true );\n            if ( rcDirective != null )\n            {\n               this.log.warn( `The config.json Cmd4 Directive: ${ key } is Capitalized.  It should be: ${ rcDirective.key }. In the near future this will be an error for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n               // create the proper lower case value\n               config[ rcDirective.key ] = value;\n               // delete the upper case value\n               delete config[ key ];\n\n               //set the key\n               key = rcDirective.key;\n            }\n         }\n         // Not finding the key is not an error as it could be a Characteristic\n\n         switch ( key )\n         {\n            case constants.TYPE:\n            {\n               this.type = value;\n               let rcValue = isDevDirective( value, false );\n               if ( rcValue.devEnumIndex == null )\n               {\n                  rcValue = isDevDirective( value, true );\n                  if ( rcValue.devEnumIndex == null )\n                    throw new Error( `Unknown device type: \"${ value }\" given in: \"${ this.displayName }\".` );\n\n                  // warn now\n                  this.log.warn( `The config.json Cmd4 device type: ${ value } is lowerCase.  It should be: ${ rcValue.deviceName }. In the near future this will be an error for homebridge-UI integration.\\nTo remove this Warning, Please fix your config.json.` );\n\n                  this.type = rcValue.deviceName;\n               }\n               this.typeIndex = rcValue.devEnumIndex;\n\n               if ( CMD4_DEVICE_TYPE_ENUM.properties[ this.typeIndex ].deprecated == true )\n                  throw new Error( `Error: device type: \"${ this.type }\" is now deprecated in Homebridge.` );\n\n               break;\n            }\n            case constants.SUBTYPE:\n               this.subType = value;\n\n               break;\n            case constants.MODEL:\n               // createAccessorysInformationService uses these\n               // to add to existing information service, when defined\n               this.model = value;\n\n               break;\n            case constants.MANUFACTURER:\n               // createAccessorysInformationService uses these\n               // to add to existing information service, when defined\n               this.manufacturer = value;\n\n               break;\n            case constants.SERIALNUMBER:\n               // createAccessorysInformationService uses these\n               // to add to existing information service, when defined\n               this.serialNumber = value;\n\n               break;\n            case constants.DISPLAYNAME:\n               // DisplayName is not a characteristic but used as a parm when\n               // creating the Service.  This has already been parsed, but\n               // here so that parseConfig passes.\n               this.displayName = value;\n\n               break;\n            case constants.UUID:\n               // For those who define there own UUID\n               this.uuid = value;\n\n               break;\n           case constants.ACCESSORY:\n               // For 8.0 this is no longer supported.  Homebridge has deprecated\n               // the template and only wants Platform templates which makes\n               // it easier for Cmd4 to support homebridge-ui as well..\n               throw new Error( `Accessory: has been deprecated by homebridge. Only Platform confgurations are supported by Cmd4 >= 8.0 for: \"${ this.displayName }\".` );\n           case constants.CATEGORY:\n               // For those who define there own Category\n               // Uppercase the category to be nice. Why do I know\n               // this will come back to bite me.\n               this.category = this.api.hap.Categories[ String( value ).toUpperCase( ) ];\n\n               if ( ! this.category )\n                  throw new Error( `Category specified: \"${ value }\" is not a valid homebridge category for: \"${ this.displayName }\".` );\n\n               break;\n            case constants.PUBLISHEXTERNALLY:\n               // The user can make the accessory be published externally.\n               this.publishExternally = value;\n\n               break;\n            case constants.PROPS:\n               // Allow characteristic property changes.\n               this.props = value;\n\n               break;\n            case constants.OUTPUTCONSTANTS:\n               // Define if we should ouput constant strings\n               this.outputConstants = value;\n\n               break;\n            case constants.STATUSMSG:\n               // During state change, display a message or not\n               if ( value === true )\n                  this.statusMsg = \"TRUE\";\n                else\n                  this.statusMsg = \"FALSE\";\n\n               break;\n            case constants.QUEUE:\n            {\n               let queue = queueExists( value );\n               if ( queue == undefined )\n                  throw new Error( `\"QueueType\" must be defined first for queue \"${ value }\" in: \"${ this.displayName }\"` );\n\n               this.queue = queue;\n\n               break;\n            }\n            case constants.TIMEOUT:\n               // Timers are in milliseconds. A low value can result in failure to get/set values\n               this.timeout = parseInt( value, 10 );\n               if ( this.timeout < 500 )\n               {\n                  this.log.warn( `Timeout for: ${ this.displayName } is in milliseconds. A value of \"${ this.timeout }\" seems pretty low` );\n               }\n\n               break;\n            case constants.POLLING:\n               // Do not parse it yet as characteristics must be set first.\n               this.polling = value;\n\n               break;\n            case constants.INTERVAL:\n               // Intervals are in seconds\n               this.interval = parseInt( value, 10 ) * 1000;\n\n               break;\n            case constants.STATECHANGERESPONSETIME:\n               // respnse time is in seconds\n               this.stateChangeResponseTime = value * 1000;\n\n               break;\n            case constants.STATE_CMD_PREFIX:\n               // Not 100% sure why this would be needed, but\n               // added anyway since we have a suffix\n               this.state_cmd_prefix = value;\n\n               break;\n            case constants.STATE_CMD_SUFFIX:\n               // This gets added after any Get/Set <value>\n               // We replace any constants already defined\n               this.state_cmd_suffix = value;\n\n               break;\n            case constants.STATE_CMD:\n               // What this plugin is all about\n               this.state_cmd = value;\n\n               break;\n            case constants.FAKEGATO:\n               // Do not parse it yet as characteristics must be set first.\n               this.fakegatoConfig = value;\n\n               break;\n            case constants.REQUIRES:\n               this.processRequires( value );\n\n               break;\n            case constants.CONSTANTS:\n               this.log.warn( `Warning: ${ key } will soon been deprecated at the Accessory level. Please move it to where \"Platform: \"Cmd4\" is located in your config.json.` );\n               this.log.warn( `This message will disappear when you have done so.` );\n\n               this.processConstants( value );\n\n               break;\n            case constants.VARIABLES:\n               this.processVariables( value );\n\n               break;\n            case constants.LINKEDTYPES:\n               if ( settings.cmd4Dbg ) this.log.debug(  `parseConfig. Found linked Accessories` );\n               this.linkedAccessoriesConfig = value;\n\n               break;\n            case constants.ACCESSORIES:\n               if ( settings.cmd4Dbg ) this.log.debug( `parseConfig. Found Accessories` );\n               this.accessoriesConfig = value;\n\n               break;\n            case constants.URL:\n               this.processURL( value );\n\n               break;\n            case constants.ALLOWTLV8:\n               this.log.warn( `Warning: ${ key } will soon been deprecated at the Accessory level. Please move it to where \"Platform: \"Cmd4\" is located.` );\n               this.log.warn( `This message will disappear when you have done so.` );\n\n               this.allowTLV8 = value;\n               break;\n            default:\n            {\n               this.parseKeyForCharacteristics( key, value, parseConfigShouldUseCharacteristicValues );\n            }\n         }\n      }\n\n      if ( cmd4Mode != null && this.polling )\n      {\n         if ( cmd4Mode == \"Demo\" )\n            throw new Error(\"Demo mode is achieved when there are no polling entries in your config.json\");\n\n         this.log.warn( `Cmd4 has been simplified and optimized as per: https://git.io/JtMGR.` );\n         this.log.warn( `To remove this message, just remove \"Cmd4_Mode\" from your config.json` );\n      }\n\n      // A device type must be specified\n      if ( this.typeIndex == undefined || this.typeIndex < 0 )\n          throw new Error( `Unknown device type: \"${ this.type }\" given in: \"${ this.displayName }\".` );\n\n      // Create a subType to delimit services with multiple accessories of\n      // the same type and possibly the same accessory.name.\n      this.subType = this.subType || this.displayName;\n\n      // UUID must be defined or created.\n      this.uuid = this.uuid || getAccessoryUUID( config, this.api.hap.uuid );\n\n      // Solve some issues people have encounterred who\n      // have had problems with shell completion which is\n      // only available from shell expansion.\n\n      // State_cmd is only required when polling is enabled.\n      if ( this.polling )\n      {\n         // throws its own exceptio if it fails\n         this.validateStateCmd( this.state_cmd );\n      } else\n      {\n         // Added accessories like input have no polled configuristics and therefore don't\n         // deserve this message\n         if ( this.level != 1)\n            this.log.info( chalk.blue( `Cmd4 is running in Demo Mode for ${ this.displayName }` ) );\n      }\n\n      // Handle seperation of strings of state_cmd for a prefix\n      if ( this.state_cmd_prefix )\n         this.state_cmd_prefix = this.state_cmd_prefix + \" \";\n      else\n         this.state_cmd_prefix = \"\";\n\n      // Handle seperation of strings of state_cmd for a suffix\n      if ( this.state_cmd_suffix )\n      {\n         if ( typeof this.state_cmd_suffix != \"string\" )\n            throw new Error( `state_cmd_suffix must be a string: \"${ this.state_cmd_suffix }\".` );\n\n         this.state_cmd_suffix = \" \" + this.replaceConstantsInString( this.state_cmd_suffix );\n      } else\n      {\n         this.state_cmd_suffix = \"\";\n      }\n\n      if ( this.typeIndex == CMD4_DEVICE_TYPE_ENUM.Television )\n      {\n          if ( this.CMD4 == constants.PLATFORM &&  ( ! this.publishExternally || ! this.category ) ||\n               this.CMD4 == constants.STANDALONE )\n          {\n               this.log.warn( `Televisions should be Platform Accessories with \"${ constants.PUBLISHEXTERNALLY }\": true, \"${ constants.CATEGORY }\": \"TELEVISION\"` );\n          }\n          if ( this.CMD4 == constants.PLATFORM && ! this.publishExternally && ( numberOfTVsPerBridge += 1 ) > 1 )\n          {\n             this.log.warn( `Only one unpublished TV is allowed per bridge` );\n          }\n      }\n\n      // Convert polling to an Array now so that it does not need to be done multiple times later.\n      let pollingType = trueTypeOf( this.polling );\n\n      switch( pollingType )\n      {\n         case null:\n         case undefined:\n            if ( settings.cmd4Dbg ) this.log.debug( `No polling configured.` );\n            return;\n         case Boolean:\n            if ( settings.cmd4Dbg ) this.log.debug( `Polling config is Default Polling. Nothing to check for unset polling characteristics` );\n            return;\n         case String:\n            throw new Error( `Unknown type for Polling \"${ this.polling }\" given in: \"${ this.displayName }\".` );\n         case Array:\n            break;\n         case Object:\n            this.log.warn( `Polling config for ${ this.displayName } should be an array.` );\n            this.log.warn( `Converting to array, but this may be an error in the future.` );\n            // Convert the object to an Array and try again.\n            this.polling = [ this.polling ];\n            return;\n         default:\n            throw new Error( `Do not know how to handle polling type of: \"${ pollingType }\" for: \"${ this.displayName }\".` );\n      }\n\n      // We need to check for removed characteristic Strings in the config\n      for ( let accTypeEnumIndex = 0; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex ++ )\n      {\n         let storedValue = this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex );\n         if ( storedValue != null )\n         {\n\n            // connect the accTypeEnumIndex to its characteristic string\n            let lcCharacteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( accTypeEnumIndex );\n            let ucCharacteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( accTypeEnumIndex );\n            if ( config[ lcCharacteristicString  ] != undefined ||\n                 config[ ucCharacteristicString  ] != undefined )\n            {\n               continue;\n            } else\n            {\n               // There was a previously stored characteristic, if it was not initialized\n               this.log.warn( `Removing previously configured characteristic: ${ lcCharacteristicString }` );\n               this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, null );\n            }\n         }\n      }\n   }\n\n   // HV may change with polling characteristics\n   lookupAccessoryHVForPollingCharacteristic( accessory, accTypeEnumIndex )\n   {\n      // Heirarchy is first the default\n      let timeout = accessory.hV.timeout;\n      let interval = accessory.hV.interval;\n      let stateChangeResponseTime = accessory.hV.stateChangeResponseTime;\n\n      // For testing purposes where there is no queue\n      let queueName = null;\n      if ( accessory.queue )\n          queueName = accessory.queue.queueName;\n\n\n      let pollingEntry = accessory.listOfPollingCharacteristics[ accTypeEnumIndex ];\n\n      // There should only be one, if any\n      if ( pollingEntry != undefined )\n      {\n         if ( pollingEntry.timeout )\n            timeout = pollingEntry.timeout;\n         if ( pollingEntry.interval )\n            interval = pollingEntry.interval;\n         if ( pollingEntry.stateChangeResponseTime )\n            stateChangeResponseTime = pollingEntry.stateChangeResponseTime;\n         if ( pollingEntry.queueName )\n            queueName = pollingEntry.queueName;\n      }\n\n      return { [ constants.TIMEOUT_lv ]: timeout, [ constants.INTERVAL_lv ]: interval, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.QUEUE_NAME_lv ]: queueName };\n\n   }\n\n   getDevicesRelatedTargetAccTypeEnumIndex( accCurrentEnumIndex )\n   {\n      // Get the Devices required characteristics\n      let requiredCharacteristicsArray = CMD4_DEVICE_TYPE_ENUM.properties[ this.typeIndex ].requiredCharacteristics;\n\n      if ( requiredCharacteristicsArray.length  == 0 )\n         return null;\n\n      let found = requiredCharacteristicsArray.find( entry => entry.type == accCurrentEnumIndex );\n\n      if ( found && found.relatedTargetAccTypeEnumArray.length > 0  )\n         return found.relatedTargetAccTypeEnumArray[ 0 ];\n\n      return null;\n\n      // For Optional, the *Target* characteristic does not have to be\n      // defined with the *Current* characteristic as *Current* is\n      // optional, so may be *Target*\n\n   }\n   getDevicesRelatedCurrentAccTypeEnumIndex( accTargetEnumIndex )\n   {\n      // Get the Devices required characteristics\n      let requiredCharacteristicsArray = CMD4_DEVICE_TYPE_ENUM.properties[ this.typeIndex ].requiredCharacteristics;\n\n      if ( requiredCharacteristicsArray.length  == 0 )\n         return null;\n\n      let found = requiredCharacteristicsArray.find( entry => entry.type == accTargetEnumIndex );\n\n      if ( found && found.relatedCurrentAccTypeEnumArray.length > 0 )\n         return found.relatedCurrentAccTypeEnumArray[ 0 ];\n\n      return null;\n   }\n\n   determineCharacteristicsToPollForAccessory( accessory  )\n   {\n      // Get the values based on their hierarchy.\n      let timeout = accessory.hV.timeout;\n      let interval = accessory.hV.interval;\n      let stateChangeResponseTime = accessory.hV.stateChangeResponseTime;\n\n      // We need to create the listOfPollingCharacteristics, even in Demo mode because\n      // this list is also used to determine if the related characteristic should be set\n      // which happens in the Demo mode without polling.\n      if ( typeof accessory.polling == \"object\" )\n      {\n         if ( settings.cmd4Dbg ) this.log.debug( `Characteristic polling for: ${ accessory.displayName }` );\n         accessory.polling.forEach( ( jsonPollingConfig ) =>\n         {\n            // Characteristic polling is a json type\n            // let jsonPollingConfig = accessory.polling[ jsonIndex ];\n\n\n            let value;\n            let accTypeEnumIndex = -1;\n\n            // All this code disappears in the next major release.\n            for ( let key in jsonPollingConfig )\n            {\n               value = jsonPollingConfig[ key ];\n\n               let rcDirective = isCmd4Directive( key );\n               if ( rcDirective == null )\n               {\n                  rcDirective = isCmd4Directive( key, true );\n                  if ( rcDirective != null )\n                  {\n                     this.log.warn( `The config.json Cmd4 Polling Directive: ${ key } is Capitalized.  It should be: ${ rcDirective.key }. In the near future this will be an error for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n                     // create the proper lower case value\n                     jsonPollingConfig[ rcDirective.key ] = value;\n                     // delete the upper case value\n                     delete jsonPollingConfig[ key ];\n\n                     //set the key\n                     key = rcDirective.key;\n                  }\n               }\n               // Not finding the key is not an error as it could be a Characteristic\n\n               switch ( key )\n               {\n                  case constants.TIMEOUT:\n                     // Timers are in milliseconds. A low value can result in failure to get/set values\n                     timeout = parseInt( value, 10 );\n                     if ( timeout < 500 )\n                        this.log.warn( `Timeout for: ${ accessory.displayName } is in milliseconds. A value of: ${ timeout } seems pretty low.` );\n\n                     break;\n                  case constants.INTERVAL:\n                     // Intervals are in seconds\n                     interval = parseInt( value, 10 ) * 1000;\n                     break;\n                  case constants.STATECHANGERESPONSETIME:\n                     // respnse time is in seconds\n                     stateChangeResponseTime = value * 1000;\n\n                     break;\n                  case constants.CHARACTERISTIC:\n                  {\n                     // The key must be a characteristic property\n                     // but first check if one has already been defined as we can only handle one at a time.\n                     if ( accTypeEnumIndex != -1 )\n                        throw new Error( `For charateristic polling, you can only define one characteristic per array item.\\nCannot add \"${ key }\" as \"${ value }\" is already defined for: ${ accessory.displayName } ${accTypeEnumIndex}` );\n\n                     rcDirective = isAccDirective( value, false );\n                     if ( rcDirective.accTypeEnumIndex == null )\n                     {\n                        rcDirective = isAccDirective( value, true );\n                        if ( rcDirective.accTypeEnumIndex == null )\n                           throw new Error( `No such polling characteristic: \"${ value }\" for: \"${ this.displayName }\".` );\n\n                        this.log.warn( `1. The config.json Polling characteristic: ${ value } is Capitalized it should be: ${ rcDirective.type }.  In the near future this will be an Error so that Cmd4 can use homebridge-ui.\\nTo remove this Warning, Please fix your config.json.` );\n                     }\n                     accTypeEnumIndex = rcDirective.accTypeEnumIndex;\n\n                     // We can do this as this is a new way to do things.\n                     if ( this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex ) == undefined )\n                        throw new Error( `CCC Polling for: \"${ value }\" requested, but characteristic is not in your config.json file for: \"${ this.displayName }\".` );\n\n                     break;\n                  }\n                  default: // Switching polling key but key is unknown\n                  {\n\n                     throw new Error( `No such polling characteristic: \"${ key }\" for: \"${ accessory.displayName }\".` );\n\n                  }\n               }\n            }\n\n            // Everything now goes through the queue\n            if ( this.queue == null )\n            {\n               this.queue = addQueue( this.log, \"Q:\" + this.displayName, constants.QUEUETYPE_STANDARD, constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT );\n            }\n            // This has to be UC as it gets passed to the getValue cmd string\n            let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( accTypeEnumIndex );\n\n            if ( settings.cmd4Dbg ) this.log.debug( `Setting up accessory: ${ accessory.displayName } for polling of: ${ characteristicString } timeout: ${ timeout } interval: ${ interval } queueName: \"${ this.queue.queueName }\"` );\n\n            if ( timeout == undefined )\n               throw new Error( `determineCharacteristicsToPollForAccessory  Timeout is undefined ` );\n\n\n            let record = { [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.CHARACTERISTIC_STRING_lv ]: characteristicString, [ constants.INTERVAL_lv ]: interval, [ constants.TIMEOUT_lv ]: timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.QUEUE_NAME_lv ]: this.queue.queueName };\n\n            // Used to determine missing related characteristics and\n            // to determine if the related characteristic is enabled.\n            this.listOfPollingCharacteristics[ accTypeEnumIndex ] = record;\n\n            this.queue.addLowPriorityGetPolledQueueEntry(\n               record.accessory,\n               record.accTypeEnumIndex,\n               record.characteristicString,\n               record.interval,\n               record.timeout )\n\n\n         });\n      } else\n      {\n         // Even though polling might == undefined, we need to create a list of\n         // would be polled characteristics for \"Demo\" mode\n         // This list is also used to determine if the related characteristic should be set\n         // which happens in the Demo mode without polling.\n         if ( this.queue == null )\n         {\n            this.queue = addQueue( this.log, \"Q:\" + this.displayName, constants.QUEUETYPE_STANDARD, constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT );\n         }\n\n         // Make sure the defined characteristics will be polled\n         CMD4_DEVICE_TYPE_ENUM.properties[ accessory.typeIndex ].defaultPollingCharacteristics.forEach( defaultPollingAccTypeEnumIndex =>\n         {\n\n            // This has to be UC as it gets passed to the getValue cmd string\n            let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( defaultPollingAccTypeEnumIndex );\n\n            let record = { [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: defaultPollingAccTypeEnumIndex, [ constants.CHARACTERISTIC_STRING_lv ]: characteristicString, [ constants.INTERVAL_lv ]: interval, [ constants.TIMEOUT_lv ]: timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.QUEUE_NAME_lv ]: this.queue.queueName };\n\n            // Used to determine missing related characteristics and\n            // to determine if the related characteristic is also polled.\n            this.listOfPollingCharacteristics[ record.accTypeEnumIndex ] = record;\n\n            // Do not create the polling record or it will start polling\n            if ( accessory.polling == true )\n            {\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Adding ${ record.accessory.displayName } ${ CMD4_ACC_TYPE_ENUM.properties[ record.accTypeEnumIndex ].type }  record.timeout: ${ record.timeout } record.interval: ${ record.interval }  to Polled Queue ${ record.queueName }` );\n\n               this.queue.addLowPriorityGetPolledQueueEntry(\n                     record.accessory,\n                     record.accTypeEnumIndex,\n                     record.characteristicString,\n                     record.interval,\n                     record.timeout )\n            }\n         });\n      }\n\n      for( let accTypeEnumIndex in this.listOfPollingCharacteristics )\n      {\n         // Look to see if currently polled characteristics are like \"Current*\" and have\n         // a related characteristic like \"Target*\"\n         let relatedTargetAccTypeEnumIndex =\n            this.getDevicesRelatedTargetAccTypeEnumIndex(\n                    accTypeEnumIndex );\n\n         if ( relatedTargetAccTypeEnumIndex != null )\n         {\n            // Check that the characteristic like \"Target*\" is also requested to be polled\n            // We are in a \"Set\" but this applies to the \"Get\" for why we would need to\n            // set the relatedCurrentAccTypeEnumIndex Characteristic as well.\n\n            // - isRelated must be checked, because TemperatureSensors do\n            //   not have *Target* characteristics.\n            if ( this.listOfPollingCharacteristics[ relatedTargetAccTypeEnumIndex ] == undefined\n               )\n            {\n\n               let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( accTypeEnumIndex );\n               let relatedCharacteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( relatedTargetAccTypeEnumIndex );\n               this.log.warn( `Warning, With polling for \"${ characteristicString }\" requested, you also must do polling of \"${ relatedCharacteristicString }\" or things will not function properly` );\n            }\n         }\n      }\n   }\n\n}\n\n// Compare accessory's UUID with those already created for possible duplicates\nfunction checkAccessoryForDuplicateUUID( accessory, uuid )\n{\n   // check for UUID+subtype conflict\n   if ( settings.cmd4Dbg ) accessory.log.debug( `Checking ${ accessory.name } for Duplicate UUID: ${ accessory.uuid }` );\n\n   for ( let existingAccessory in accessory.createdCmd4Accessories )\n   {\n      if ( uuid == existingAccessory.uuid )\n      {\n         // This is the same check as what is in \n         // hap-nodejs/dist/lib/Accessory.js\n         if ( accessory.service.subtype == existingAccessory.service.subtype )\n         {\n            accessory.log.error( chalk.red( `Error` ) + `: Cannot add a bridged Accessory with the same UUID as another bridged Accessory: ${ getAccessoryName( existingAccessory ) }` );\n\n            if ( accessory.name == existingAccessory.name )\n               accessory.log.error( chalk.red( `Duplicate accessory names can cause this issue.` ) );\n\n            throw new Error( `It is wiser to define the second accessory in a different bridge.` );\n         }\n      }\n      // Check for duplicates in Added accessories.\n      if ( accessory.addedAccessories && accessory.LEVEL == 0 )\n      {\n         accessory.accessories.forEach( ( addedAccessory ) =>\n         {\n            checkAccessoryForDuplicateUUID( addedAccessory, uuid );\n         });\n      }\n\n      // Check for duplicates in Linked accessories.\n      if ( accessory.linkedAccessories && accessory.LEVEL == 0 )\n      {\n         accessory.linkedAccessories.forEach( ( linkedAccessory ) =>\n         {\n            checkAccessoryForDuplicateUUID( linkedAccessory, uuid );\n         });\n      }\n   }\n\n   if ( settings.cmd4Dbg ) accessory.log.debug( `No Duplicate UUID's for this Accessory - ` + chalk.green( `OK` ) + `. Using: ${ accessory.uuid }` );\n}\n\nexports.Cmd4Accessory = Cmd4Accessory;\n"
  },
  {
    "path": "Cmd4Platform.js",
    "content": "'use strict';\n\n// Cmd4 includes seperated out for Unit testing\nconst { getAccessoryName,\n        getAccessoryDisplayName } = require( \"./utils/getAccessoryNameFunctions\" );\nconst { parseAddQueueTypes } = require( \"./Cmd4PriorityPollingQueue\" );\n\n\n\n\nlet Logger = require( \"./utils/Logger\" );\nlet getAccessoryUUID = require( \"./utils/getAccessoryUUID\" );\nlet lcFirst = require( \"./utils/lcFirst\" );\nlet isNumeric = require( \"./utils/isNumeric\" );\nlet trueTypeOf = require( \"./utils/trueTypeOf\" );\n\n// Hierarchy variables\nlet HV = require( \"./utils/HV\" );\n\nlet createAccessorysInformationService = require( \"./utils/createAccessorysInformationService\" );\n\n// Pretty Colors\nvar chalk = require( \"chalk\" );\n\n// These would already be initialized by index.js\nlet CMD4_CHAR_TYPE_ENUMS = require( \"./lib/CMD4_CHAR_TYPE_ENUMS\" ).CMD4_CHAR_TYPE_ENUMS;\nlet CMD4_DEVICE_TYPE_ENUM = require( \"./lib/CMD4_DEVICE_TYPE_ENUM\" ).CMD4_DEVICE_TYPE_ENUM;\nlet CMD4_ACC_TYPE_ENUM = require( \"./lib/CMD4_ACC_TYPE_ENUM\" ).CMD4_ACC_TYPE_ENUM;\n\nlet CMD4_FORMAT_TYPE_ENUM = CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM;\nlet CMD4_UNITS_TYPE_ENUM = CMD4_CHAR_TYPE_ENUMS.CMD4_UNIT_TYPE_ENUM;\nlet CMD4_PERMS_TYPE_ENUM = CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM;\n\n// The Cmd4 Classes\nconst Cmd4Accessory = require( \"./Cmd4Accessory\" ).Cmd4Accessory;\n\n// Settings, Globals and Constants\nlet settings = require( \"./cmd4Settings\" );\nconst constants = require( \"./cmd4Constants\" );\n\n// Platform definition\nclass Cmd4Platform\n{\n   constructor( log, config, api )\n   {\n      // Unit testing passes their own logger with debug enabled/disabled\n      // replace with ours\n      if ( typeof log.setOutputEnabled === \"function\" )\n      {\n         this.log = log;\n\n         // Carry the debug flag from the platform\n         settings.cmd4Dbg = log.debugEnabled;\n      }\n      else\n      {\n         // By using our own Logger, we don't trigger others\n         this.log = new Logger( );\n\n         if ( config[ constants.DEBUG ]  == true ||\n              config[ \"Debug\" ]  == true ||\n              process.env.DEBUG == settings.PLATFORM_NAME )\n         {\n            settings.cmd4Dbg = true;\n         }\n      }\n\n      this.log.setDebugEnabled( settings.cmd4Dbg );\n\n      if ( settings.cmd4Dbg ) this.log.debug( chalk.blue( `Class Cmd4Platform` ) );\n\n      if ( config === undefined )\n         return;\n\n      this.config = config;\n      this.api = api;\n      this.Service = this.api.hap.Service;\n\n      // Pass along the trigger when creating the Cmd4Accessory.\n      // Note: The LEVEL starts at -1 as the first one gets incremented to Zero.\n      //\n      //       LEVEL 0 Accessories are Platform or Standalone Accessories.\n      //       LEVEL 1 Accessories are linked accessories.\n      //       LEVEL 2 Accessories are added Platform accessories coerced to\n      //               level 2 as a distinction. i.e. TelevisionSpeaker.\n\n      this.CMD4 = constants.PLATFORM;\n      this.LEVEL = -1;\n      this.toBeRestoredPlatforms = [ ];\n      this.createdCmd4Accessories = [ ];\n      this.createdCmd4Platforms = [ ];\n      this.globalConstants = null;\n\n      this.services = [ ];\n\n      // These would be queues of Characteristics to be polled or get/set via IOS.\n      settings.listOfCreatedPriorityQueues = { };\n\n      // Track the polling timers only so that unit testing can cancel them.\n      this.pollingTimers = [ ];\n\n      // Create the hierarhy variables\n      this.hV = new HV();\n\n      this.parseConfigForCmd4Directives( this.config );\n\n      // Update the namespace for stored variables\n      // like timeout, stateChangeResponseTime ... As it may require\n      // changes from parseConfig.\n      this.hV.update( this );\n\n      this.processNewCharacteristicDefinitions( );\n\n\n      // didFinishLaunching is only called after the\n      // registerPlatform completes.\n      api.on( \"didFinishLaunching\", ( ) =>\n      {\n         this.log.info( chalk.blue( \"Cmd4Platform didFinishLaunching\" ) );\n\n         this.discoverDevices( this.log );\n\n         // Any accessory not reachable must have been removed, find them\n         this.toBeRestoredPlatforms.forEach( ( accessory ) =>\n         {\n            if ( ! accessory.reachable )\n               this.removeAccessory( accessory );\n         });\n\n         // Let the Polling Begin\n         this.startPolling();\n\n      });\n   }\n\n   // Platforms do not use getServices. Good to know.\n   //getServices( )\n   //{\n   //   return this.services;\n   //}\n\n   // As Per HomeBridge:\n   // This function is invoked when homebridge restores cached accessories\n   // from disk at startup.  It should be used to setup event handlers\n   // for characteristics and update respective values.\n   //\n   // We do not handle restoring cached accessories ( Yet? ). Remove them\n   // as we regenerate everything.\n   configureAccessory( platformAccessory )\n   {\n      if ( platformAccessory )\n      {\n         if ( settings.cmd4Dbg ) this.log.debug( `Found cached accessory: ${ platformAccessory.displayName }` );\n         this.toBeRestoredPlatforms.push( platformAccessory );\n      }\n   }\n\n   removeAccessory( platformAccessory )\n   {\n      if ( ! platformAccessory )\n         return;\n\n      this.log.info( `Accessory ${ platformAccessory.displayName } will be removed.` );\n\n      this.api.unregisterPlatformAccessories(  settings.PLUGIN_NAME, settings.PLATFORM_NAME, [ platformAccessory ] );\n\n   }\n\n   // Hmmmm does not happen\n   //configurationRequestHandler( context, request, callback )\n   //{\n   //   this.log( chalk.red( `In ConfigRequestHandler context: ${ context }` ) );\n   //   switch( context.step )\n   //   {\n   //      case 5:\n   //         this.log( chalk.red( `Asked to remove` ) );\n   //         break;\n   //   }\n   //}\n\n   // Only parse those CMD4 directives we care about\n   parseConfigForCmd4Directives( config )\n   {\n      for ( let key in config )\n      {\n         let lcKey = lcFirst( key );\n         if ( key == \"UUID\" )\n         {\n            lcKey = \"uuid\";\n         } else\n         {\n            // warn now\n            if ( key.charAt( 0 ) === key.charAt( 0 ).toUpperCase( ) )\n            {\n               this.log.warn( `The config.json Platform key: ${ key } is Capitalized.  All keys in the near future will ALWAYS start with a lower case character for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n            }\n         }\n\n         let value = config[ key ];\n\n         switch ( lcKey )\n         {\n            case constants.TIMEOUT:\n               // Timers are in milliseconds. A low value can result in\n               // failure to get/set values\n               this.timeout = parseInt( value, 10 );\n               if ( this.timeout < 500 )\n                  this.log.warn( `Default Timeout is in milliseconds. A value of \"${ this.timeout }\" seems pretty low.` );\n\n               break;\n            case constants.INTERVAL:\n               // Intervals are in seconds\n               this.interval = parseInt( value, 10 ) * 1000;\n\n               break;\n            case constants.STATECHANGERESPONSETIME:\n               // respnse time is in seconds\n               this.stateChangeResponseTime = value * 1000;\n\n               break;\n            case constants.STATE_CMD_PREFIX:\n               // Not 100% sure why this would be needed, but\n               // added anyway since we have a suffix\n               this.state_cmd_prefix = value;\n\n               break;\n            case constants.STATE_CMD_SUFFIX:\n               // This gets added after any Get/Set <value>\n               this.state_cmd_suffix = value;\n\n               break;\n            case constants.STATE_CMD:\n               // What this plugin is all about\n               this.state_cmd = value;\n\n               break;\n            case constants.OUTPUTCONSTANTS:\n               this.outputConstants = value;\n\n               break;\n            case constants.STATUSMSG:\n              if ( value === false )\n                 this.statusMsg = \"FALSE\";\n\n               break;\n            case constants.QUEUETYPES:\n               parseAddQueueTypes( this.log, value );\n\n               break;\n            case constants.DEFINITIONS:\n               this.definitions = value;\n\n               break;\n            case constants.CONSTANTS:\n               // Save the constants defined globally so the accessory\n               // can parse it.\n               this.globalConstants = value;\n\n               break\n            case constants.PLATFORM:\n               // Noop\n\n               break;\n            case constants.ACCESSORIES:\n               // Noop\n\n               break;\n            default:\n               // This cannot be because all the Cmd4Accessory directives\n               // for Standalone would have to be added.\n               //this.log.error( chalk.red( `Error: Unknown Cmd4 Platform config option: \"${ key }\"` ) );\n               //process.exit( 448 ) ;\n         }\n      }\n   }\n   // The purpose here is not to duplicate what is in homebridge. Just to\n   // do a little checking to make sure that what is defined won't cause\n   // Cmd4 to balk.  It is okay if homebridge does though ;-)\n   processNewCharacteristicDefinitions( )\n   {\n      if ( this.definitions == undefined )\n         return;\n\n      if ( trueTypeOf( this.definitions ) != Array )\n         throw new Error( `${ constants.DEFINITIONS } is not a array.` );\n\n      this.definitions.forEach( ( definition, definitionIndex ) =>\n      {\n         if ( settings.cmd4Dbg ) this.log.debug( `Processing definition index: ${ definitionIndex }` );\n\n         if ( trueTypeOf( definition.type ) != String )\n            throw new Error( `definition.type at index: ${ definitionIndex } is not a String.` );\n\n         if ( trueTypeOf( definition.description ) != String )\n            throw new Error( `definition.description at index: ${ definitionIndex } is not a String.` );\n\n         if ( trueTypeOf( definition.props ) != Object )\n            throw new Error( `definition.props at index: ${ definitionIndex } is not an Object.` );\n\n         if ( trueTypeOf( definition.props.format ) != String )\n            throw new Error( `definition.props.format at index: ${ definitionIndex } is not a String.` );\n\n         // Need to check if format is correct\n         let formatIndex = CMD4_FORMAT_TYPE_ENUM.properties.indexOfEnum( i => i.type === definition.props.format );\n         if ( formatIndex < 0 )\n            throw new Error( `definition.props.format at index: ${ definitionIndex } is not a valid format.` );\n\n\n         if ( definition.props.units )\n         {\n            if ( trueTypeOf( definition.props.units ) != String )\n               throw new Error( `definition.props.units at index: ${ definitionIndex } is not a String.` );\n\n            // Need to check if units is correct\n            let unitsIndex = CMD4_UNITS_TYPE_ENUM.properties.indexOfEnum( i => i.type === definition.props.units );\n            if ( unitsIndex < 0 )\n               throw new Error( `definition.props.units at index: ${ definitionIndex } is not a valid unit.` );\n\n         }\n\n         if ( definition.props.maxValue &&\n              isNumeric( definition.props.maxValue ) != true )\n            throw new Error( `definition.props.maxValue at index: ${ definitionIndex } is not numeric.` );\n\n         if ( definition.props.minValue &&\n              ! Number.isFinite( definition.props.minValue ) )\n            throw new Error( `definition.props.minValue at index: ${ definitionIndex } is not finite.` );\n\n         if ( definition.props.minStep &&\n              isNumeric( definition.props.minStep ) != true )\n            throw new Error( `definition.props.minStep at index: ${ definitionIndex } is not numeric.` );\n\n         if ( trueTypeOf( definition.props.perms ) != Array )\n            throw new Error( `definition.props.perms at index: ${ definitionIndex } is not an Array.` );\n\n         if ( definition.props.perms.length == 0 )\n            throw new Error( `definition.props.perms at index: ${ definitionIndex } cannot be an empty Array.` );\n\n         definition.props.perms.forEach( ( perm ) =>\n         {\n            let permIndex = CMD4_PERMS_TYPE_ENUM.properties.indexOfEnum( i => i.type === perm );\n            if ( permIndex < 0 )\n               throw new Error( `definition.props.perms at index: ${ definitionIndex } ${ perm } is not a valid perm.` );\n\n         });\n\n         if ( definition.validValues )\n         {\n            if ( trueTypeOf( definition.validValues ) != Object )\n               throw new Error( `definition.validValues at index: ${ definitionIndex } is not an Object.` );\n         } else\n         {\n            definition.validValues = { };\n         }\n\n         CMD4_ACC_TYPE_ENUM.add( this.api, definition.type, definition.description, definition.props, definition.validValues );\n         if ( settings.cmd4Dbg ) this.log.debug( `Created definition type: \"${ definition.type }\".` );\n\n      });\n   }\n\n   // These would be platform accessories with/without linked accessories\n   discoverDevices( )\n   {\n      let platform;\n      let accessory;\n\n      // loop over the config.json devices and register each one if it has not\n      // already been registered.\n      this.config.accessories && this.config.accessories.forEach( ( device ) =>\n      {\n         if ( settings.cmd4Dbg ) this.log.debug( `Fetching config.json Platform accessories.` );\n         this.Service=this.api.hap.Service;\n\n         device.name = getAccessoryName( device );\n         let displayName = device.displayName = getAccessoryDisplayName( device );\n\n         // generate a unique id for the accessory this should be generated from\n         // something globally unique, but constant, for example, the device serial\n         // number or MAC address.\n         let uuid = getAccessoryUUID( device, this.api.hap.uuid );\n\n         // See if an accessory with the same UUID has already been registered and\n         // restored from the cached devices we stored in the `configureAccessory`\n         // method above\n\n         // NOTE: HOMEBRIDGE EXAMPLES HAVE THIS AS UPPERCASE UUID.\n         //       lower case uuid will not be found.\n         const existingAccessory = this.toBeRestoredPlatforms.find(accessory => accessory.UUID === uuid);\n\n         if (existingAccessory)\n         {\n            // NOTE: HOMEBRIDGE EXAMPLES HAVE THIS AS UPPERCASE UUID.\n            //       lower case uuid will not be found.\n            let duplicatePlatformAccessory = this.createdCmd4Platforms.find(accessory => accessory.UUID === existingAccessory.UUID);\n            if ( duplicatePlatformAccessory )\n            {\n               this.log( chalk.red( `Error duplicate platform accessory: ${ duplicatePlatformAccessory.name } uuid:${ duplicatePlatformAccessory.UUID }` ) );\n               // Next in for.Each object iteration\n               return;\n            }\n\n            this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);\n\n            // if you need to update the accessory.context then you should run\n            // `api.updatePlatformAccessories`. eg.:\n            //    existingAccessory.context.device = device;\n            //    this.api.updatePlatformAccessories( [ existingAccessory ] );\n            //existingAccessory.context.device = device;\n            //this.api.updatePlatformAccessories( [ existingAccessory ] );\n\n            // create the accessory handler for the restored accessory\n            // this is imported from `platformAccessory.ts`\n            // new ExamplePlatformAccessory( this, existingAccessory );\n\n            platform = existingAccessory;\n            platform.Service = this.Service;\n\n            // This is how we keep the device status information over restart.\n            // Version 0\n            // Within STORED_DATA_ARRAY is a list of UUID identified objects\n            // of storedValuesPerCharacteristic. \n            // Version 1\n            // Within STORED_DATA_ARRAY is a list of UUID identified objects\n            // of Cmd4Storage.\n\n            // If the accessory has linked accessories or standalone accessories,\n            // there infomation gets put in this as well.  I'm pretty sure\n            // that previosly these states were lost.\n\n            // Init the STORED_DATA_ARRAY to empty [ ].  If there was never any\n            // type to use, this is okay to.\n            let STORED_DATA_ARRAY = [ ];\n\n            // If the saved context has our STORED_DATA_ARRAY, then use it.\n            if ( existingAccessory.context.STORED_DATA_ARRAY )\n            {\n               if ( settings.cmd4Dbg ) this.log.debug(`Cmd4Platform: Using context.STORED_DATA_ARRAY` );\n               STORED_DATA_ARRAY = existingAccessory.context.STORED_DATA_ARRAY;\n\n            }\n\n            let that = this;\n            accessory = new Cmd4Accessory( that.log, device, this.api, STORED_DATA_ARRAY, this );\n            accessory.platform = platform;\n\n            // Put the accessory into its correct collection array.\n            this.createdCmd4Accessories.push( accessory );\n\n            // Store a copy of the device object in the `accessory.context`\n            // the `context` property can be used to store any data about the\n            // accessory you may need\n            accessory.platform.context.STORED_DATA_ARRAY = accessory.STORED_DATA_ARRAY;\n\n            // Get the properties for this accessories device type\n            let devProperties = CMD4_DEVICE_TYPE_ENUM.properties[ accessory.typeIndex ];\n\n            if ( settings.cmd4Dbg ) this.log.debug( `Step 2. ${ accessory.displayName }.service = platform.getService( Service.${ devProperties.deviceName }, ${ accessory.subType })` );\n            accessory.service = platform.getService( devProperties.service, accessory.name, accessory.subType );\n\n            // Determine which characteristics, if any, will be polled. This\n            // information is also used to define which service.getValue is\n            // used, either immediate, cached or polled.\n            // Already done by new Cmd4Acc\n            // accessory.determineCharacteristicsToPollOfAccessoryAndItsChildren( accessory );\n\n            // set up all services for those characteristics in the\n            // config.json file\n            accessory.addAllServiceCharacteristicsForAccessory( accessory );\n\n            // Create all the services for the accessory, including fakegato\n            // true = from existing.\n            this.createServicesForAccessoriesChildren( accessory, true )\n\n            // Since 'updateReachability()' function and the key 'reachable' are deprecated in\n            // Homebridge_v2, We will define the key 'reachable' and set the locally read in copy\n            // of the value to 'true' explicitly to flag that this accessory is restored from cache.\n            existingAccessory.reachable = true;\n\n         } else\n         {\n            // The accessory does not yet exist, so we need to create it.\n            this.log.info('Adding new platformAccessory:', displayName);\n\n            // Create the new PlatformAccessory\n            if ( device.category == undefined )\n            {\n               if ( settings.cmd4Dbg ) this.log.debug( `Step 1. platformAccessory = new platformAccessory( ${ displayName }, ${ uuid } )` );\n               platform = new this.api.platformAccessory( displayName, uuid );\n\n            } else\n            {\n               // Uppercase the category to be nice. Why do I know\n               // this will come back to bite me.\n               let category = this.api.hap.Categories[ String( device.category ).toUpperCase( ) ];\n\n               if ( ! category )\n                  throw new Error( `Category specified: ${ device.category } is not a valid homebridge category.` );\n\n               if ( settings.cmd4Dbg ) this.log.debug( `Step 1. platformAccessory = new platformAccessory( ${ displayName }, ${ uuid }, ${ category } )` );\n\n               platform = new this.api.platformAccessory( displayName, uuid, category );\n            }\n\n            platform.Service = this.Service;\n\n            this.log.info( chalk.magenta( `Configuring platformAccessory: ` ) + `${ device.displayName }` );\n            let that = this;\n            accessory = new Cmd4Accessory( that.log, device, this.api, [ ], this );\n            accessory.platform = platform\n\n            // Put the accessory into its correct collection array.\n            this.createdCmd4Accessories.push( accessory );\n\n            if ( settings.cmd4Dbg ) this.log.debug( `Created platformAccessory: ${ accessory.displayName }` );\n\n            // Store a copy of the device object in the `accessory.context`\n            // the `context` property can be used to store any data about the\n            // accessory you may need\n            accessory.platform.context.STORED_DATA_ARRAY = accessory.STORED_DATA_ARRAY;\n\n            // Get the properties for this accessories device type\n            let devProperties = CMD4_DEVICE_TYPE_ENUM.properties[ accessory.typeIndex ];\n\n            // MOVE OUSTSIDE\n            // Platform Step 2. const tvService = this.tvAccessory.addService( this.Service.Television );\n            if ( settings.cmd4Dbg ) this.log.debug( `Step 2. ${ accessory.displayName }.service = platform.addService( this.Service.${ devProperties.deviceName }, ${ accessory.name }, ${ accessory.subType })` );\n            accessory.service = platform.addService( new devProperties.service( accessory.name, accessory.subType )  );\n\n            // Create all the services for the accessory, including fakegato\n            // false = not from existing.\n            this.createServicesForAccessoriesChildren( accessory, false )\n\n            // Step 6. this.api.publishExternalAccessories( PLUGIN_NAME, [ this.tvAccessory ] );\n            if ( accessory.publishExternally )\n            {\n               if ( settings.cmd4Dbg ) this.log.debug( `Step 6. publishExternalAccessories( ${ settings.PLUGIN_NAME }, [ ${accessory.displayName } ] )` );\n\n               this.api.publishExternalAccessories( settings.PLUGIN_NAME, [ platform ] );\n\n            } else {\n               if ( settings.cmd4Dbg ) this.log.debug( `Step 6. registerPlatformAccessories( ${ settings.PLUGIN_NAME }, ${ settings.PLATFORM_NAME }, [ ${  accessory.displayName } ] ) `);\n\n               this.api.registerPlatformAccessories( settings.PLUGIN_NAME, settings.PLATFORM_NAME, [ platform ] );\n            }\n         }\n\n\n         // Just a flag to say we have processed this existing platform accessory.\n         // @deprecated homebridge v2\n         //platform.updateReachability( true );\n\n\n         // For Unit testing only\n         this.createdCmd4Platforms.push( platform );\n\n      });\n   }\n\n   createServicesForAccessoriesChildren( cmd4PlatformAccessory, fromExisting )\n   {\n      // Create the information Service for the platform itself\n      // Unlike Standalone Accessories; The Platform information service is created\n      // for us and the getService hangs off the platform, not the accessory.\n      if ( cmd4PlatformAccessory.model )\n      {\n         if ( settings.cmd4Dbg ) cmd4PlatformAccessory.log.debug( `Adding model( ${ cmd4PlatformAccessory.model } ) to information service of ${ cmd4PlatformAccessory.displayName }` );\n         cmd4PlatformAccessory.platform.getService( cmd4PlatformAccessory.platform.Service.AccessoryInformation )\n            .setCharacteristic( this.api.hap.Characteristic.Model, cmd4PlatformAccessory.model );\n      }\n\n      if ( cmd4PlatformAccessory.manufacturer )\n      {\n         if ( settings.cmd4Dbg ) cmd4PlatformAccessory.log.debug( `Adding manufacturer( ${ cmd4PlatformAccessory.manufacturer } ) to information service of ${ cmd4PlatformAccessory.displayName }` );\n         cmd4PlatformAccessory.platform.getService( cmd4PlatformAccessory.platform.Service.AccessoryInformation )\n            .setCharacteristic( this.api.hap.Characteristic.Manufacturer, cmd4PlatformAccessory.manufacturer );\n      }\n\n      if ( cmd4PlatformAccessory.serialNumber )\n      {\n         if ( settings.cmd4Dbg ) cmd4PlatformAccessory.log.debug( `Adding serial Number( ${ cmd4PlatformAccessory.serialNumber } ) to information service of ${ cmd4PlatformAccessory.displayName }` );\n         cmd4PlatformAccessory.platform.getService( cmd4PlatformAccessory.platform.Service.AccessoryInformation )\n            .setCharacteristic( this.api.hap.Characteristic.SerialNumber, cmd4PlatformAccessory.serialNumber );\n      }\n\n      if ( cmd4PlatformAccessory.firmwareRevision )\n      {\n         if ( settings.cmd4Dbg ) cmd4PlatformAccessory.log.debug( `Adding Firmware Revision( ${ cmd4PlatformAccessory.firmwareRevision } ) to information service of ${ cmd4PlatformAccessory.displayName }` );\n         cmd4PlatformAccessory.platform.getService( cmd4PlatformAccessory.platform.Service.AccessoryInformation )\n            .setCharacteristic( this.api.hap.Characteristic.FirmwareRevision, cmd4PlatformAccessory.firmwareRevision );\n      }\n\n      // Create the service for all the accessories. i.e. Speaker Service\n      // Step 3.\n      //    const speakerService = this.tvAccessory.addService( this.Service.TelevisionSpeaker );\n      cmd4PlatformAccessory.accessories && cmd4PlatformAccessory.accessories.forEach( ( addedAccessory ) =>\n      {\n         // Set the platform of the added accessories so that the accessories can call methods\n         // like this one.\n         addedAccessory.platform = cmd4PlatformAccessory.platform;\n\n         // Get the properties for this accessory's device type\n         let devProperties = CMD4_DEVICE_TYPE_ENUM.properties[ addedAccessory.typeIndex ];\n\n         // Existing Accessories would have existing services\n         if ( fromExisting == true )\n         {\n            if ( settings.cmd4Dbg ) this.log.debug( `Platform (AddedAccessory-existing) Step 3, ${ addedAccessory.displayName }.service = accessory.platform.getService( Service.${ devProperties.deviceName }, ${ addedAccessory.name }, ${ addedAccessory.subType }` );\n            // If you have added more than one service of the same type to an accessory, you will need to get the service using the name you defined when adding it.\n            //addedAccessory.service = addedAccessory.platform.getService( devProperties.service, addedAccessory.name, addedAccessory.subType );\n            addedAccessory.service = addedAccessory.platform.getService( addedAccessory.name, addedAccessory.subType );\n         } else\n         {\n\n            if ( settings.cmd4Dbg ) this.log.debug( `Platform (AddedAccessory-new) Step 3, ${ addedAccessory.displayName }.service = PlatformAccessory: ${ cmd4PlatformAccessory.displayName } addService( Service:${ devProperties.deviceName }, ${ addedAccessory.name }, ${ addedAccessory.subType } )` );\n\n            addedAccessory.service = cmd4PlatformAccessory.platform.addService( new devProperties.service( addedAccessory.name, addedAccessory.subType ) );\n         }\n\n         addedAccessory.addAllServiceCharacteristicsForAccessory( addedAccessory );\n         // Create Information Service for the addedAccessory\n         if ( settings.cmd4Dbg ) addedAccessory.log.debug( `Creating information service for AddedAccessory: ${ addedAccessory.displayName }` );\n         createAccessorysInformationService( addedAccessory );\n\n          // Setup the fakegato service if defined in the config.json file\n         addedAccessory.setupAccessoryFakeGatoService( addedAccessory.fakegatoConfig );\n         // Move the information service to the top of the list\n         addedAccessory.services.unshift( addedAccessory.informationService );\n\n      });\n\n      // Create the service for all the linked accessories. i.e. HDMI Service\n      cmd4PlatformAccessory.linkedAccessories && cmd4PlatformAccessory.linkedAccessories.forEach( ( linkedAccessory ) =>\n      {\n         // Set the platform of the linked accessories so that the accessories can call methods\n         // like this one.\n         linkedAccessory.platform = cmd4PlatformAccessory.platform;\n\n         // Get the properties for this linked Accessory device type\n         let devProperties = CMD4_DEVICE_TYPE_ENUM.properties[ linkedAccessory.typeIndex ];\n\n         // Child accessories can have linked accessories. i.e. HDMI accessory\n         // Step 4.\n         //    const hdmi1InputService = this.tvAccessory.addService( this.Service.InputSource, `hdmi1', 'HDMI 1' );\n\n         // Existing Accessories would have existing services\n         if ( fromExisting == true )\n         {\n            if ( settings.cmd4Dbg ) this.log.debug( `Platform (LinkedAccessory-existing) Step 4. ${ linkedAccessory.displayName }.service = ${ cmd4PlatformAccessory.displayName }.getService:( ${ devProperties.deviceName }.service, ${linkedAccessory.name }, ${linkedAccessory.subType } )` );\n            // If you have added more than one service of the same type to an accessory, you will need to get the service using the name you defined when adding it.\n\n            //linkedAccessory.service = linkedAccessory.platform.getService( devProperties.service, linkedAccessory.name, linkedAccessory.subType );\n            linkedAccessory.service = linkedAccessory.platform.getService( linkedAccessory.name, linkedAccessory.subType );\n         } else\n         {\n            if ( settings.cmd4Dbg ) this.log.debug( `Platform (LinkedAccessory-new) Step 4. ${ linkedAccessory.displayName }.service = ${ cmd4PlatformAccessory.displayName }.addService:( ${ devProperties.deviceName }.service, ${linkedAccessory.name }, ${linkedAccessory.subType } )` );\n\n            linkedAccessory.service = cmd4PlatformAccessory.platform.addService( new devProperties.service( linkedAccessory.name, linkedAccessory.subType ) );\n         }\n\n         linkedAccessory.addAllServiceCharacteristicsForAccessory( linkedAccessory );\n\n         if ( fromExisting == false )\n         {\n            if ( settings.cmd4Dbg ) this.log.debug( `Platform Step 5. ${ cmd4PlatformAccessory.displayName }.service.addLinkedService( ${ linkedAccessory.displayName }.service )` );\n            cmd4PlatformAccessory.service.addLinkedService( linkedAccessory.service );\n         }\n\n         // Create Information Service for the linkedAccessory\n         if ( settings.cmd4Dbg ) linkedAccessory.log.debug( `Creating information service for Linked Platform Accessory: ${ linkedAccessory.displayName }` );\n         createAccessorysInformationService( linkedAccessory );\n\n          // Setup the fakegato service if defined in the config.json file\n         linkedAccessory.setupAccessoryFakeGatoService( linkedAccessory.fakegatoConfig );\n         // Move the information service to the top of the list\n         linkedAccessory.services.unshift( linkedAccessory.informationService );\n\n      });\n\n      // Setup all the characteristics for the platform accessory itself\n      cmd4PlatformAccessory.addAllServiceCharacteristicsForAccessory( cmd4PlatformAccessory );\n\n      // Setup the fakegato service for the platform accessory istelf.\n      cmd4PlatformAccessory.setupAccessoryFakeGatoService( cmd4PlatformAccessory.fakegatoConfig );\n   }\n\n   // The delay definitions are not meant to be changed, except for unit testing\n   // ==========================================================================\n   // staggeredStartDelay - These would be for just polling and to be nice to the system.\n   // queuedStartDelay - As this is both IOS and polling, the delay only happens to \n   // the low priority polling.\n   startPolling( queuedStartDelay = 40000 )\n   {\n      // Check for any queued characteristics\n      if ( Object.keys( settings.listOfCreatedPriorityQueues ).length == 0 )\n      {\n         if ( settings.cmd4Dbg ) this.log.debug( `No queued polling characteristics` );\n         return;\n      }\n\n      // Start polling of each queue of characteristics\n      let lastIndex = Object.keys( settings.listOfCreatedPriorityQueues ).length;\n      Object.keys( settings.listOfCreatedPriorityQueues ).forEach( ( queueName, index ) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         let queuedPollingTimer = setTimeout( ( ) =>\n         {\n            if ( index == lastIndex -1 )\n              this.log.info( chalk.magenta( `*** Starting Polling` ) );\n            queue.startQueue( queue, ( ) =>\n            {\n               if ( index == 0 )\n                  this.log.info( chalk.magenta( `*** All characteristics are now being polled` ) );\n            });\n\n         }, queuedStartDelay );\n\n         this.pollingTimers.push( queuedPollingTimer );\n      });\n   }\n}\n\nexports.Cmd4Platform = Cmd4Platform;\n"
  },
  {
    "path": "Cmd4PriorityPollingQueue.js",
    "content": "'use strict';\n\n// 3rd Party includes\nconst exec = require( \"child_process\" ).exec;\n\n\n// These would already be initialized by index.js\nlet CMD4_ACC_TYPE_ENUM = require( \"./lib/CMD4_ACC_TYPE_ENUM\" ).CMD4_ACC_TYPE_ENUM;\n\n\n// Settings, Globals and Constants\nlet settings = require( \"./cmd4Settings\" );\nconst constants = require( \"./cmd4Constants\" );\n\n// Pretty Colors\nvar chalk = require( \"chalk\" );\n\nlet trueTypeOf = require( \"./utils/trueTypeOf\" );\nlet lcFirst = require( \"./utils/lcFirst\" );\n\n// For changing validValue Constants to Values and back again\nvar { transposeConstantToValidValue,\n      transposeValueToValidConstant,\n      transposeBoolToValue\n    } = require( \"./utils/transposeCMD4Props\" );\n\n\nlet HIGH_PRIORITY_SET = 0;\nlet HIGH_PRIORITY_GET = 1;\nlet LOW_PRIORITY_GET = 2;\n\nclass Cmd4PriorityPollingQueue\n{\n   constructor( log, queueName, queueType = constants.DEFAULT_QUEUE_TYPE, queueRetryCount = constants.DEFAULT_WORM_QUEUE_RETRY_COUNT )\n   {\n      this.log = log;\n\n      // This works better for Unit testing\n      settings.cmd4Dbg = log.debugEnabled;\n\n      this.queueName = queueName;\n      this.queueType = queueType;\n      this.queueRetryCount = queueRetryCount;\n      this.queueStarted = false;\n      this.highPriorityQueue = [ ];\n      this.lowPriorityQueue = [ ];\n      this.lowPriorityQueueIndex = 0 ;\n      this.inProgressGets = 0;\n      this.inProgressSets = 0;\n\n      this.listOfRunningPolls = {};\n\n      // This is not a sanity timer.\n      // This controls when it is safe to do a \"Get\" of the Aircon\n      // after a failed condition. It does happen to fix the queue\n      // when something is wrong, but this is not the purpose of\n      // this timer.\n      this.pauseTimer = null;\n      this.lastGoodTransactionTime =  Date.now( );\n      this.errorCountSinceLastGoodTransaction = 0;\n\n      // - Not a const so it can be manipulated during unit testing\n      this.pauseTimerTimeout = constants.DEFAULT_QUEUE_PAUSE_TIMEOUT;\n\n      // The WoRm queue needs error messages to be silenced as\n      // they are inevitable, but are handled through retries\n      // By default non WoRm queues are allowed to echo errors\n\n      if ( this.queueRetryCount == 0 || settings.debug )\n         this.echoE = true;\n      else\n         this.echoE = true;\n\n      this.changeQueueType( this, queueType );\n   }\n\n   echoRetryErrors( currentRetryCount )\n   {\n      // If debug then the default is true\n      if ( settings.cmd4Debug )\n         return true;\n\n      // Since this is the last retry, echo the error\n      if ( currentRetryCount == this.queueRetryCount )\n         return true;\n\n      return false;\n   }\n\n   // This function is called by homebridge to *PUT AN ENTRY INTO THE HIGHEST PRIORITY SET QUEUE*.\n   // We immediately return success if the device is accessible. Either way the Set is attempted\n   // above everything else except other SetValue requests.\n   prioritySetValue( accTypeEnumIndex, characteristicString, timeout, stateChangeResponseTime,  value, homebridgeCallback )\n   {\n      // this is Accessory\n      //\n      //if ( settings.cmd4Dbg ) this.log.debug(`prioritySetValue, asked to set: ${ characteristicString } to ${ value }`);\n\n      // Save the value to cache. The set will come later\n      // this.cmd4Storage.setStoredValueForIndex( accTypeEnumIndex, value );\n\n      if ( this.errorValue != 0 )\n      {\n         if ( settings.cmd4Dbg ) this.log.debug(`prioritySetValue for ${ this.displayName }, homebridgeCallback returning error ${ this.errorValue } ${ this.errorString }`);\n         homebridgeCallback( this.errorValue );\n      } else\n      {\n         if ( settings.cmd4Dbg ) this.log.debug(`prioritySetValue for ${ this.displayName }, homebridgeCallback returning default success 0`);\n         homebridgeCallback( 0 );\n      }\n\n      let newEntry = { [ constants.IS_SET_lv ]: true, [ constants.ACCESSORY_lv ]: this, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.CHARACTERISTIC_STRING_lv ]: characteristicString, [ constants.TIMEOUT_lv ]: timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: stateChangeResponseTime, [ constants.CALLBACK_lv ]: homebridgeCallback, [ constants.VALUE_lv ]: value };\n\n      // Determine where to put the entry in the queue\n      if ( this.queue.highPriorityQueue.length == 0 )\n      {\n         // No entries, then it goes on top\n         this.queue.highPriorityQueue.push( newEntry );\n\n      } else {\n\n         // Make sure that this is the latest \"Set\" of this entry\n         let index = this.queue.highPriorityQueue.findIndex( ( entry ) => entry.accessory.uuid == this.uuid && entry.isSet == true && entry.accTypeEnumIndex == accTypeEnumIndex );\n\n         if ( index == -1 )\n         {\n            // It doesn't exist in the queue, It needs to be placed after any \"Sets\".\n            // First Determine the first \"Get\"\n            let getIndex = this.queue.highPriorityQueue.findIndex( ( entry ) => entry.isSet == false );\n\n            if ( getIndex == -1 )\n            {\n               // No \"Get\" entrys, it goes at the end after everything.\n               this.queue.highPriorityQueue.push( newEntry );\n\n            } else\n            {\n               // Insert before the first \"Get\" entry\n               this.queue.highPriorityQueue.splice( getIndex, 0, newEntry );\n            }\n         } else\n         {\n            this.queue.highPriorityQueue[ index ] = newEntry;\n         }\n      }\n      this.queue.processQueueFunc( HIGH_PRIORITY_SET, this.queue );\n   }\n\n   // This function is called by homebridge to *PUT AN ENTRY INTO THE HIGHEST PRIORITY GET QUEUE*.\n   // We immediately return with success and the last known value if the device is accessible, otherwise\n   // the last failure error code.\n   // The Get is attempted no matter the devices availability. This is done after every Set\n   // request and at the bottom of the hightPrioritySetValue queue, but above any polling.\n   priorityGetValue( accTypeEnumIndex, characteristicString, timeout, homebridgeCallback )\n   {\n      // this is Accessory\n\n      // if ( settings.cmd4Dbg ) this.log.debug(`priorityGetValue for ${ this.displayName }, asked to Get: ${ characteristicString }`);\n\n      if ( this.errorValue != 0 )\n      {\n         // if ( settings.cmd4Dbg ) this.log.debug(`priorityGetValue for ${ this.displayName }, homebridgeCallback returning error ${ this.errorValue } ${ this.errorString}`);\n         homebridgeCallback( this.errorValue );\n      } else\n      {\n         // return the cached value\n         let storedValue = this.cmd4Storage.getStoredValueForIndex( accTypeEnumIndex );\n\n         // if ( settings.cmd4Dbg ) this.log.debug(`priorityGetValue for ${ this.displayName }, homebridgeCallback returning storedValue: ${ storedValue }`);\n         homebridgeCallback( 0, storedValue );\n      }\n\n      if ( this.queue.queueType != constants.QUEUETYPE_WORM2 )\n      {\n         // When the value is returned, it will update homebridge\n         this.queue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: true, [ constants.ACCESSORY_lv ]: this, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.CHARACTERISTIC_STRING_lv ]: characteristicString, [ constants.TIMEOUT_lv ]: timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: homebridgeCallback } );\n\n         this.queue.processQueueFunc( HIGH_PRIORITY_GET, this.queue );\n      }\n   }\n\n   // This function is called by polling to *PUT AN ENTRY INTO THE LOW PRIORITY POLLING QUEUE*.\n   addLowPriorityGetPolledQueueEntry( accessory, accTypeEnumIndex, characteristicString, interval, timeout )\n   {\n      // These are all gets from polling\n      accessory.queue.lowPriorityQueue.push( { [ constants.ACCESSORY_lv ]: accessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: accTypeEnumIndex, [ constants.CHARACTERISTIC_STRING_lv ]: characteristicString, [ constants.INTERVAL_lv ]: interval, [ constants.TIMEOUT_lv ]: timeout } );\n\n   }\n\n   processHighPrioritySetQueue( entry )\n   {\n      if ( settings.cmd4Dbg ) this.log.debug( `Processing high priority queue \"Set\" entry: ${ entry.accTypeEnumIndex } length: ${ this.highPriorityQueue.length }` );\n\n      this.inProgressSets ++;\n      this.qSetValue( entry.accessory, entry.accTypeEnumIndex, entry.characteristicString, entry.timeout, entry.value, function ( error )\n      {\n\n         let queue = entry.accessory.queue;\n\n         // Save the error code - Pass or fail\n         entry.accessory.errorValue = error;\n\n         if ( error == 0 )\n         {\n            // Now that the set was successful, store the value\n            entry.accessory.cmd4Storage.setStoredValueForIndex( entry.accTypeEnumIndex, entry.value );\n\n            // Since the \"Set\" passed, do the stateChangeResponseTime\n            setTimeout( ( ) =>\n            {\n            // A set with no error means the queue is sane to do reading\n            queue.lastGoodTransactionTime = Date.now( );\n            queue.errorCountSinceLastGoodTransaction = 0;\n\n            // After the stateChangeResponseTime, do the related characteristic ( if any )\n            let relatedCurrentAccTypeEnumIndex = entry.accessory.getDevicesRelatedCurrentAccTypeEnumIndex( entry.accTypeEnumIndex );\n\n               if ( relatedCurrentAccTypeEnumIndex != null )\n            {\n            let relatedCurrentCharacteristicString = CMD4_ACC_TYPE_ENUM.properties[ relatedCurrentAccTypeEnumIndex ].type;\n            // Change the entry to a get and set queueGetIsUpdate to true\n            // Use unshift to make it next in line\n            entry.isSet = false;\n            entry.accTypeEnumIndex = relatedCurrentAccTypeEnumIndex;\n            entry.characteristicString = relatedCurrentCharacteristicString;\n            entry.queueGetIsUpdate = true;\n            queue.highPriorityQueue.unshift( entry );\n               }\n\n               // The \"Set\" is now complete after its stateChangeResponseTime.\n               queue.inProgressSets --;\n\n               setTimeout( ( ) => { queue.processQueueFunc( HIGH_PRIORITY_GET, queue ); }, 0 );\n\n            return;\n\n            }, entry.stateChangeResponseTime );\n\n         } else  // setValue failed\n         {\n            // The \"Set\" is complete, even if it failed.\n            queue.inProgressSets --;\n\n            let currentRetryCount = queue.errorCountSinceLastGoodTransaction;\n\n            if ( currentRetryCount >= queue.queueRetryCount )\n            {\n               if ( queue.echoRetryErrors( currentRetryCount ) )\n               {\n                  // Counting starts from zero, i.e queueRetries = 0, so add 1\n                  queue.log.warn( `*${ currentRetryCount + 1 }* error(s) were encountered for \"${ entry.accessory.displayName }\" getValue. Last error found Getting: \"${ entry.characteristicString}\". Perhaps you should run in debug mode to find out what the problem might be.` );\n               }\n\n               // Convert the errorValue into an errorString\n               entry.accessory.errorString = new Error( constants.errorString( error ) );\n\n               // This does not work - Nothing happens to HomeKit !\n               // queue.log.warn( `START processHighPrioritySetQueue calling updateCharacteristic errorValue: ${ entry.accessory.errorValue} errorString: ${ entry.accessory.errorString }`);\n               // entry.accessory.service.getCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ entry.accTypeEnumIndex ].characteristic ).updateValue( entry.accessory.errorString );\n               // queue.log.warn( `END processHighPrioritySetQueue calling updateCharacteristic errorValue: ${ entry.accessory.errorValue} errorString: ${ entry.accessory.errorString }`);\n\n\n            } else\n            {\n               // Increment the errorCount/currentRetryCount\n               queue.errorCountSinceLastGoodTransaction++;\n\n               // Set failed. We need to keep trying\n               queue.highPriorityQueue.push( entry );\n\n            }\n\n            entry.accessory.queue.pauseQueue( entry.accessory.queue );\n         }\n\n         // Note 1.\n         // Do not call the callback as it was done when the \"Set\" entry was\n         // created.\n\n         // Note 2.\n         // We cannot release the queue for further processing as the\n         // statechangeResponseTime has not completed. This must be\n         // done first or any next \"Get\" or \"Set\" would interfere\n         // with the device\n\n      });\n   }\n\n   processHighPriorityGetQueue( entry )\n   {\n      if ( settings.cmd4Dbg ) this.log.debug( `Processing high priority queue \"Get\" entry: ${ entry.accTypeEnumIndex } isUpdate: ${ entry.queueGetIsUpdate } length: ${ this.highPriorityQueue.length }` );\n\n      this.inProgressGets ++;\n\n      this.qGetValue( entry.accessory, entry.accTypeEnumIndex, entry.characteristicString, entry.timeout, function ( error, properValue )\n      {\n         let queue = entry.accessory.queue;\n\n         // Save the error code - Pass or fail\n         entry.accessory.errorValue = error;\n\n         // Nothing special was done for casing on errors, so omit it.\n         if ( error == 0 )\n         {\n            // Save the new returned value\n            entry.accessory.cmd4Storage.setStoredValueForIndex( entry.accTypeEnumIndex, properValue );\n\n            // hmmm if ( entry.queueGetIsUpdate == true )\n               entry.accessory.service.getCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ entry.accTypeEnumIndex ].characteristic ).updateValue( properValue );\n\n             // A good anything, updates the lastGoodTransactionTime\n            queue.lastGoodTransactionTime = Date.now( );\n            queue.errorCountSinceLastGoodTransaction = 0;\n\n         } else  // highPriority getValue failed\n         {\n\n            let currentRetryCount = queue.errorCountSinceLastGoodTransaction;\n\n            if ( currentRetryCount >= queue.queueRetryCount )\n            {\n               if ( queue.echoRetryErrors( currentRetryCount ) )\n                  queue.log.warn( `*${ currentRetryCount + 1}* error(s) were encountered for \"${ entry.accessory.displayName }\" getValue. Last error found Getting: \"${ entry.characteristicString}\". Perhaps you should run in debug mode to find out what the problem might be.` );\n\n               // Convert the errorValue into an errorString\n               entry.accessory.errorString = new Error( constants.errorString( error ) );\n\n               // This does not work - Nothing happens to HomeKit !\n               // queue.log.warn( `START processHighPriorityGetQueue calling updateCharacteristic errorValue: ${ entry.accessory.errorValue} errorString: ${ entry.accessory.errorString }`);\n               // entry.accessory.service.getCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ entry.accTypeEnumIndex ].characteristic ).updateValue( entry.accessory.errorString );\n               // queue.log.warn( `END processHighPriorityGetQueue calling updateCharacteristic errorValue: ${ entry.accessory.errorValue} errorString: ${ entry.accessory.errorString }`);\n\n            } else\n            {\n               // Increment the errorCount/currentRetryCount\n               queue.errorCountSinceLastGoodTransaction++;\n\n               // High Priority Get failed. We keep retrying until the mod of\n               // queueRetryCount reaches zero, which is WoRm only as it has more than 1\n               // default retry count.\n               queue.highPriorityQueue.push( entry );\n            }\n\n            entry.accessory.queue.pauseQueue( entry.accessory.queue );\n         }\n\n         queue.inProgressGets --;\n         setTimeout( ( ) => { queue.processQueueFunc( HIGH_PRIORITY_GET, queue ); }, 0 );\n\n      });\n   }\n\n   // This is called from polling\n   processEntryFromLowPriorityQueue( entry )\n   {\n      if ( settings.cmd4Dbg ) this.log.debug( `Processing low priority queue entry: ${ entry.accTypeEnumIndex }` );\n\n      let queue = entry.accessory.queue;\n\n      queue.inProgressGets ++;\n\n      // isLowPriority is set to true,\n      queue.qGetValue( entry.accessory, entry.accTypeEnumIndex, entry.characteristicString, entry.timeout, function ( error, properValue )\n      {\n         // For the next one\n         queue.inProgressGets --;\n\n         // Save the error code - Pass or fail\n         entry.accessory.errorValue = error;\n\n         // Nothing special was done for casing on errors, so omit it.\n         if ( error == 0 )\n         {\n            // Save the new value\n            entry.accessory.cmd4Storage.setStoredValueForIndex( entry.accTypeEnumIndex, properValue );\n\n            if ( settings.cmd4Dbg ) entry.accessory.log.debug( `processEntryFromLowPriorityQueue calling updateValue properValue: ${ properValue }`);\n\n            // Update the new value in homebridge\n            entry.accessory.service.getCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ entry.accTypeEnumIndex ].characteristic ).updateValue( properValue );\n\n             // A good anything, updates the lastGoodTransactionTime\n            queue.lastGoodTransactionTime = Date.now( );\n            queue.errorCountSinceLastGoodTransaction = 0;\n\n         } else { // LowPriority getValue failed\n            queue.errorCountSinceLastGoodTransaction++;\n\n            // Convert the errorValue into an errorString\n            entry.accessory.errorString = new Error( constants.errorString( error ));\n\n            // This does not work - Nothing happens to HomeKit !\n            // Call updateValue with new Error so device will become unavailable\n            // queue.log.warn( `START processEntryFromLowPriorityQueue calling updateCharacteristic errorValue: ${ entry.accessory.errorValue } errorString: ${ entry.accessory.errorString }`);\n            // entry.accessory.service.getCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ entry.accTypeEnumIndex ].characteristic ).updateValue( entry.accessory.errorString );\n            // queue.log.warn( `END processEntryFromLowPriorityQueue calling updateCharacteristic errorValue: ${ entry.accessory.errorValue } errorString: ${ entry.accessory.errorString }`);\n\n            queue.pauseQueue( entry.accessory.queue );\n         }\n\n         // Now that this one has been processed, schedule it again for next time\n         queue.scheduleLowPriorityEntry( entry )\n\n      });\n   }\n\n   // ***********************************************\n   //\n   // qGetValue: Method to call an external script\n   //            that returns an accessories status\n   //            for a given characteristic.\n   //\n   //   The script will be passed:\n   //      Get <Device Name> <accTypeEnumIndex>\n   //\n   //      Where:\n   //         - Device name is the name in your\n   //           config.json file.\n   //         - accTypeEnumIndex represents\n   //           the characteristic to get as in index into\n   //           the CMD4_ACC_TYPE_ENUM.\n   //\n   // ***********************************************\n   qGetValue( accessory, accTypeEnumIndex, characteristicString, timeout, callback )\n   {\n      let self = accessory;\n      let queue = accessory.queue;\n\n      let cmd = self.state_cmd_prefix + self.state_cmd + \" Get '\" + self.displayName + \"' '\" + characteristicString + \"'\" + self.state_cmd_suffix;\n\n      // My AdvAir friends want to allow single quotes in accessory names, which\n      // may have consequences with globbing for others.\n      if ( self.state_cmd.match( /AdvAir.sh/ ) )\n      {\n          cmd = self.state_cmd_prefix + self.state_cmd + ' Get \"' + self.displayName + '\" ' + \"'\" + characteristicString + \"'\" + self.state_cmd_suffix;\n      }\n\n      if ( settings.cmd4Dbg ) self.log.debug( `getValue: accTypeEnumIndex:( ${ accTypeEnumIndex } )-\"${ characteristicString }\" function for: ${ self.displayName } cmd: ${ cmd } timeout: ${ timeout }` );\n\n      let reply = \"NxN\";\n\n      // Execute command to Get a characteristics value for an accessory\n      // exec( cmd, { timeout: timeout }, function ( error, stdout, stderr )\n      //let child = spawn( cmd, { shell:true } );\n      let child = exec( cmd, { timeout: timeout }, function ( error, stdout, stderr )\n      {\n         if ( stderr )\n            if ( queue.echoE ) self.log.error( `getValue: ${ characteristicString } function for ${ self.displayName } streamed to stderr: ${ stderr }` );\n\n         // Handle errors when process closes\n         if ( error )\n            if ( queue.echoE ) self.log.error( chalk.red( `getValue ${ characteristicString } function failed for ${ self.displayName } cmd: ${ cmd } Failed.  Generated Error: ${ error }` ) );\n\n         reply = stdout;\n\n      }).on('close', ( code ) =>\n      {\n         // Was the return code successful ?\n         if ( code != 0 )\n         {\n            // Commands that time out have \"null\" return codes. So get the real one.\n            if ( child.killed == true )\n            {\n               if ( queue.echoE  ) self.log.error( chalk.red( `getValue ${ characteristicString } function timed out ${ timeout }ms for ${ self.displayName } cmd: ${ cmd } Failed` ) );\n               callback( constants.ERROR_TIMER_EXPIRED );\n\n               return;\n            }\n            if ( queue.echoE  ) self.log.error( chalk.red( `getValue ${ characteristicString } function failed for ${ self.displayName } cmd: ${ cmd } Failed. Error: ${ code }. ${ constants.DBUSY }` ) );\n\n            callback( code );\n\n            return;\n         }\n\n         if ( reply == \"NxN\" )\n         {\n            if ( queue.echoE  ) self.log.error( `getValue: nothing returned from stdout for ${ characteristicString } ${ self.displayName }. ${ constants.DBUSY }` );\n\n            callback( constants.ERROR_NO_DATA_REPLY );\n\n            return;\n         }\n\n         if ( reply == null )\n         {\n            if ( queue.echoE  ) self.log.error( `getValue: null returned from stdout for ${ characteristicString } ${ self.displayName }. ${ constants.DBUSY }` );\n\n            // We can call our callback though ;-)\n            callback( constants.ERROR_NULL_REPLY );\n\n            return;\n         }\n\n         // Coerce to string for manipulation\n         reply += '';\n\n         // Remove trailing newline or carriage return, then\n         // Remove leading and trailing spaces, carriage returns ...\n         let trimmedReply = reply.replace(/\\n|\\r$/,\"\").trim( );\n\n         // Theoretically not needed as this is caught below, but I wanted\n         // to catch this before much string manipulation was done.\n         if ( trimmedReply.toUpperCase( ) == \"NULL\" )\n         {\n            if ( queue.echoE  ) self.log.error( `getValue: \"${ trimmedReply }\" returned from stdout for ${ characteristicString } ${ self.displayName }. ${ constants.DBUSY }` );\n            callback( constants.ERROR_NULL_STRING_REPLY );\n\n            return;\n         }\n\n         // Handle beginning and ending matched single or double quotes. Previous version too heavy duty.\n         // - Remove matched double quotes at begining and end, then\n         // - Remove matched single quotes at beginning and end, then\n         // - remove leading and trailing spaces.\n         let unQuotedReply = trimmedReply.replace(/^\"(.+)\"$/,\"$1\").replace(/^'(.+)'$/,\"$1\").trim( );\n\n         if ( unQuotedReply == \"\" )\n         {\n            if ( queue.echoE  ) self.log.error( `getValue: ${ characteristicString } function for: ${ self.displayName } returned an empty string \"${ trimmedReply }\". ${ constants.DBUSY }` );\n\n            callback( constants.ERROR_EMPTY_STRING_REPLY );\n\n            return;\n         }\n\n         // The above \"null\" checked could possibly have quotes around it.\n         // Now that the quotes are removed, I must check again.  The\n         // things I must do for bad data ....\n         if ( unQuotedReply.toUpperCase( ) == \"NULL\" )\n         {\n            if ( queue.echoE  ) self.log.error( `getValue: ${ characteristicString } function for ${ self.displayName } returned the string \"${ trimmedReply }\". ${ constants.DBUSY }` );\n\n            callback( constants.ERROR_2ND_NULL_STRING_REPLY );\n\n            return;\n         }\n\n         let words = unQuotedReply.split( \" \" ).length;\n         if ( words > 1 && CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].props.allowedWordCount == 1 )\n         {\n            self.log.warn( `getValue: Warning, Retrieving ${ characteristicString }, expected only one word value for: ${ self.displayName } of: ${ trimmedReply }` );\n         }\n\n         if ( settings.cmd4Dbg ) self.log.debug( `getValue: ${ characteristicString } function for: ${ self.displayName } returned: ${ unQuotedReply }` );\n\n\n         var transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, unQuotedReply )\n         if ( settings.cmd4Dbg && transposed != unQuotedReply ) self.log.debug( `getValue: ${ characteristicString } for: ${ self.displayName } transposed: ${ transposed }` );\n\n\n         // Return the appropriate type, by seeing what it is\n         // defined as in Homebridge,\n         let properValue = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( transposed );\n         if ( properValue == undefined )\n         {\n            self.log.warn( `${ self.displayName } ` + chalk.red( `Cannot convert value: ${ unQuotedReply } to ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].props.format } for ${ characteristicString }` ) );\n\n            callback( constants.ERROR_NON_CONVERTABLE_REPLY );\n\n            return;\n         }\n\n         if ( settings.cmd4Dbg && properValue != transposed ) self.log.debug( `getValue: ${ characteristicString } for: ${ self.displayName } properValue: ${ properValue }` );\n\n         // Success !!!!\n         callback( 0, properValue );\n\n         // Store history using fakegato if set up\n         self.updateAccessoryAttribute( accTypeEnumIndex, properValue );\n\n      });\n   }\n\n   // ***********************************************\n   //\n   // qSetValue: Method to call an external script\n   //            that sets an accessories status\n   //            for a given characteristic.\n   //\n   //\n   //   The script will be passed:\n   //      Set < Device Name > < accTypeEnumIndex > < Value >\n   //\n   //\n   //      Where:\n   //         - Device name is the name in your\n   //           config.json file.\n   //         - accTypeEnumIndex represents\n   //           the characteristic to get as in index into\n   //           the CMD4_ACC_TYPE_ENUM.\n   //         - Characteristic is the accTypeEnumIndex\n   //           in HAP form.\n   //         - Value is new characteristic value.\n   //\n   //  Notes:\n   //    ( 1 ) In the special TARGET set characteristics, getValue\n   //        is called to update HomeKit.\n   //          Example: Set My_Door < TargetDoorState > 1\n   //            calls: Get My_Door < CurrentDoorState >\n   //\n   //       - Where he value in <> is an one of CMD4_ACC_TYPE_ENUM\n   // ***********************************************\n   qSetValue( accessory, accTypeEnumIndex, characteristicString, timeout, value, queueCallback )\n   {\n      let self = accessory;\n      let queue = accessory.queue;\n\n      if ( self.hV.outputConstants == true )\n      {\n         value = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, value );\n\n      } else\n      {\n         value = transposeBoolToValue( value );\n      }\n\n      let cmd = accessory.state_cmd_prefix + accessory.state_cmd + \" Set '\" + accessory.displayName + \"' '\" + characteristicString + \"' '\" + value + \"'\" + accessory.state_cmd_suffix;\n\n      // My AdvAir friends want to allow single quotes in accessory names, which\n      // may have consequences with globbing for others.\n      if ( accessory.state_cmd.match( /AdvAir.sh/ ) )\n      {\n          cmd = accessory.state_cmd_prefix + accessory.state_cmd + ' Set \"' + accessory.displayName + '\" ' + \"'\" + characteristicString + \"' '\" + value + \"'\" + accessory.state_cmd_suffix;\n      }\n\n      if ( accessory.hV.statusMsg == \"TRUE\" )\n         self.log.info( chalk.blue( `Setting ${ self.displayName } ${ characteristicString }` ) + ` ${ value }` );\n\n      if ( settings.cmd4Dbg ) self.log.debug( `setValue: accTypeEnumIndex:( ${ accTypeEnumIndex } )-\"${ characteristicString }\" function for: ${ self.displayName } ${ value }  cmd: ${ cmd } timeout: ${ timeout }` );\n\n      // Execute command to Set a characteristic value for an accessory\n      let child = exec( cmd, { timeout: timeout }, function ( error, stdout, stderr )\n      {\n         if ( stderr )\n            if ( queue.echoE ) self.log.error( `setValue: ${ characteristicString } function for ${ self.displayName } streamed to stderr: ${ stderr }` );\n\n         if ( error )\n            if ( queue.echoE  ) self.log.error( chalk.red( `setValue ${ characteristicString } function failed for ${ self.displayName } cmd: ${ cmd } Failed.  Error: ${ error.message }` ) );\n\n      }).on( \"close\", ( code ) =>\n      {\n         if ( code != 0 )\n         {\n            if ( child.killed == true )\n            {\n               if ( queue.echoE  ) self.log.error( chalk.red( `setValue ${ characteristicString } function failed for ${ self.displayName } cmd: ${ cmd } Failed.  Error: ${ code } ${ constants.DBUSY }` ) );\n\n               queueCallback( constants.ERROR_TIMER_EXPIRED );\n\n               return;\n            }\n\n            queueCallback( code );\n\n            return;\n         }\n\n         queueCallback( code );\n\n      });\n   }\n\n   // The queue is self maintaining, except for lowPriorityEntries\n   // which if passed in, must be rescheduled as they go by their own\n   // intervals and thus must handle the return code.\n   processWormQueue( lastTransactionType, queue, lowPriorityEntry = null )\n   {\n      // \"WoRm\", No matter what, only one \"Set\" allowed\n      if ( queue.inProgressSets > 0 )\n      {\n         // if ( settings.cmd4Dbg ) queue.log.debug(`processWormQueue queue.inProgressSets > 0 : ${queue.inProgressSets}`);\n \n         // We are *NOT* processing the low prioirity queue entry\n         return false;\n      }\n\n      // It is not a good time to do a anything, so skip it\n      if ( queue.lastGoodTransactionTime == 0 )\n      {\n         // if ( settings.cmd4Dbg ) queue.log.debug(`processWormQueue queue.lastGoodTransactionTime == 0`);\n\n         // We are *NOT* processing the low prioirity queue entry\n         return false;\n      }\n\n      if ( queue.highPriorityQueue.length > 0 )\n      {\n         let nextEntry = queue.highPriorityQueue[ 0 ];\n\n         if ( nextEntry.isSet == true )\n         {\n            // If already in progress, when they finish they will restart the queue\n            // Otherwise continuing will purge the next item from the queue as it\n            // cannot be run with an entry already in progress.\n            if ( nextEntry.accessory.queue.inProgressSets > 0 ||\n                 nextEntry.accessory.queue.inProgressGets > 0 )\n            {\n               // Return as queue is busy.\n               // Return false as we are *NOT* processing the low prioirity queue entry\n               // if ( settings.cmd4Dbg ) queue.log.debug(`processWormQueue queue.inProgressSets> 0 ${ nextEntry.accessory.queue.inProgressSets } ${ nextEntry.accessory.queue.inProgressGets }`);\n\n               return false;\n            }\n\n            queue.processHighPrioritySetQueue( queue.highPriorityQueue.shift( ) );\n\n            // Return false as we are *NOT* processing the low prioirity queue entry\n            return false;\n         }\n\n         // This must be a \"Get\". Process them all.\n         let max = queue.highPriorityQueue.length;\n\n         while( queue.highPriorityQueue.length > 0 &&\n                nextEntry.isSet == false &&\n                max >= 1 )\n         {\n            queue.processHighPriorityGetQueue( queue.highPriorityQueue.shift( ) );\n            nextEntry = queue.highPriorityQueue[ 0 ];\n            max--;\n         }\n\n         // Return false as we are *NOT* processing the low prioirity queue entry\n         return false;\n\n      } else  if ( lastTransactionType == HIGH_PRIORITY_SET ||\n                   lastTransactionType == HIGH_PRIORITY_GET )\n      {\n         // Return false as we are *NOT* processing the low prioirity queue entry\n         return false;\n      }\n      // This is self evident, until their are other types of Prioritys\n      if ( lastTransactionType == LOW_PRIORITY_GET &&\n           lowPriorityEntry != null &&\n           queue.queueStarted == true )\n      {\n         queue.processEntryFromLowPriorityQueue( lowPriorityEntry );\n\n         // We are processing the low priority queue entry.\n         return true;\n\n      } else {\n          if ( lastTransactionType == LOW_PRIORITY_GET &&\n               queue.queueStarted == false )\n          {\n             // Return false as we are *NOT* processing the low prioirity queue entry\n             return false;\n\n          } if ( queue.inProgressGets == 0 &&\n                 queue.inProgressSets == 0 )\n          {\n             // Return false as we are *NOT* processing the low prioirity queue entry\n             return false;\n\n          } else {\n             if ( settings.cmd4Dbg ) this.log.debug( `Unhandled lastTransactionType: ${ lastTransactionType } inProgressSets: ${  queue.inProgressSets } inProgressGets: ${  queue.inProgressGets } queueStarted: ${ queue.queueStarted } lowQueueLen: ${ queue.lowPriorityQueue.length } hiQueueLen: ${ queue.highPriorityQueue.length }` );\n\n          }\n      }\n   }\n\n   // The queue is self maintaining, except for lowPriorityEntries\n   // which if passed in, must be rescheduled as they go by their own\n   // intervals and thus must handle the return code.\n   processSequentialQueue( lastTransactionType, queue, lowPriorityEntry = null )\n   {\n      // Sequential, No matter what, only one transaction allowed\n      if ( queue.inProgressSets > 0 ||\n           queue.inProgressGets > 0 )\n         // Return false as we are *NOT* processing the low prioirity queue entry\n         return false;\n\n      // It is not a good time to do a anything, so skip it\n      if ( queue.lastGoodTransactionTime == 0 )\n         // Return false as we are *NOT* processing the low prioirity queue entry\n         return false;\n\n      if ( queue.highPriorityQueue.length > 0 )\n      {\n         let nextEntry = queue.highPriorityQueue[ 0 ];\n\n         if ( nextEntry.isSet == true )\n         {\n            queue.processHighPrioritySetQueue( queue.highPriorityQueue.shift( ) );\n\n            // Return false as we are *NOT* processing the low prioirity queue entry\n            return false;\n\n         }\n\n         // Has to be a High Priority \"Get\" entry. Process just this one.\n         queue.processHighPriorityGetQueue( queue.highPriorityQueue.shift( ) );\n\n         // Return false as we are *NOT* processing the low prioirity queue entry\n         return false;\n\n      } else  if ( lastTransactionType == HIGH_PRIORITY_SET ||\n                   lastTransactionType == HIGH_PRIORITY_GET )\n      {\n         // Return false as we are *NOT* processing the low prioirity queue entry\n         return false;\n      }\n      // This is self evident, until their are other types of Prioritys\n      if ( lastTransactionType == LOW_PRIORITY_GET &&\n           lowPriorityEntry != null &&\n           queue.queueStarted == true )\n      {\n         queue.processEntryFromLowPriorityQueue( lowPriorityEntry );\n\n         // We are processing the low priority queue entry.\n         return true;\n\n      } else {\n          if ( lastTransactionType == LOW_PRIORITY_GET &&\n               queue.queueStarted == false )\n          {\n             // Return false as we are *NOT* processing the low prioirity queue entry\n             return false;\n\n          } if ( queue.inProgressGets == 0 &&\n                 queue.inProgressSets == 0 )\n          {\n             // Return false as we are *NOT* processing the low prioirity queue entry\n             return false;\n\n          } else {\n             if ( settings.cmd4Dbg ) this.log.debug( `Unhandled lastTransactionType: ${ lastTransactionType } inProgressSets: ${  queue.inProgressSets } inProgressGets: ${  queue.inProgressGets } queueStarted: ${ queue.queueStarted } lowQueueLen: ${ queue.lowPriorityQueue.length } hiQueueLen: ${ queue.highPriorityQueue.length }` );\n\n          }\n      }\n   }\n\n   // The standard queue is just free running, except if the queue has not\n   // been started yet.\n   processPassThruQueue( lastTransactionType, queue, lowPriorityEntry = null )\n   {\n      if ( lastTransactionType == LOW_PRIORITY_GET &&\n           lowPriorityEntry != null &&\n           queue.queueStarted == true )\n      {\n         queue.processEntryFromLowPriorityQueue( lowPriorityEntry );\n      }\n\n      if ( queue.highPriorityQueue.length > 0 )\n      {\n         let nextEntry = queue.highPriorityQueue[ 0 ];\n\n         if ( nextEntry.isSet == true )\n         {\n\n            queue.processHighPrioritySetQueue( queue.highPriorityQueue.shift( ) );\n         }\n         else\n         {\n            queue.processHighPriorityGetQueue( queue.highPriorityQueue.shift( ) );\n         }\n      }\n   }\n\n   scheduleLowPriorityEntry( entry )\n   {\n      let accessory = entry.accessory;\n      let queue = entry.accessory.queue;\n\n      if ( settings.cmd4Dbg ) accessory.log.debug( `Scheduling Poll of index: ${ entry.accTypeEnumIndex } characteristic: ${ entry.characteristicString } for: ${ accessory.displayName } timeout: ${ entry.timeout } interval: ${ entry.interval }` );\n\n      // Clear polling\n      if ( queue.listOfRunningPolls &&\n           queue.listOfRunningPolls[ accessory.displayName + entry.accTypeEnumIndex ] == undefined )\n              clearTimeout( queue.listOfRunningPolls[ accessory.displayName + entry.accTypeEnumIndex ] );\n\n      queue.listOfRunningPolls[ accessory.displayName + entry.accTypeEnumIndex ] = setTimeout( ( ) =>\n      {\n         // If the queue was busy/not available, schedule the entry at a later time\n         if ( queue.processQueueFunc( LOW_PRIORITY_GET, queue, entry ) == false )\n         {\n            if ( settings.cmd4Dbg ) accessory.log.debug( `processsQueue returned false` );\n\n            queue.scheduleLowPriorityEntry( entry );\n         }\n\n      }, entry.interval);\n   }\n\n\n   pauseQueue( queue )\n   {\n      if ( queue.queueType == constants.QUEUETYPE_STANDARD )\n         return;\n\n      queue.lastGoodTransactionTime = 0;\n\n      if ( queue.pauseTimer == null )\n      {\n         queue.pauseTimer = setTimeout( ( ) =>\n         {\n             // So we do not trip over this again immediately\n             queue.lastGoodTransactionTime = Date.now( );\n             queue.pauseTimer = null;\n\n             queue.processQueueFunc( HIGH_PRIORITY_GET, queue );\n\n          }, queue.pauseTimerTimeout );\n      }\n   }\n\n   printQueueStats( queue )\n   {\n      let line = `QUEUE \"${ queue.queueName }\" stats`;\n      this.log.info( line );\n      this.log.info( `${ \"=\".repeat( line.length ) }` );\n      this.log.info( \"No longer applicable\" );\n   }\n   dumpQueue( queue )\n   {\n      let line = `Low Priority Queue \"${ queue.queueName }\"`;\n      this.log.info( line );\n      this.log.info( `${ \"=\".repeat( line.length ) }` );\n      queue.lowPriorityQueue.forEach( ( entry, entryIndex ) =>\n      {\n         this.log.info( `${ entryIndex } ${ entry.accessory.displayName } characteristic:  ${ entry.characteristicString } accTypeEnumIndex: ${ entry.accTypeEnumIndex } interval: ${ entry.interval } timeout: ${ entry.timeout }` );\n      } );\n   }\n\n   startQueue( queue, allDoneCallback )\n   {\n      queue.lowPriorityQueueIndex = 0 ;\n\n      let delay = 0;\n      let staggeredDelays = [ 3000, 6000, 9000, 12000 ];\n      let staggeredDelaysLength = staggeredDelays.length;\n      let staggeredDelayIndex = 0;\n      let lastAccessoryUUID = \"\"\n      let allDoneCount = 0;\n\n      if ( settings.cmd4Dbg ) this.log.debug( `enablePolling for the first time` );\n\n      // If there is nothing in the lowPriorityQueue, we are dome.\n      // Demo mode or Unit testing.\n      if ( queue.lowPriorityQueue.length == 0 )\n      {\n\n         allDoneCallback( allDoneCount );\n         setTimeout( ( ) => { queue.processQueueFunc( HIGH_PRIORITY_GET, queue ); }, 0 );\n\n      } else\n      {\n         queue.lowPriorityQueue.forEach( ( entry, entryIndex ) =>\n         {\n            allDoneCount ++;\n            setTimeout( ( ) =>\n            {\n               if ( entryIndex == 0 && settings.cmd4Dbg )\n               {\n                  if ( queue.queueType == constants.QUEUETYPE_WORM ||\n                       queue.queueType == constants.QUEUETYPE_WORM2\n                     )\n                  {\n                     entry.accessory.log.debug( `Started staggered kick off of ${ queue.lowPriorityQueue.length } polled characteristics for queue: \"${ entry.accessory.queue.queueName }\"` );\n                  } else\n                  {\n                     entry.accessory.log.debug( `Started staggered kick off of ${ queue.lowPriorityQueue.length } polled characteristics for \"${ entry.accessory.displayName }\"` );\n                  }\n               }\n\n               if ( settings.cmd4Dbg ) entry.accessory.log.debug( `Kicking off polling for: ${ entry.accessory.displayName } ${ entry.characteristicString } interval:${ entry.interval }, staggered:${ staggeredDelays[ staggeredDelayIndex ] }` );\n\n               queue.scheduleLowPriorityEntry( entry );\n\n               if ( entryIndex == queue.lowPriorityQueue.length -1 )\n               {\n                  if ( settings.cmd4Dbg )\n                  {\n                     if ( queue.queueType == constants.QUEUETYPE_WORM ||\n                          queue.queueType == constants.QUEUETYPE_WORM2\n                        )\n                     {\n                        entry.accessory.log.debug( `All characteristics are now being polled for queue: \"${ queue.queueName }\"` );\n                     }\n                     else\n                     {\n                        entry.accessory.log.debug( `All characteristics are now being polled for \"${ entry.accessory.displayName }\"` );\n                     }\n                  }\n                  allDoneCallback( allDoneCount );\n               }\n\n            }, delay );\n\n            if ( staggeredDelayIndex++ >= staggeredDelaysLength )\n               staggeredDelayIndex = 0;\n\n            if ( lastAccessoryUUID != entry.accessory.uuid )\n               staggeredDelayIndex = 0;\n\n            lastAccessoryUUID = entry.accessory.uuid;\n\n            delay += staggeredDelays[ staggeredDelayIndex ];\n\n         });\n      }\n\n      queue.queueStarted = true;\n   }\n\n   changeQueueType( queue, queueType )\n   {\n      if ( queue.queueStarted )\n         throw new Error( `Cannot change queueType when queue is running` );\n\n      // The WoRm queue needs error messages to be silenced as\n      // they are inevitable, but are handled through retries\n      // By default non WoRm queus are allowed to echo errors\n      this.echoE = true;\n\n      // Default\n      this.processQueueFunc = this.processWormQueue;\n      switch ( queueType )\n      {\n         case constants.QUEUETYPE_SEQUENTIAL:\n            this.processQueueFunc = this.processSequentialQueue;\n            break;\n         case constants.QUEUETYPE_WORM:\n         case constants.QUEUETYPE_WORM2:\n            this.processQueueFunc = this.processWormQueue;\n            // When not in debug mode, do not echo errors for the WoRm queue\n            // as errors are handled through retries.\n            if ( ! settings.cmd4Dbg )\n               this.echoE = false;\n            break;\n         case constants.QUEUETYPE_STANDARD:\n            // only polled entries go straight through the queue\n            this.processQueueFunc = this.processPassThruQueue;\n            break;\n         case constants.QUEUETYPE_PASSTHRU:\n            // entries go straight through the queue\n            this.processQueueFunc = this.processPassThruQueue;\n            break;\n         default:\n            this.log.error( `Error: Invalid queue type: ${ queueType }` );\n      }\n   }\n\n   isCharacteristicPolled( accTypeEnumIndex, queue, accessory )\n   {\n       if ( queue.lowPriorityQueue.filter(\n               entry => entry.accessory.uuid == accessory.uuid &&\n               entry.accTypeEnumIndex == accTypeEnumIndex\n            ).length == 0 )\n       {\n          return false;\n       }\n\n       return true;\n   }\n}\n\nvar queueExists = function( queueName )\n{\n   return settings.listOfCreatedPriorityQueues[ queueName ];\n}\n\nvar addQueue = function( log, queueName, queueType = constants.DEFAULT_QUEUE_TYPE, queueRetryCount = constants.DEFAULT_WORM_QUEUE_RETRY_COUNT )\n{\n   let queue = queueExists( queueName );\n   if ( queue != undefined )\n      return queue;\n\n   log.debug( `Creating new Priority Polled Queue \"${ queueName }\" with QueueType of: \"${ queueType }\" retryCount: ${queueRetryCount}` );\n\n   queue = new Cmd4PriorityPollingQueue( log, queueName, queueType, queueRetryCount );\n   settings.listOfCreatedPriorityQueues[ queueName ] = queue;\n\n   return queue;\n\n}\n\n\n\nvar parseAddQueueTypes = function ( log, entrys )\n{\n   if ( trueTypeOf( entrys ) != Array )\n      throw new Error( `${ constants.QUEUETYPES } is not an Array of { \"Queue Name\": \"QueueType\" }. found: ${ entrys }` );\n\n   entrys.forEach( ( entry, entryIndex ) =>\n   {\n      let queueName = null;\n      let queueType = constants.DEFAULT_QUEUE_TYPE;\n      let queueRetryCount = constants.DEFAULT_WORM_QUEUE_RETRY_COUNT;\n\n      for ( let key in entry )\n      {\n         let lcKey = lcFirst( key );\n\n         // warn now\n         if ( key.charAt( 0 ) === key.charAt( 0 ).toUpperCase( ) )\n         {\n            log.warn( `The config.json queueTypes key: ${ key } is Capitalized.  All keys in the near future will ALWAYS start with a lower case character for homebridge-ui integration.\\nTo remove this Warning, Please fix your config.json.` );\n         }\n\n         let value = entry[ key ];\n\n         switch( lcKey )\n         {\n            case constants.QUEUE:\n               if ( settings.listOfCreatedPriorityQueues[ entry.queue ] )\n                  throw new Error( `QueueName: ${ entry.queue } was added twice` );\n\n               queueName = value;\n\n               break;\n            case constants.QUEUETYPE:\n               // Set the default Queue Retry Count based on QueueType\n               switch ( value )\n               {\n                  case constants.QUEUETYPE_WORM:\n                     queueRetryCount = constants.DEFAULT_WORM_QUEUE_RETRY_COUNT;\n                     queueType = value;\n                     break;\n                  case constants.QUEUETYPE_WORM2:\n                     queueRetryCount = constants.DEFAULT_WORM_QUEUE_RETRY_COUNT;\n                     queueType = value;\n                     break;\n                  case constants.QUEUETYPE_SEQUENTIAL:\n                     queueRetryCount = constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT;\n                     queueType = value;\n                     break;\n                  case constants.QUEUETYPE_STANDARD:\n                     queueRetryCount = constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT;\n                     queueType = value;\n                     break;\n                  default:\n                     throw new Error( `QueueType: ${ entry.queueType } is not valid at index: ${ entryIndex }. Expected: ${ constants.QUEUETYPE_WORM }, ${ constants.QUEUETYPE_WORM2 } or ${ constants.QUEUETYPE_SEQUENTIAL }` );\n               }\n\n               break;\n            case constants.QUEUE_RETRIES:\n               queueRetryCount = value;\n               break;\n            default:\n               throw new Error( `Unknown Queue option\"${ key }  not provided at index ${ entryIndex }` );\n         }\n      }\n\n      // At least a Queue name must be defined, the rest are defaulted\n      if ( queueName == null )\n         throw new Error( `\"${ constants.QUEUE }\"  not provided at index ${ entryIndex }` );\n\n      if ( settings.cmd4Dbg ) log.debug( `calling addQueue: ${ queueName } type: ${ queueType } retryCount: ${ queueRetryCount }` );\n\n      addQueue( log, queueName, queueType, queueRetryCount );\n   } );\n}\n\n\nmodule.exports = { addQueue,\n                   parseAddQueueTypes,\n                   queueExists,\n                   Cmd4PriorityPollingQueue\n                 }\n"
  },
  {
    "path": "Extras/Cmd4Scripts/CheckYourScript.sh",
    "content": "#!/bin/bash --noprofile --norc\n\n# Fun colour & cursor stuff\nTCR=$(tput cr)\nTCLR=$(tput clear)\nTBLD=$(tput bold)\nTNRM=$(tput sgr0)\nTBLK=$(tput setaf 0)\nTRED=$(tput setaf 1)\nTGRN=$(tput setaf 2)\nTYEL=$(tput setaf 3)\nTBLU=$(tput setaf 4)\nTMAG=$(tput setaf 5)\nTCYN=$(tput setaf 6)\nTWHT=$(tput setaf 7)\n\n# OS type for flavours of different commands (like date on OSX)\ncase $(uname | tr '[:upper:]' '[:lower:]') in\n  solaris*)\n     date_cmd=\"date -u +%s.%N\"\n  ;;\n  darwin*)\n     # OSX does not have msec\n     date_cmd=\"date -u +%s\"\n  ;; \n  linux*)\n     date_cmd=\"date -u +%s.%N\"\n  ;;\n  bsd*)\n     date_cmd=\"date -u +%s.%N\"\n  ;;\n  msys*)\n     date_cmd=\"date -u +%s.%N\"\n  ;;\n  *)\n     echo \"unknown: OSTYPE:$OSTYPE\"\n     exit -1\n  ;;\nesac\n\nprintf \"${TCLR}\"\n\nif [ \"${1}\" = '-h' ]; then\n   printf \"${TBLU}Usage:${TNRM}\"\n   printf \"${TNRM}  SHELL> cd \\n\"\n   printf \"${TNRM}  SHELL> bash --noprofile --norc \\n\"\n   printf \"\\n\"\n   printf \"${TBLU}Syntax:${TNRM}\\n\"\n   printf \"  ${TBLU}${0}${TNRM} 'full state command'\\n\"\n   printf \"${TBLU}i.e.${TNRM}\\n\"\n   printf \"  '.homebridge/Cmd4Scripts/CheckYourScript.sh' 'bin/MyExec' 'Get' 'MyDevice' 'On'\\n\"\n   printf \"     or\\n\"\n   printf \"  '.homebridge/Cmd4Scripts/CheckYourScript.sh' 'bash bin/YourScript.sh' 'Get' 'MyDevice' 'On'\\n\"\n   printf \"     or\\n\"\n   printf \"  '.homebridge/Cmd4Scripts/CheckYourScript.sh' 'bin/YourScript.sh 'Get 'MyDevice' 'On'\\n\"\n   printf \"\\n\"\n   printf \"Note: Add the '' around the command to prevent globbing, which is not done by homebridge-cmd4\\n\"\n   exit 0\nfi\n\n# Processes are run from your home directory, so go there first.\ncd \"${HOME}\"\nprintf \"${TBLU}Changing to:${TNRM}'${HOME}' ${TBLU}where processes are run from${TNRM}\\n\"\n\n# $HOME is expanded by the shell and not scripts, so do not rely on it.\nunset HOME\n\nprintf \"${TBLU}Enviroment in shell is limited to these variables:${TNRM}\\n\"\nenv\n\nprintf \"\\n\"\n\nprintf \"${TBLU}Command will be run from the directory: ${TNRM}${PWD}\\n\"\n\noutput=\"\"\nrc=0\n\nif [ \"$2\" = 'Set' ] || [ \"$3\" = 'Set' ]; then\n   printf \"${TBLU}(Set) Cmd4 would execute:${TNRM} $* \"\n   printf \"\\n\"\n\n   start_time=\"$( $date_cmd )\"\n   output=$(\"$@\")\n   rc=\"$?\"\n   end_time=\"$( $date_cmd )\"\n\n   # The elapsed time (in microseconds)\n   # We add 1 second as OSX does not have msec dates.\n   # One second will make no difference, but might help a newbie.\n   elapsed=( $(/usr/bin/bc <<<\"($end_time-$start_time) * 1000 + 1000\") ) \n\n   printf \"\\n\"\n   if [ $rc = 0 ]; then\n      printf \"${TGRN}Command passed with returned code:${TNRM}'${rc}'\\n\"\n      if [ \"${output}\" != \"\" ]; then\n         printf \"Output: '${output}' would be ignored\\n\"\n      fi\n      printf \"$TBLU}The timeout value should be at least :${TNRM} ${elapsed} (microseconds)\\n\"\n      printf \"$TBLU}Multiply by 5 for safety.${TNRM}\\n\"\n   else\n      printf \"${TRED}Command given did not exit with a ${TNRM}0${TRED} return code and would fail in homebridge-cmd4 rc=${TNRM}'${rc}'\\n\"\n      printf \"Understand that the error given is a result of running your command in a basic shell environment.  Head the errors given\\n\"\n   fi\nelse\n   printf \"${TBLU}(Get) Cmd4 would execute:${TNRM} $*\"\n   printf \"\\n\"\n\n   start_time=\"$( $date_cmd )\"\n   output=$(\"$@\")\n   rc=\"$?\"\n   end_time=\"$( $date_cmd )\"\n\n   # The elapsed time (in microseconds)\n   # We add 1 second as OSX does not have msec dates.\n   elapsed=( $(/usr/bin/bc <<<\"($end_time-$start_time) * 1000 + 1000\") ) \n\n   printf \"\\n\"\n   wordCount=0\n   if [ $rc = 0 ]; then\n      printf \"${TGRN}Command passed with returned code:${TNRM}'${rc}'\\n\"\n      printf \"${TBLU}Output: of command was:${TNRM}'${output}'\\n\"\n      wordCount=$(IFS=' '; set -f; set -- \"${output}\"; echo $#)\n      if [ \"${wordCount}\" != '1' ]; then\n         printf \"${TYEL}Word count of output should only be 1, not ${TNRM}'${wordCount}'\\n\"\n      fi\n      printf \"$TBLU}The timeout value should be at least :${TNRM} ${elapsed} (microseconds)\\n\"\n      printf \"$TBLU}Multiply by 5 for safety.${TNRM}\\n\"\n   else\n      printf \"${TRED}Command given did not exit with a ${TNRM}0${TRED} return code and would fail in homebridge-cmd4 rc=${TNRM}'${rc}'\\n\"\n      printf \"Understand that the error given is a result of running your command in a basic shell environment.  Head the errors given\\n\"\n   fi\nfi\n\n\nexit ${rc}\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/AirPurifier.js",
    "content": "#!/usr/bin/env node\n//  State.js\n//\n// Description:\n//   This script *CAN* be called by the HomeBridge plugin Cmd4 as defined in your config.json\n//   file.  The purpose is to fake the existance of an accessory or to be modified by you\n//   such that acessories can Get/Set characteristics as defined in the HomeKit Accessory\n//   Specifications.\n//\n// Plugin Installation:\n//   - npm install [-g] Cmd4\n//   - mkdir $HOME/.homebridge/Cmd4Scripts\n//   - cp State.js  $HOME/.homebridge/Cmd4Scripts/State.js\n//   - chmod u+x $HOME/.homebridge/Cmd4Scripts/State.js\n//\n// Parameters are:\n//    Get <Accessory name> <Characteristic>\n//    Set <Accessory name> <Characteristic> <value>\n//\n// Note 1: These paramaters match the those of the Cmd4 plugin.\n// Note 2: All characteristics of the HomeKit Accessory Protocol (HAP)\n//         specifications are supported, except for camera streaming;\n//         Though I have found some like LockManagement are not within IOS.\n//         Side Note: The Eve app is nicer, try it.\n// Note 3: The Hap spec is quoted throughout, but this is not the spec so\n//         this is not gauranteed to be correct.\n// Note 4: In this latest version, State.js does not care which characteristic\n//         belongs with a specific accessssory for the purpose of creating\n//         custom accessories.  IOS would not like this, but if you use\n//         the provided config.json file that defines the corrrect characteristics,\n//         this will not matter.\n//\n// How it works:\n//    A characteristic value is stored in the $HOME/.homebridge/Cmd4Scripts/Cmd4States in\n//    the file named \"Status + <Accessory Name> _ <Characteristic>\" and is returned or\n//    written to based on the <Get|Set> option.\n//\n//    For example:   node State.js Set My_Door MotionDetected 0\n//       will create the file .homebridge/Cmd4Scripts/Cmd4States/My_Door_MotionDetected\n//       with the contents of \"0\"\n//       Note: See how this is run from $HOME (Important!)\n//\n// Environmental Variables Used:\n//    $HOME - to create path to .homebridge\n//\n//\n// Interesting fact.  If you use characteristics as is, and define all possible accessories in your config.json\n//                    file, they will all appear fully functional within HomeKit. In this way you\n//                    can play with HomeKit and not have any physical devices at all.  Cool Eh!\n//\n// *IMPORTANT* - I cannot audit commented constants.  The lib/CMD4_DEVICE_ENUM.js is what is used\n//               for constant translations.\n\n'use strict';\n\n// FileSystem requirements.\nvar fs = require('fs');\nvar path = require('path');\nvar os = require('os');\n\n// The files created within Cmd4StatesPath contain just a value of the accessories last state,\n// so they are very small in size.\nvar Cmd4StatesPath =  path.join(os.homedir(), \".homebridge/Cmd4Scripts/Cmd4States\");\n\nvar length = process.argv.length;\nvar device = \"\";\nvar io = \"\";\nvar characteristic = \"\";\nvar option = \"\";\n\nif ( length == 2 ) process.exit( 0 );\n\nif ( length <= 2 ) {\n    process.stdout.write( `Usage: ${ process.argv[ 0 ] } <Get> <AccessoryName> <Characteristic>` );\n    process.stdout.write( `       ${ process.argv[ 0 ] } <Set> <AccessoryName> <Characteristic> <Value>` );\n    process.exit(-1);\n}\n\nif ( length >= 2 ) io = process.argv[ 2 ];\nif ( length >= 3 ) device = process.argv[ 3 ];\nif ( length >= 4 ) characteristic  = process.argv[ 4 ];\nif ( length >= 5 ) option  = process.argv[ 5 ];\n\n// Placing the states in a subdirectory makes things look cleaner.\n// Some platforms require an exception handler\nconst mkdirSync = function( dirPath )\n{\n    try {\n        fs.mkdirSync( dirPath )\n    } catch ( err ) {\n        if ( err.code !== 'EEXIST' )\n        {\n            process.stdout.write( `mkdir failed: ${ dirPath }`);\n            throw err;\n        } else {\n            // directory already exists - OK\n        }\n    }\n}\n\nmkdirSync( Cmd4StatesPath );\n\n\n// Such a simple way to store state information that is small and fast!\n// Put exception handling here too. Just in case!\nfunction writeData( a, b,c )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n\n   try {\n       fs.writeFileSync( fn,c );\n   } catch (err) {\n       if ( err.code !== 'EEXIST' )\n       {\n          process.stdout.write( `write data failed: ${ fn }  data: ${ c }` );\n          throw err;\n       } else {\n          // file already exists - OK\n       }\n   }\n}\n\n// Read the state information.  If there is none, just return what\n// was expected.\n// Put exception handling here too. Just in case!\nfunction readData( a, b )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n   c = \"\";\n\n   try {\n      c = String( fs.readFileSync( fn, 'utf8' ) );\n   } catch (err) {\n      if ( err.code === 'ENOENT' ) {\n         // This is OK. just return what was expected.\n         return c;\n      } else\n      {\n         if ( err.code !== 'EEXIST' )\n         {\n            process.stdout.write( `read data failed: ${ fn }` );\n            throw err;\n         } else {\n            // file already exists - OK\n         }\n      }\n   }\n\n   return c;\n}\n\nvar c = \"\";\n\nswitch( io )\n{\n   case \"Get\":\n   {\n      switch( characteristic )\n      {\n         case \"Active\":   // 3\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 000000B0-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.active\n            // Permissions: Paired Write, Paired Read, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 1\n            // Step Value: 1\n\n            // Valid Values\n            // 0 - \"INACTIVE\"\n            // 1 - \"ACTIVE\"\n\n            break;\n         }\n         case \"CurrentAirPurifierState\":   // 34\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 000000A9-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.air-purifier.state.current\n            // Permissions: Paired Read, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 2\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"INACTIVE\"\n            // 1 - \"IDLE\"\n            // 2 - \"PURIFYING_AIR\"\n\n            break;\n         }\n         case \"LockPhysicalControls\":   // 86\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 000000A7-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.lock-physical-controls\n            // Permissions: Paired Write,Paired Read, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 1\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"CONTROL_LOCK_DISABLED\" - Control lock disabled\n            // 1 - \"CONTROL_LOCK_ENABLED\" - Control lock enabled\n\n            break;\n         }\n         case \"Name\":   // 97\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( `\"${ device }\"` ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 00000023-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.name\n            // Permissions: Paired Read, Notify\n\n            // Format: string\n\n            // Maximum Length: 64\n\n            break;\n         }\n         case \"RotationSpeed\":   // 139\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 00000029-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.rotation.speed\n            // Permissions: Paired Read, Paired Write, Notify\n\n            // Format: float\n\n            // Minimum Value: 0\n            // Maximum Value: 100\n            // Step Value: 1\n            // Unit: percentage\n\n            break;\n         }\n         case \"SwingMode\":   // 180\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 000000B6-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.swing-mode\n            // Permissions: Paired Read, Notify, Paired Write\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 1\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"SWING_DISABLED\"\n            // 1 - \"SWING_ENABLED\"\n\n            break;\n         }\n         case \"TargetAirPurifierState\":   // 181\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 000000A8-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.air-purifier.state.target\n            // Permissions: Paired Write,Paired Read, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 1\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"MANUAL\"\n            // 1 - \"AUTO\"\n\n            break;\n         }\n         default:\n            process.stderr.write( `Unknown Characteristic for: ${ io } Device: ${ device } Characteristic: ${ characteristic }` );\n            process.exit( -1 );\n       }\n\n       break;\n\n   } // End of Switch for \"Get\"\n   case \"Set\":\n   {\n      switch( characteristic )\n      {\n         case \"Active\":   // 3\n         {\n            writeData( device, characteristic, option );\n\n            // Off\n            if ( option == 0 )\n            {\n               // InActive - 0\n               writeData( device, \"CurrentAirPurifierState\", 0 );\n               // Auto Mode - 1\n               writeData( device, \"TargetAirPurifierState\", 1 );\n            } else // On\n            {\n               // Purifying Air - 2\n               writeData( device, \"CurrentAirPurifierState\", 2 );\n               // Auto Mode - 1\n               writeData( device, \"TargetAirPurifierState\", 1 );\n            }\n\n            break;\n         }\n         case \"CurrentAirPurifierState\":   // 34\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"LockPhysicalControls\":   // 86\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Name\":   // 97\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"RotationSpeed\":   // 139\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SwingMode\":   // 180\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"TargetAirPurifierState\":   // 181\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentAirPurifierState\", option);\n\n            break;\n         }\n         default:\n            process.stderr.write( `Unknown Characteristic for: ${ io } Device:${ device  } Characteristic:${ characteristic }` );\n            process.exit( -1 );\n      }\n\n      break;\n   } // End of Switch Device for \"Set\"\n   default:\n      process.stderr.write( `Unknown IO ${ io }` );\n      process.exit( -1 );\n}\n\n//process.stdout.write( `Say What Device: ${ device } Characteristic: ${ characteristic } Option: ${ option }` );\n\nprocess.exit( 0 );\n\n\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/AnyDevice",
    "content": "#!/usr/bin/env node\n\n/*\n\n   AnyDevice\n   =========\n\n   Description:\n   ============\n   This script is used to fake any Cmd4 devices Get/Set requests.\n   Most characteristics just return 0.\n\n   Parameters:\n   ===========\n      Get < Any accessory name > < Characteristic >\n      Set < Any accessory name > < Characteristic > < value >\n\n   Notes:\n   =====\n   1) These paramaters match the those of the Cmd4 plugin.\n\n   How it works:\n   ============\n   A characteristic value is stored in\n   $HOME/.homebridge/Cmd4Scripts/Cmd4States in a file named\n   \"Status_ + <device> _ <Characteristic>\" and is returned or\n   written to based on the <Get|Set> option.\n\n   Example:\n   =======\n      ./AnyDevice Set My_Door MotionDetected 0\n\n   Files Created:\n   =============\n   ${ HOME }/.homebridge/Cmd4Scripts/Cmd4States/Status_My_Door\n   with the contents of \"0\", the Characteristic value of the\n   device sent.\n\n   Environmental Variables Used:\n   ============================\n   $HOME - Used to get the path to .homebridge\n\n*/\n\n\n\n'use strict';\n\n// FileSystem requirements.\nvar fs = require( 'fs' );\nvar path = require( 'path' );\nvar os = require( 'os' );\n\n// The files created within Cmd4StatesPath contain just a\n// value of the accessories last state, so they are very\n// small in size.\nvar Cmd4StatesPath =  path.join( os.homedir( ), \".homebridge/Cmd4Scripts/Cmd4States\" );\n\nlet length = process.argv.length;\nlet device;\nlet io;\nlet characteristic;\nlet option = \"\";\n\nfunction showHelp( )\n{\n   process.stdout.write( `Usage:\n      AnyDevice < Get > < AccessoryName > < Characteristic >\n      AnyDevice < Set > < AccessoryName > < Characteristic > < Value >\n`);\n}\n\nif ( length <= 4 )\n{\n   showHelp( );\n   process.exit( 1);\n}\n\nio = process.argv[ 2 ];\ndevice = process.argv[ 3 ];\ncharacteristic = process.argv[ 4 ];\nif ( io == \"Set\" )\n{\n   if ( length > 5 )\n   {\n      option = process.argv[ 5 ];\n   } else\n   {\n      showHelp( );\n      process.exit( 1 );\n   }\n}\n\n// Placing the states in a subdirectory makes things look cleaner.\n// Some platforms require an exception handler\nconst mkdirSync = function ( dirPath )\n{\n    try {\n        fs.mkdirSync( dirPath )\n    } catch ( err ) {\n        if ( err.code !== 'EEXIST' )\n        {\n            process.stdout.write( \"mkdir failed: \" + dirPath );\n            throw err;\n        } else {\n            // directory already exists - OK\n        }\n    }\n}\n\nmkdirSync( Cmd4StatesPath );\n\n\n// Such a simple way to store state information that is small and fast!\n// Put exception handling here too. Just in case!\nfunction writeData( a, b, c )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n\n   try {\n       fs.writeFileSync( fn,c );\n   } catch ( err )\n   {\n      if ( err.code !== 'EEXIST' )\n      {\n         process.stdout.write( \"write data failed: \" + fn + \" data:\" + c );\n         throw err;\n      } else\n      {\n         // file already exists - OK\n      }\n   }\n}\n\n// Read the state information.  If there is none, just return what\n// was expected.\n// Put exception handling here too. Just in case!\nfunction readData( a,b )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n   c = \"\";\n\n   try {\n      c = String( fs.readFileSync( fn, 'utf8' ) );\n   } catch ( err )\n   {\n      if ( err.code === 'ENOENT' )\n      {\n         // This is OK. just return what was expected.\n         return c;\n      } else\n      {\n         if ( err.code !== 'EEXIST' )\n         {\n            process.stdout.write( \"read data failed: \" + fn );\n            throw err;\n         } else\n         {\n            // file already exists - OK\n         }\n      }\n   }\n\n   return c;\n}\n\nlet c = \"\";\n\nswitch( io )\n{\n   case \"Get\":\n   {\n      c = readData( device, characteristic );\n\n      switch( characteristic )\n      {\n         // Characteristics who should get a 1 return\n         case \"AccessoryFlags\":\n         case \"AirQuality\":\n         case \"DayoftheWeek\":\n         case \"OpticalZoom\":\n         case \"Reachable\":\n         {\n             if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( c );\n\n             break;\n         }\n         case \"AccessoryIdentifier\":\n         {\n             if ( c == \"\" ) process.stdout.write( \"TLB\" ); else process.stdout.write( c );\n\n             break;\n         }\n         // Characteristics who should get a larger value return\n         case \"AirParticulateDensity\":\n         case \"BatteryLevel\":\n         case \"Brightness\":\n         case \"CoolingThresholdTemperature\":\n         case \"ColorTemperature\":\n         case \"CurrentAmbientLightLevel\":\n         case \"CurrentRelativeHumidity\":\n         case \"CurrentTemperature\":\n         case \"FilterLifeLevel\":\n         case \"HeartBeat\":\n         case \"HeatingThresholdTemperature\":\n         case \"Hue\":\n         case \"LockManagementAutoSecurityTimeout\":\n         case \"NitrogenDioxideDensity\":\n         case \"OzoneDensity\":\n         case \"PM10Density\":\n         case \"PM2_5Density\":\n         case \"SulphurDioxideDensity\":\n         case \"VOCDensity\":\n         {\n             // Make things a little different between devices\n             if ( c == \"\" ) process.stdout.write( Math.floor(Math.random() * 60) + 20 ); else process.stdout.write( c );\n\n             break;\n         }\n         case \"CurrentTime\":\n         {\n             if ( c == \"\" ) process.stdout.write( \"11:15\" ); else process.stdout.write( c );\n\n             break;\n         }\n         case \"FirmwareRevision\":\n         case \"Version\":\n         case \"HardwareRevision\":\n         {\n             if ( c == \"\" ) process.stdout.write( \"100.1.1\" ); else process.stdout.write( c );\n\n             break;\n         }\n         case \"Manufacturer\":\n         case \"Model\":\n         case \"SerialNumber\":\n         case \"Name\":\n         case \"ConfiguredName\":\n         {\n             if ( c == \"\" ) process.stdout.write( device ); else process.stdout.write( c );\n\n             break;\n         }\n         default:\n             if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( c );\n             process.exit( 0 );\n      }\n\n      break;\n\n   } // End of Switch for \"Get\"\n   case \"Set\":\n   {\n      switch( characteristic )\n      {\n         case \"Active\":\n         case \"On\":\n         {\n            writeData( device, characteristic, option );\n\n            switch( option )\n            {\n               case 0:\n               case false:\n               case \"INACTIVE\":\n                  writeData( device, \"RotationSpeed\", 0 );\n\n                  // Set to INACTIVE\n                  writeData( device, \"CurrentAirPurifierState\", 0 );\n\n                  break;\n               case 1:\n               case true:\n               case \"ACTIVE\":\n                  writeData( device, \"RotationSpeed\", 6 );\n\n                  // Set to IDLE\n                  writeData( device, \"CurrentAirPurifierState\", 1 );\n\n                 break;\n             }\n\n            break;\n         }\n         case \"SecuritySystemTargetState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"SecuritySystemCurrentState\", option );\n\n            break;\n         }\n         case \"TargetAirPurifierState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentAirPurifierState\", option );\n\n            break;\n         }\n         case \"TargetAirQuality\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device, \"AirQuality\", option );\n\n            break;\n         }\n         case \"TargetDoorState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to Done\n            writeData( device, \"CurrentDoorState\", option );\n\n            break;\n         }\n         case \"TargetFanState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData( device, \"CurrentFanState\", option );\n\n            break;\n         }\n         case \"TargetHeaterCoolerState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData( device, \"CurrentHeaterCoolerState\", option );\n\n            break;\n         }\n         case \"TargetHeatingCoolingState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData( device, \"CurrentHeatingCoolingState\", option );\n\n            break;\n         }\n         case \"TargetHorizontalTiltAngle\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentHorizontalTiltAngle\", option );\n\n            break;\n         }\n         case \"TargetHumidifierDehumidifierState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentHumidifierDehumidifierState\", option );\n\n            break;\n         }\n         case \"TargetMediaState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentMediaState\", option );\n\n            break;\n         }\n         case \"TargetPosition\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentPosition\", option );\n\n            break;\n         }\n         case \"TargetRelativeHumidity\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device, \"CurrentRelativeHumidity\", option );\n\n            break;\n         }\n         case \"TargetSlatState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device, \"CurrentSlatState\", option );\n\n            break;\n         }\n         case \"TargetTemperature\":\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it\n            writeData( device, \"CurrentTemperature\", option );\n\n            break;\n         }\n         case \"TargetTiltAngle\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentTiltAngle\", option );\n\n            break;\n         }\n         case \"TargetVerticalTiltAngle\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentVerticalTiltAngle\", option );\n\n            break;\n         }\n         case \"TargetVisibilityState\":\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData( device,\"CurrentVisibilityState\", option );\n\n            break;\n         }\n         default:\n            writeData( device, characteristic, option );\n      }\n\n      break;\n   } // End of Switch Device for \"Set\"\n   default:\n      console.error( \"Unknown IO\" + io );\n      process.exit( -1 );\n}\n\nprocess.exit( 0 );\n\n\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/DoorLock.sh",
    "content": "#!/bin/sh\n\n#\n# In this example we see a Raspberry Pi with a gpio pin that triggers\n# a lock mechanism. The lock is momentary. You should configure the GPIO by executing:\n#\n# echo 24 > /sys/class/gpio/export\n# echo \"out\" > /sys/class/gpio/gpio24/direction\n#\n# The corresponding config.json is\n#\n# {\n#    \"type\": \"LockMechanism\",\n#    \"displayName\": \"Front Door\",\n#    \"lockCurrentState\": \"SECURED\",\n#    \"lockTargetState\": \"SECURED\",\n#    \"name\": \"Front Door\",\n#    \"manufacturer\": \"XYZ\",\n#    \"model\": \"XYZ\",\n#    \"serialNumber\": \"GPIO 24\",\n#    \"polling\": [\n#        {\n#            \"characteristic\": \"lockCurrentState\",\n#            \"interval\": 5,\n#            \"timeout\": 4900\n#        },\n#        {\n#            \"characteristic\": \"lockTargetState\",\n#            \"interval\": 5,\n#            \"timeout\": 4900\n#        }\n#    ],\n#    \"stateChangeResponseTime\": 0.2,\n#    \"state_cmd\": \"sh /homebridge/DoorLock.sh\"\n# }\n\n#!/bin/sh\n\nSTATE_FILE=\"/dev/shm/DoorLock.state\"\n\nif [ ! -f \"$STATE_FILE\" ]; then\n        echo 1 > $STATE_FILE\nfi\n\nSTATE=$(cat $STATE_FILE)\n\nif [ \"$1\" = \"Get\" ]; then\n        case $3 in\n                \"LockCurrentState\")\n                        echo $STATE\n                ;;\n                \"LockTargetState\")\n                        echo $STATE\n                        echo 1 > $STATE_FILE\n                ;;\n        esac\n        echo 0 > /sys/class/gpio/gpio24/value\n        exit 0\nfi\n\nif [ \"$1\" = \"Set\" ]; then\n        case $3 in\n                \"LockTargetState\")\n                if [ \"$4\" = \"UNSECURED\" ]; then\n                        echo 0 > $STATE_FILE\n                        echo 1 > /sys/class/gpio/gpio24/value\n                        sleep 0.1\n                fi\n                ;;\n        esac\n        echo 0 > /sys/class/gpio/gpio24/value\n        exit 0\nfi\n\nexit 66\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/ExampleJavaScript_template.js",
    "content": "#!/usr/bin/env node\n//  ExampleScript_template.js\n//\n// Description:\n//   This script is a goood starting place for you to create Cmd4 Scripts\n//   of your own\n//\n// Parameters are:\n//    Get < Any accessory name > < Characteristic >\n//    Set < Any accessory name > < Characteristic > < value >\n//\n// Note 1: These paramaters match the those of the Cmd4 plugin.\n//         A full lost of supported devices and characteristics can be\n//         found at:\n//         https://ztalbot2000.github.io/homebridge-cmd4\n//\n// How it works:\n//    The Cmd4 plugin will call this script to retrieve those states\n//    you have defined as not Cached to Get/Set your devices characteristic\n//    states.\n//\n//    For example:\n//       node ExampleScript_template.js Set My_Door TargetDoorState 0\n//     or\n//       node ExampleScript.js Get My_Door CurrentDoorState\n//\n//\n\n'use strict';\n\nvar length = process.argv.length;\nvar device = \"My_Door\";\nvar io = \"\";\nvar characteristic = \"\";\nvar option = \"\";\n\nif ( length == 2 ) process.exit( 0 );\n\nif ( length <= 2 ) {\n    console.log( \"Usage: \" + process.argv[0] + \" < Get > < AccessoryName > < Characteristic >\" );\n    console.log( \"       \" + process.argv[0] + \" < Set > < AccessoryName > < Characteristic > < Value >\" );\n    process.exit( -1 );\n}\n\nif ( length >= 2 ) io = process.argv[2];\nif ( length >= 3 ) device = process.argv[3];\nif ( length >= 4 ) characteristic  = process.argv[4];\nif ( length >= 5 ) option  = process.argv[5];\n\nvar c = \"\";\n\nswitch( io )\n{\n    case \"Get\":\n    {\n        switch( characteristic )\n        {\n            case \"CurrentDoorState\":\n            {\n               console.log( 0 );\n\n               // See https://ztalbot2000.github.io/homebridge-cmd4\n               // For the possible values and characteristics\n               // available per device. It will show somethink like:\n               // Valid Values:\n               // 0 - \"Open. The door is fully open.\"\n               // 1 - \"Closed. The door is fully closed.\"\n               // 2 - \"Opening. The door is actively opening.\"\n               // 3 - \"Closing. The door is actively closing.\"\n               // 4 - \"Stopped. The door is not moving, and it is not fully\n               //      open nor fully closed.\"\n               // 5-255 - \"Reserved\"\n\n               break;\n            }\n            case \"TargetDoorState\":\n            {\n                console.log( 0 );\n                break;\n            }\n            case \"ObstructionDetected\":\n            {\n                console.log ( 0 );\n                break;\n            }\n            case \"LockCurrentState\":\n            {\n                console.log ( 0 );\n                break;\n            }\n            default:\n                console.error( \"Unhandled characteristic for:\"  + io  +  \" Device:\" + device  +  \" Characteristic:\" + characteristic );\n                process.exit( -1 );\n        }\n\n        break;\n\n    } // End of Switch for \"Get\"\n    case \"Set\":\n    {\n        switch( characteristic )\n        {\n            case \"CurrentDoorState\":\n            {\n               // Current Door State is not settable. The\n               // call would be to TargetDoorState. This is here\n               // for debugging only.\n\n               break;\n            }\n            case \"TargetDoorState\":\n            {\n                // Do something of your own here.\n\n                break;\n            }\n            case \"ObstructionDetected\":\n            {\n               // Obstruction Detected is not settable. It\n               // call is a read-only characteristic. This is here\n               // for debugging only.\n               break;\n            }\n            case \"LockCurrentState\":\n            {\n                // Lock Current State is not settable. It\n                // call is a read-only characteristic. This is here\n                // for debugging only.\n                break;\n            }\n            default:\n                console.error( \"UnHandled Characteristic for:\"  + io  +  \" Device:\" + device  +  \" Characteristic:\" + characteristic );\n                process.exit( -1 );\n        }\n\n        break;\n    } // End of Switch Device for \"Set\"\n    default:\n        console.error( \"Unknown IO\" + io );\n        process.exit( -1 );\n}\n\n//console.log( \"Say What Device:\" + device + \" Characteristic:\" + characteristic + \" Option:\" + option );\n\n// You must exit with a zero status, confirming the script rannsuccessfully.\nprocess.exit( 0 );\n\n\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/ExampleShellScript_template.sh",
    "content": "#!/bin/bash\n\n#  ExampleScript_template.sh\n#\n# Description:\n#   This script is a goood starting place for you to create Cmd4 Scripts\n#   of your own\n#\n# Parameters are:\n#    Get < Any accessory name > < Characteristic>\n#    Set < Any accessory name > < Characteristic> < value >\n#\n# Note 1: These paramaters match the those of the Cmd4 plugin.\n#         A full lost of supported devices and characteristics can be\n#         found at:\n#         https://ztalbot2000.github.io/homebridge-cmd4\n#\n# How it works:\n#\n#    The Cmd4 plugin will call this script to retrieve those states\n#    you have defined as not Cached to Get/Set your devices characteristic\n#    states.\n#\n#    For example:\n#       bash ExampleScript_template.sh Set My_Door TargetDoorState 0\n#     or\n#       bash ExampleScript.sh Get My_Door CurrentDoorState\n#\n\nset -e\n\n# Exit immediately for unbound variables.\nset -u\n\n\nlength=$#\ndevice=\"\"\nio=\"\"\ncharacteristic=\"\"\noption=\"\"\n\nif [ $length -le 1 ]; then\n   printf \"Usage: $0 Get < AccessoryName > < Characteristic >\\n\"\n   printf \"Usage: $0 Set < AccessoryName > < Characteristic > < Value >\\n\"\n   exit -1\nfi\n\n# printf \"args =$#\\n\"   # debug\n# printf \"arg1 =$1\\n\"   # debug\n\nif [ $length -ge 1 ]; then\n    io=$1\n    # printf \"io=$io\\n\"   # debug\nfi\nif [ $length -ge 2 ]; then\n    device=$2\n    # printf \"device = ${device}\\n\"   # debug\nfi\nif [ $length -ge 3 ]; then\n    characteristic=$3\n    # printf \"Characteristic = ${characteristic}\\n\"   # debug\nfi\nif [ $length -ge 4 ]; then\n    option=$4\n    # printf \"option = ${option}\\n\"   # debug\nfi\n\nif [ \"${io}\" == \"Get\" ]; then\n   case $characteristic in\n      'CurrentDoorState')\n\n         printf \"0\\n\"          # Door is open\n\n         # See https://ztalbot2000.github.io/homebridge-cmd4\n         # For the possible values and characteristics\n         # available per device. It will show somethink like:\n         # Valid Values:\n         # 0 - \"Open. The door is fully open.\"\n         # 1 - \"Closed. The door is fully closed.\"\n         # 2 - \"Opening. The door is actively opening.\"\n         # 3 - \"Closing. The door is actively closing.\"\n         # 4 - \"Stopped. The door is not moving, and it is not fully\n         #      open nor fully closed.\"\n         # 5-255 - \"Reserved\"\n         exit 0\n         ;;\n      'TargetDoorState')\n         printf \"0\\n\"\n         exit 0\n         ;;\n      'ObstructionDetected')\n         printf \"0\\n\"\n         exit 0\n         ;;\n      'LockCurrentState')\n         printf \"0\\n\"\n         exit 0\n         ;;\n      *)\n         printf \"UnHandled Get ${device}  Characteristic ${characteristic}\\n\"\n         exit -1\n         ;;\n    esac\nfi\nif [ \"${io}\" == 'Set' ]; then\n   case $characteristic in\n      'CurrentDoorState')\n         # Current Door State is not settable. The\n         # call would be to TargetDoorState. This is here\n         # for debugging only.\n\n         exit 0\n         ;;\n      'TargetDoorState')\n         # Do something of your own here.\n         exit 0\n         ;;\n      'ObstructionDetected')\n         # Obstruction Detected is not settable. It\n         # call is a read-only characteristic. This is here\n         # for debugging only.\n         exit 0\n         ;;\n      'LockCurrentState')\n         # Lock Current State is not settable. It\n         # call is a read-only characteristic. This is here\n         # for debugging only.\n         exit 0\n         ;;\n      *)\n         printf \"UnHandled Set GarageDoorOpenner Characteristic ${characteristic}\"\n         exit -1\n         ;;\n    esac\nfi\nprintf \"Unknown io command ${io}\\n\"\nexit -1\n\n\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/PS4.sh",
    "content": "#!/bin/bash\n\n\n#\n# This Cmd4 example demonstrates a script that is compatible with\n# cmdSwitch2's example of controlling a PS4.\n#\n# Your Cmd4 .homebridge/.config.json file would have a state_cmd like:\n# state_cmd: \".homebridge/Cmd4Scripts/Examples/PS4.sh\"\n#\n# Testing from the shell prompt:\n#    ./PS4.sh Get PS4 On\n#    or\n#    ./PS4.sh Set PS4 On 1\n#    or\n#    ./PS4.sh Set PS4 On 0\n\n# Exit immediately if a command exits with a non-zero status\nset -e\n\n# Check if the first parameter to this script was \"Get\" for getting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Get\" ]; then\n\n   # Normally we would exit immediately if a command fails with a non-zero status.\n   # In this case ps4-waker can fail and we would rely on the failing exit status to\n   # tell Cmd4 that the accessory is not on the network. That would be the prefered\n   # thing to do. However for this example we are going to output '0' (false) so\n   # that you can see the '0' on the console telling us that the accessory is not\n   # on the network.\n   set +e\n\n   ps4-waker search | grep -i '200 Ok' >> /dev/null 2>&1\n   rc=$?\n\n   # Exit immediately if a command exits with a non-zero status\n   set -e\n\n   # Check if we got the message '200 OK' meaning the accessory is\n   # on the network by seeing if the return code of the above command passed or\n   # failed.\n   if [ \"$rc\" = \"0\" ]; then\n      # The message was recieved so the target is up, sending a '1' (true), like\n      # a binary number is, back to Cmd4.\n      echo \"1\"\n\n      # Exit this script positivitely.\n      exit 0\n   else\n      # The message was not recieved so the target must be down, sending a '0' (false), like\n      # a binary number is, back to Cmd4.\n      echo \"0\"\n\n      # Exit this script positivitely, even though ps4-waker failed.\n      exit 0\n   fi\nfi\n\n# Check if the first parameter to this script was \"Set\" for setting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Set\" ]; then\n\n   # $2 would be the name of the accessory.\n   # $3 would be the accessory's charactersistic 'On'.\n   # $4 would be '1' for 'On' and '0' for 'Off', like a binary number is.\n   # $4 would be 'true' for 'On' and 'false' for 'Off' with\n   # outputConstants=true in your .homebridge/.config.json file.\n\n   # Handle the Set 'On' attribute of the accessory\n   if [ \"$3\" = \"On\" ]; then\n\n      # If the accessory is to be set on\n      if [ \"$4\" = \"1\" ]; then\n\n         # Normally we would exit immediately if a command fails with a non-zero status.\n         # In this case ps4-waker can fail and we would rely on the failing exit status to\n         # tell Cmd4 that the accessory is not on the network. That would be the prefered\n         # thing to do. However for this example we are going to output '0' (false) so\n         # that you can see the '0' on the console telling us that the accessory is not\n         # on the network.\n         set +e\n\n         # Execute the on command\n         ps4-waker >> /dev/null 2>&1\n\n         # keep the result of the on/off command\n         rc=$?\n\n         # Exit immediately if a command exits with a non-zero status\n         set -e\n\n      else\n\n         # Normally we would exit immediately if a command fails with a non-zero status.\n         # In this case ps4-waker can fail and we would rely on the failing exit status to\n         # tell Cmd4 that the accessory is not on the network. That would be the prefered\n         # thing to do. However for this example we are going to output '0' (false) so\n         # that you can see the '0' on the console telling us that the accessory is not\n         # on the network.\n         set +e\n\n         # Execute the off command\n         ps4-waker standby >> /dev/null 2>&1\n\n         # keep the result of the on/off command\n         rc=$?\n\n         # Exit immediately if a command exits with a non-zero status\n         set -e\n      fi\n\n      # Check if the on/off command had a positive return status.\n      if [ \"$rc\" = \"0\" ]; then\n\n         # The on/off command was successful, so exit successfully.\n         exit 0\n\n      else\n         # The on/off comand had a failure result. Exit with that result.\n\n         # Exit this script positivitely, even though ping failed.\n         exit $rc\n      fi\n   fi\nfi\n\n# The proper arguments to this script were not passed to it so end with a failure exit status.\nexit 666\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/PS5.sh",
    "content": "#!/bin/bash\n\n#\n# This Cmd4 script uses playactor to turn on/off a PS5.\n#\n# You will need to install playactor and have the command in a global PATH\n# or modify this script with its actual PATH.\n#\n# Your Cmd4 .homebridge/.config.json file would have a state_cmd like:\n# state_cmd: \".homebridge/Cmd4Scripts/Examples/PS5.sh\"\n#\n# Testing from the shell prompt:\n#    ./PS5.sh Get PS5 On\n#    or\n#    ./PS5.sh Set PS5 On 1\n#    or\n#    ./PS5.sh Set PS5 On 0\n\n\nset -e\n\n# Exit immediately for unbound variables.\nset -u\n\n# Passed in Args\nlength=$#\ndevice=\"\"\nio=\"\"\ncharacteristic=\"\"\n\n\nif [ $length -le 2 ]; then\n   echo \"Usage: $0 Get < AccessoryName > < characteristic >\"\n   echo \"Usage: $0 Set < AccessoryName > < characteristic > < Value >\"\n   exit 199\nfi\n\n\nif [ $length -ge 1 ]; then\n    io=$1\nfi\nif [ $length -ge 2 ]; then\n    device=$2\nfi\nif [ $length -ge 3 ]; then\n    characteristic=$3\nfi\n\n\n# For \"Get\" Directives\nif [ \"$io\" = \"Get\" ]; then\n   case \"$characteristic\" in\n\n      On )\n\n         # Normally we would exit immediately if a command fails with a non-zero status.\n         # In this case playactor can fail and we would rely on the failing exit status to\n         # tell Cmd4 that the accessory is not on the network. That would be the prefered\n         # thing to do. However for this example we are going to output '0' (false) so\n         # that you can see the '0' on the console telling us that the accessory is not\n         # on the network.\n         set +e\n\n         # Check if we got the message '200 OK' meaning the accessory is\n         # on the network by seeing if the return code of the above command passed or\n         # failed.\n         playactor check | grep -i '200 Ok'>> /dev/null 2>&1\n         rc=$?\n         set -e\n\n         if [ \"$rc\" = \"0\" ]; then\n            # The message was recieved so the target is up, sending a '1' (true), like\n            # a binary number is, back to Cmd4.\n            stdbuf -o0 -e0 echo 1\n            exit 0\n         else\n            # The message was not recieved so the target must be down, sending a '0' (false), like\n            # a binary number is, back to Cmd4.\n            stdbuf -o0 -e0 echo 0\n            exit 0\n         fi\n         ;;\n      *)\n         echo \"Unhandled Get characteristic $characteristic\" >&2\n         exit 109\n         ;;\n   esac\nfi\n\n# For \"Set\" Directives\nif [ \"$io\" = \"Set\" ]; then\n   value=\"1\"\n   if [ $length -ge 4 ]; then\n      value=$4\n   else\n      echo \"No value specified for set\" >&2\n      exit 199\n   fi\n\n   case \"$characteristic\" in\n      On )\n         # Normally we would exit immediately if a command fails with a non-zero status.\n         # In this case playactor can fail and we would rely on the failing exit status to\n         # tell Cmd4 that the accessory is not on the network. That would be the prefered\n         # thing to do. However for this example we are going to output '0' (false) so\n         # that you can see the '0' on the console telling us that the accessory is not\n         # on the network.\n         set +e\n\n         if [ \"$value\" = \"1\" ]; then\n\n             # Execute the on command\n            sudo playactor wake\n\n            exit 0\n         else\n             # Execute the off command\n            sudo playactor standby\n\n            exit 0\n         fi\n         ;;\n      *)\n         echo \"Unhandled Set characteristic $characteristic\" >&2\n         exit 109\n         ;;\n   esac\nfi\n\n\necho \"Unhandled $io $device $characteristic\" >&2\n\nexit 150\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/SecuritySystem.js",
    "content": "#!/usr/bin/env node\n//  SecuritySystem.js\n//\n// Description:\n//   This script *CAN* be called by the HomeBridge plugin Cmd4 as defined in your config.json\n//   file.  The purpose is to fake the existance of an Security System as best it can.\n//\n// Note: Security Systems are tricky to fake since the securitySysytemCurrentState\n//       Does not align with the SecuritySystemTargetState. The only way to trigger\n//       the alarm would be:\n//    node ./SecuritySystem.js Set My_System SecuritySystemCurrentState 4\n//\n//   Likewise to disarm\n//    node ./SecuritySystem.js Set My_System SecuritySystemCurrentState 3\n//\n// Note 1: The Hap spec is quoted throughout, but this is not the spec so\n//         this is not gauranteed to be correct.\n//\n// How it works:\n//    A characteristic value is stored in the $HOME/.homebridge/Cmd4Scripts/Cmd4States in\n//    the file named \"Status + <Accessory Name> _ <Characteristic>\" and is returned or\n//    written to based on the <Get|Set> option.\n//\n//    For example:   node SecuritySystem.js Set My_System SecuritySystemCurrentState 0\n//       will create the file:\n//          .homebridge/Cmd4Scripts/Cmd4States/Status_My_System_SecuritySystemCurrentState\n//       with the contents of \"0\"\n//\n// Environmental Variables Used:\n//    $HOME - to create path to .homebridge\n//\n// The following is an example config.json entry for this script.\n/*\n{\n   \"platform\": \"Cmd4\",\n   \"name\": \"Cmd4\",\n   \"debug\": false,\n   \"statusMsg\": true,\n   \"accessories\": [\n   {\n      \"type\": \"SecuritySystem\",\n      \"displayName\": \"My_SecuritySystem\",\n      \"securitySystemCurrentState\": \"AWAY_ARM\",\n      \"securitySystemTargetState\": \"AWAY_ARM\",\n      \"interval\": 30,\n      \"timeout\": 4900,\n      \"polling\": [\n          { \"characteristic\": \"securitySystemCurrentState\" },\n          { \"characteristic\": \"securitySystemTargetState\" }\n      ],\n      \"stateChangeResponseTime\": 1,\n      \"state_cmd\": \"node ./homebridge/Cmd4Scripts/SecuritySystem.js\"\n   }\n}\n*/\n\n'use strict';\n\n// FileSystem requirements.\nvar fs = require('fs');\nvar path = require('path');\nvar os = require('os');\n\n// The files created within Cmd4StatesPath contain just a value of the accessories last state,\n// so they are very small in size.\nvar Cmd4StatesPath =  path.join(os.homedir(), \".homebridge/Cmd4Scripts/Cmd4States\");\n\nvar length = process.argv.length;\nvar device = \"\";\nvar io = \"\";\nvar characteristic = \"\";\nvar option = \"\";\n\nif ( length == 2 ) process.exit( 0 );\n\nif ( length <= 2 ) {\n    process.stdout.write( `Usage: ${ process.argv[ 0 ] } <Get> <AccessoryName> <Characteristic>` );\n    process.stdout.write( `       ${ process.argv[ 0 ] } <Set> <AccessoryName> <Characteristic> <Value>` );\n    process.exit(-1);\n}\n\nif ( length >= 2 ) io = process.argv[ 2 ];\nif ( length >= 3 ) device = process.argv[ 3 ];\nif ( length >= 4 ) characteristic  = process.argv[ 4 ];\nif ( length >= 5 ) option  = process.argv[ 5 ];\n\n// Placing the states in a subdirectory makes things look cleaner.\n// Some platforms require an exception handler\nconst mkdirSync = function( dirPath )\n{\n    try {\n        fs.mkdirSync( dirPath )\n    } catch ( err ) {\n        if ( err.code !== 'EEXIST' )\n        {\n            process.stdout.write( `mkdir failed: ${ dirPath }`);\n            throw err;\n        } else {\n            // directory already exists - OK\n        }\n    }\n}\n\nmkdirSync( Cmd4StatesPath );\n\n\n// Such a simple way to store state information that is small and fast!\n// Put exception handling here too. Just in case!\nfunction writeData( a, b,c )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n\n   try {\n       fs.writeFileSync( fn,c );\n   } catch (err) {\n       if ( err.code !== 'EEXIST' )\n       {\n          process.stdout.write( `write data failed: ${ fn }  data: ${ c }` );\n          throw err;\n       } else {\n          // file already exists - OK\n       }\n   }\n}\n\n// Read the state information.  If there is none, just return what\n// was expected.\n// Put exception handling here too. Just in case!\nfunction readData( a, b )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n   c = \"\";\n\n   try {\n      c = String( fs.readFileSync( fn, 'utf8' ) );\n   } catch (err) {\n      if ( err.code === 'ENOENT' ) {\n         // This is OK. just return what was expected.\n         return c;\n      } else\n      {\n         if ( err.code !== 'EEXIST' )\n         {\n            process.stdout.write( `read data failed: ${ fn }` );\n            throw err;\n         } else {\n            // file already exists - OK\n         }\n      }\n   }\n\n   return c;\n}\n\nvar c = \"\";\n\nswitch( io )\n{\n   case \"Get\":\n   {\n      switch( characteristic )\n      {\n         case \"Name\":   // 97  Optional Characteristic\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( `\"${ device }\"` ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 00000023-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.name\n            // Permissions: Paired Read, Notify\n\n            // Format: string\n\n            // Maximum Length: 64\n\n            break;\n         }\n         case \"SecuritySystemCurrentState\":   // 143\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 00000066-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.security-system-state.current\n            // Permissions: Paired Read, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 4\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"STAY_ARM\"  - The home is occupied and the residents are\n            //      active. e.g. morning or evenings\"\n            // 1 - \"AWAY_ARM\"  -  The home is unoccupied\"\n            // 2 - \"NIGHT ARM\" -  The home is occupied and the residents are sleeping\"\n            // 3 - \"DISARMED\"\n            // 4 - \"ALARM_TRIGGERED\"\n            // 5 - 255 - Reserved\n\n            break;\n         }\n         case \"SecuritySystemTargetState\":   // 144\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 00000067-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.security-system-state.target\n            // Permissions: Paired Read, Paired Write, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 3\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"STAY_ARM\"  - The home is occupied and the residents\n            //      are active. e.g. morning or evenings\n            // 1 - \"AWAY_ARM\"  - The home is unoccupied\n            // 2 - \"NIGHT_ARM\" - The home is occupied and the residents are sleeping\n            //\n            // 3 - 255 - Reserved\n\n            break;\n         }\n         case \"SecuritySystemAlarmType\":   // 142  Optional Characteristic\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 0000008E-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.security-system.alarm-type\n            // Permissions: Paired Read, Notify\n\n            // Format: uint8\n\n            // Minimum Value: 0\n            // Maximum Value: 1\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - When alert cleared\n            // 1 - Unknown Cause\n\n            break;\n         }\n\n         case \"StatusFault\":   // 163  Optional Characteristic\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 00000077-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.status-fault\n            // Permissions: Paired Read, Notify\n            // Format: uint8\n            // Minimum Value: 0\n            // Maximum Value: 1\n            // Step Value: 1\n\n            // Valid Values:\n            // 0 - \"NO_FAULT\"\n            // 1 - \"GENERAL_FAULT\"\n\n            break;\n         }\n         case \"StatusTampered\":   // 166  Optional Characteristic\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // UUID: 0000007A-0000-1000-8000-0026BB765291\n            // Type: public.hap.characteristic.status-tampered\n            // Permissions: Paired Read, Notify\n\n            // Format: uint8\n\n            // Valid Values:\n            // 0 - \"NOT_TAMPERED\" - Accessory is not tampered\"\n            // 1 - \"TAMPERED\"     - Accessory is tampered with\n\n            break;\n         }\n\n         default:\n            process.stderr.write( `Unknown Characteristic for: ${ io } Device: ${ device } Characteristic: ${ characteristic }` );\n            process.exit( -1 );\n       }\n\n       break;\n\n   } // End of Switch for \"Get\"\n   case \"Set\":\n   {\n      switch( characteristic )\n      {\n         case \"Name\":   // 97  Optional Characteristic\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SecuritySystemAlarmType\":   // 142\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SecuritySystemCurrentState\":   // 143\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SecuritySystemTargetState\":   // 144\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"SecuritySystemCurrentState\", option);\n\n            break;\n         }\n         case \"StatusFault\":   // 163  Optional Characteristic\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StatusTampered\":   // 166  Optional Characteristic\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n\n\n         default:\n            process.stderr.write( `Unknown Characteristic for: ${ io } Device:${ device  } Characteristic:${ characteristic }` );\n            process.exit( -1 );\n      }\n\n      break;\n   } // End of Switch Device for \"Set\"\n   default:\n      process.stderr.write( `Unknown IO ${ io }` );\n      process.exit( -1 );\n}\n\n//process.stdout.write( `Say What Device: ${ device } Characteristic: ${ characteristic } Option: ${ option }` );\n\nprocess.exit( 0 );\n\n\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/advanced_ping.sh",
    "content": "#!/bin/sh\n\n#\n# This Cmd4 example demonstrates a little more advanced way of using ping to test if an\n# accessory is on the network by passing in the IP address to be used with the Cmd4 option\n# of state_cmd_suffix.\n#\n# Your Cmd4 .homebridge/.config.json file would have a state_cmd like:\n# state_cmd: \".homebridge/Cmd4Scripts/Examples/ping.sh\"\n# state_cmd_suffix: \"192.168.2.1\"\n#\n# Testing from the shell prompt:\n#    ./advanced_ping.sh Get My_TV On 192.168.2.1\n#    or\n#    ./advanced_ping.sh Set My_TV On 1 192.168.2.1\n\n# Exit immediately if a command exits with a non-zero status\nset -e\n\n# Check if the first parameter to this script was \"Get\" for getting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Get\" ]; then\n\n   # Cmd4 will pass the IP in the config.json defined by state_cmd_suffix as the fourth\n   # parameter to a Get command.\n   ip=\"${4}\"\n\n   # Normally we would exit immediately if a command fails with a non-zero status.\n   # In this case ping can fail and we would rely on the failing exit status to\n   # tell Cmd4 that the accessory is not on the network. That would be the prefered\n   # thing to do. However for this example we are going to output '0' (false) so\n   # that you can see the '0' on the console telling us that the accessory is not\n   # on the network.\n   set +e\n\n   # $2 would be the name of the accessory\n   # $3 would be the accessory's charactersistic 'On'\n   # On OSX the string is returned differently than on linux.\n   ping -c 2 -W 1 \"${ip}\" | sed -E 's/2 packets received/2 received/g' | grep -i '2 received' >> /dev/null\n   rc=$?\n\n   # Exit immediately if a command exits with a non-zero status\n   set -e\n\n   # Check if we got the message '2 packets recieved' meaning the accessory is\n   # on the network by seeing if the return code of the above command passed or\n   # failed.\n   if [ \"$rc\" = \"0\" ]; then\n      # The message was recieved so the target is up, sending a '1' (true), like\n      # a binary number is, back to Cmd4.\n      echo \"1\"\n\n      # Exit this script positivitely.\n      exit 0\n   else\n      # The message was not recieved so the target must be down, sending a '0' (false), like\n      # a binary number is, back to Cmd4.\n      echo \"0\"\n\n      # Exit this script positivitely, even though ping failed.\n      exit 0\n   fi\nfi\n\n# Check if the first parameter to this script was \"Set\" for setting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Set\" ]; then\n\n   # $2 would be the name of the accessory.\n   # $3 would be the accessory's charactersistic 'On'.\n   # $4 would be '1' for 'On' and '0' for 'Off', like a binary number is.\n   # $4 would be 'true' for 'On' and 'false' for 'Off' with\n   # outputConstants=true in your .homebridge/.config.json file.\n\n   # Cmd4 will pass the IP in the config.json defined by state_cmd_suffix as the fifth\n   # parameter to a Set command.\n   ip=\"${5}\"\n\n   # This ping script does not do anything for set so just exit successfully.\n   exit 0\nfi\n\n# The proper arguments to this script were not passed to it so end with a failure exit status.\nexit 66\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/basic_ping.sh",
    "content": "#!/bin/sh\n\n#\n# This Cmd4 example demonstrates how you can test if an accessory is on the network using ping.\n#\n# Your Cmd4 .homebridge/.config.json file would have a state_cmd like:\n# state_cmd: \".homebridge/Cmd4Scripts/Examples/ping.sh\"\n#\n#\n# Testing from the shell prompt:\n#    ./basic_ping.sh Get My_TV On\n#    or\n#    ./basic_ping.sh Set My_TV On 1\n\n\n\n# Exit immediately if a command exits with a non-zero status\nset -e\n\n# Define the accessories IP you wish to test\nip=\"192.168.2.1\"\n\n# Check if the first parameter to this script was \"Get\" for getting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Get\" ]; then\n\n   # Normally we would exit immediately if a command fails with a non-zero status.\n   # In this case ping can fail and we would rely on the failing exit status to\n   # tell Cmd4 that the accessory is not on the network. That would be the prefered\n   # thing to do. However for this example we are going to output '0' (false) so\n   # that you can see the '0' on the console telling us that the accessory is not\n   # on the network.\n   set +e\n\n   # $2 would be the name of the accessory\n   # $3 would be the accessory's charactersistic 'On'\n   # On OSX the string is returned differently than on linux.\n   ping -c 2 -W 1 \"${ip}\" | sed -E 's/2 packets received/2 received/g' | grep -i '2 received' >> /dev/null\n   rc=$?\n\n   # Exit immediately if a command exits with a non-zero status\n   set -e\n\n   # Check if we got the message '2 packets recieved' meaning the accessory is\n   # on the network by seeing if the return code of the above command passed or\n   # failed.\n   if [ \"$rc\" = \"0\" ]; then\n      # The message was recieved so the target is up, sending a '1' (true), like\n      # a binary number is, back to Cmd4.\n      echo \"1\"\n\n      # Exit this script positivitely.\n      exit 0\n   else\n      # The message was not recieved so the target must be down, sending a '0' (false), like\n      # a binary number is, back to Cmd4.\n      echo \"0\"\n\n      # Exit this script positivitely, even though ping failed.\n      exit 0\n   fi\nfi\n\n# Check if the first parameter to this script was \"Set\" for setting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Set\" ]; then\n\n   # $2 would be the name of the accessory.\n   # $3 would be the accessory's charactersistic 'On'.\n   # $4 would be '1' for 'On' and '0' for 'Off', like a binary number is.\n   # $4 would be 'true' for 'On' and 'false' for 'Off' with\n   # outputConstants=true in your .homebridge/.config.json file.\n\n   # This ping script does not do anything for set so just exit successfully.\n   exit 0\nfi\n\n# The proper arguments to this script were not passed to it so end with a failure exit status.\nexit 66\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/middleWare.sh",
    "content": "#!/bin/bash\nresult=$(node .homebridge/Cmd4Scripts/State.js $* 2>&1)\necho $( date ) >> /tmp/Cmd4.log\necho $* >> /tmp/Cmd4.log\necho $result | tee -a /tmp/Cmd4.log\n"
  },
  {
    "path": "Extras/Cmd4Scripts/Examples/wakeonlan.sh",
    "content": "#!/bin/bash\n\n#\n# This Cmd4 example demonstrates a script that can be used for a wakeonlan\n# scenario. It is a port of the cmdSwitch2 example and is more for a Windows\n# PC.\n#\n# Your Cmd4 .homebridge/.config.json file would have a state_cmd like:\n# state_cmd: \".homebridge/Cmd4Scripts/Examples/wakeonlan.sh\"\n# state_cmd_suffix: \"192.168.2.66 dc:a6:32:40:de:7c\"\n#\n#\n# Testing from the shell prompt:\n#    ./wakeonlan.sh Get HTPC On 192.168.2.66 dc:a6:32:40:de:7c\n#    or\n#    ./wakeonlan.sh Set HTPC On 1 192.168.2.66 dc:a6:32:40:de:7c\n#    or\n#    ./wakeonlan.sh Set HTPC On 0 192.168.2.66 dc:a6:32:40:de:7c\n\n# Exit immediately if a command exits with a non-zero status\nset -e\n\n# Check if the first parameter to this script was \"Get\" for getting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Get\" ]; then\n\n   # Cmd4 will pass the IP in the config.json defined by state_cmd_suffix as the fourth\n   # parameter to a Get command.\n   ip=\"${4}\"\n\n   # Cmd4 will pass the MAC Address in the config.json defined by state_cmd_suffix as the fifth\n   # parameter to a Get command.\n   macAddress=\"${5}\"\n\n   # Normally we would exit immediately if a command fails with a non-zero status.\n   # In this case ping can fail and we would rely on the failing exit status to\n   # tell Cmd4 that the accessory is not on the network. That would be the prefered\n   # thing to do. However for this example we are going to output '0' (false) so\n   # that you can see the '0' on the console telling us that the accessory is not\n   # on the network.\n   set +e\n\n   # On OSX the string is returned differently than on linux.\n   ping -c 2 -W 1 \"${ip}\" | sed -E 's/2 packets received/2 received/g' | grep -i '2 received' >> /dev/null\n   rc=$?\n\n   # Exit immediately if a command exits with a non-zero status\n   set -e\n\n   # Check if we got the message '2 packets recieved' meaning the accessory is\n   # on the network by seeing if the return code of the above command passed or\n   # failed.\n   if [ \"$rc\" = \"0\" ]; then\n      # The message was recieved so the target is up, sending a '1' (true), like\n      # a binary number is, back to Cmd4.\n      echo \"1\"\n\n      # Exit this script positivitely.\n      exit 0\n   else\n      # The message was not recieved so the target must be down, sending a '0' (false), like\n      # a binary number is, back to Cmd4.\n      echo \"0\"\n\n      # Exit this script positivitely, even though ping failed.\n      exit 0\n   fi\nfi\n\n# Check if the first parameter to this script was \"Set\" for setting an accessory's\n# specific attribute.\nif [ \"$1\" = \"Set\" ]; then\n\n   # $2 would be the name of the accessory.\n   # $3 would be the accessory's charactersistic 'On'.\n   # $4 would be '1' for 'On' and '0' for 'Off', like a binary number is.\n   # $4 would be 'true' for 'On' and 'false' for 'Off' with\n   # outputConstants=true in your .homebridge/.config.json file.\n\n   # Cmd4 will pass the IP in the config.json defined by state_cmd_suffix as the fifth\n   # parameter to a Set command.\n   ip=\"${5}\"\n\n   # Cmd4 will pass the MAC Address in the config.json defined by state_cmd_suffix as the sixth\n   # parameter to a Set command.\n   macAddress=\"${6}\"\n\n   # Handle the Set 'On' attribute of the accessory\n   if [ \"$3\" = \"On\" ]; then\n\n      # If the accessory is to be set on\n      if [ \"$4\" = \"1\" ]; then\n         # Execute the on command\n         wakeonlan -i ${ip} ${macAddress} >> /dev/null 2>&1\n\n         # keep the result of the on/off command\n         rc=$?\n      else\n         # Execute the off command\n         # The password is harad coded here. We use the default\n         # Raspberry Pi password asli an example. How you handle\n         # this unencrypted password is up to you. Note that\n         # this command only works to a Windows box, but is the\n         # exmple given in cmdSwitch2.\n         # net rpc shutdown -I \"${ip}\" -U user%password,\n         net rpc shutdown -I \"${ip}\" -U pi%raspberry >> /dev/null 2>&1\n\n         # keep the result of the on/off command\n         rc=$?\n      fi\n\n      # Check if the on/off command had a positive return status.\n      if [ \"$rc\" = \"0\" ]; then\n\n         # The on/off command was successful, so exit successfully.\n         exit 0\n\n      else\n         # The on/off comand had a failure result. Exit with that result.\n\n         # Exit this script positivitely, even though ping failed.\n         exit $rc\n      fi\n   fi\nfi\n\n# The proper arguments to this script were not passed to it so end with a failure exit status.\nexit 66\n"
  },
  {
    "path": "Extras/Cmd4Scripts/State.js",
    "content": "#!/usr/bin/env node\n//  State.js\n//\n// Description:\n//   This script *CAN* be called by the HomeBridge plugin Cmd4 as defined in your config.json\n//   file.  The purpose is to fake the existance of an accessory or to be modified by you\n//   such that acessories can Get/Set characteristics as defined in the HomeKit Accessory\n//   Specifications.\n//\n// Plugin Installation:\n//   - npm install [-g] Cmd4\n//   - mkdir $HOME/.homebridge/Cmd4Scripts\n//   - cp State.js  $HOME/.homebridge/Cmd4Scripts/State.js\n//   - chmod u+x $HOME/.homebridge/Cmd4Scripts/State.js\n//\n// Parameters are:\n//    Get <accessory name> <characteristic>\n//    Set <accessory name> <characteristic> <value>\n//\n// Note 1: These paramaters match the those of the Cmd4 plugin.\n// Note 2: All characteristics of the HomeKit Accessory Protocol (HAP)\n//         specifications are supported, except for camera streaming;\n//         Though I have found some like LockManagement are not within IOS.\n//         Side Note: The Eve app is nicer, try it.\n// Note 3: The Hap spec is quoted throughout, but this is not the spec so\n//         this is not gauranteed to be correct.\n// Note 4: In this latest version, State.js does not care which characteristic\n//         belongs with a specific accessssory for the purpose of creating\n//         custom accessories.  IOS would not like this, but if you use\n//         the provided config.json file that defines the corrrect characteristics,\n//         this will not matter.\n//\n// How it works:\n//    A characteristic value is stored in the $HOME/.homebridge/Cmd4Scripts/Cmd4States in\n//    the file named \"Status + <Accessory Name> _ <Characteristic>\" and is returned or\n//    written to based on the <Get|Set> option.\n//\n//    For example:   node State.js Set My_Door MotionDetected 0\n//       will create the file .homebridge/Cmd4Scripts/Cmd4States/My_Door_MotionDetected\n//       with the contents of \"0\"\n//       Note: See how this is run from $HOME (Important!)\n//\n// Environmental Variables Used:\n//    $HOME - to create path to .homebridge\n//\n//\n// Interesting fact.  If you use characteristics as is, and define all possible accessories in your config.json\n//                    file, they will all appear fully functional within HomeKit. In this way you\n//                    can play with HomeKit and not have any physical devices at all.  Cool Eh!\n//\n// *IMPORTANT* - I cannot audit commented constants.  The lib/CMD4_DEVICE_ENUM.js is what is used\n//               for constant translations.\n\n'use strict';\n\n// FileSystem requirements.\nvar fs = require('fs');\nvar path = require('path');\nvar os = require('os');\n\n// The files created within Cmd4StatesPath contain just a value of the accessories last state,\n// so they are very small in size.\nvar Cmd4StatesPath =  path.join(os.homedir(), \".homebridge/Cmd4Scripts/Cmd4States\");\n\nvar length = process.argv.length;\nvar device = \"\";\nvar io = \"\";\nvar characteristic = \"\";\nvar option = \"\";\n\nif ( length == 2 ) process.exit( 0 );\n\nif ( length <= 2 ) {\n    process.stdout.write( `Usage: ${ process.argv[ 0 ] } <Get> <AccessoryName> <Characteristic>` );\n    process.stdout.write( `       ${ process.argv[ 0 ] } <Set> <AccessoryName> <Characteristic> <Value>` );\n    process.exit(-1);\n}\n\nif ( length >= 2 ) io = process.argv[ 2 ];\nif ( length >= 3 ) device = process.argv[ 3 ];\nif ( length >= 4 ) characteristic  = process.argv[ 4 ];\nif ( length >= 5 ) option  = process.argv[ 5 ];\n\n// Placing the states in a subdirectory makes things look cleaner.\n// Some platforms require an exception handler\nconst mkdirSync = function( dirPath )\n{\n    try {\n        fs.mkdirSync( dirPath )\n    } catch ( err ) {\n        if ( err.code !== 'EEXIST' )\n        {\n            process.stdout.write( `mkdir failed: ${ dirPath }`);\n            throw err;\n        } else {\n            // directory already exists - OK\n        }\n    }\n}\n\nmkdirSync( Cmd4StatesPath );\n\n\n// Such a simple way to store state information that is small and fast!\n// Put exception handling here too. Just in case!\nfunction writeData( a, b,c )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n\n   try {\n       fs.writeFileSync( fn,c );\n   } catch (err) {\n       if ( err.code !== 'EEXIST' )\n       {\n          process.stdout.write( `write data failed: ${ fn }  data: ${ c }` );\n          throw err;\n       } else {\n          // file already exists - OK\n       }\n   }\n}\n\n// Read the state information.  If there is none, just return what\n// was expected.\n// Put exception handling here too. Just in case!\nfunction readData( a, b )\n{\n   var fn = Cmd4StatesPath + \"/Status_\" + a  + \"_\" + b;\n   c = \"\";\n\n   try {\n      c = String( fs.readFileSync( fn, 'utf8' ) );\n   } catch (err) {\n      if ( err.code === 'ENOENT' ) {\n         // This is OK. just return what was expected.\n         return c;\n      } else\n      {\n         if ( err.code !== 'EEXIST' )\n         {\n            process.stdout.write( `read data failed: ${ fn }` );\n            throw err;\n         } else {\n            // file already exists - OK\n         }\n      }\n   }\n\n   return c;\n}\n\nvar c = \"\";\n\nswitch( io )\n{\n   case \"Get\":\n   {\n      switch( characteristic )\n      {\n         case \"AccessControlLevel\":   // 0\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( `1` ); else process.stdout.write( `\"${ c }\"` );\n\n            // To avoid hard coding values, characteristic definitions can be found in:\n            // Cmd4 Github pages -> http://ztalbot2000.github.io/homebridge-cmd4\n            // Homebridge developer documentation -> https://developers.homebridge.io/#/\n\n            break;\n         }\n         case \"AccessoryFlags\":   // 1\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AccessoryIdentifier\":   // 2\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"TLB\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Active\":   // 3\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ActiveIdentifier\":   // 4\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ActivityInterval\":   // 5\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AdministratorOnlyAccess\":   // 6\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AirParticulateDensity\":   // 7\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"30\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AirParticulateSize\":   // 8\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AirQuality\":   // 9\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AppMatchingIdentifier\":   // 10\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AudioFeedback\":   // 11\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"BatteryLevel\":   // 12\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Brightness\":   // 13\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ButtonEvent\":   // 14\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CCAEnergyDetectThreshold\":   // 15\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CCASignalDetectThreshold\":   // 16\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CameraOperatingModeIndicator\":   // 17\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CarbonDioxideDetected\":   // 18\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CarbonDioxideLevel\":   // 19\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CarbonDioxidePeakLevel\":   // 20\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CarbonMonoxideDetected\":   // 21\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CarbonMonoxideLevel\":   // 22\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CarbonMonoxidePeakLevel\":   // 23\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Category\":   // 24\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CharacteristicValueTransitionControl\":   // 25\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ChargingState\":   // 26\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ClosedCaptions\":   // 27\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ColorTemperature\":   // 28\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ConfigureBridgedAccessory\":   // 29\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ConfigureBridgedAccessoryStatus\":   // 30\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ConfiguredName\":   // 31\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( `\"${ device }\"` ); else process.stdout.write(`\"${ c }\"` );\n\n            break;\n         }\n         case \"ContactSensorState\":   // 32\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CoolingThresholdTemperature\":   // 33\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"32.4\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentAirPurifierState\":   // 34\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentAmbientLightLevel\":   // 35\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentDoorState\":   // 36\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentFanState\":   // 37\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentHeaterCoolerState\":   // 38\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            process.exit(0);\n\n            break;\n         }\n         case \"CurrentHeatingCoolingState\":   // 39\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            process.exit(0);\n\n            break;\n         }\n         case \"CurrentHorizontalTiltAngle\":   // 40\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentHumidifierDehumidifierState\":   // 41\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentMediaState\":   // 42\n         {\n            c = readData( device, characteristic );\n\n            //validValues:\n            //  \"PLAY\"\n            //  \"PAUSE\"\n            //  \"STOP\"\n            //  \"LOADING\"\n            //  \"INTERRUPTED\"\n\n            if ( c == \"\" ) process.stdout.write( \"STOP\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentPosition\":   // 43\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentRelativeHumidity\":   // 44\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"60.2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentSlatState\":   // 45\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentTemperature\":   // 46\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"22.2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentTiltAngle\":   // 47\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentTime\":   // 48\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"11.5\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentTransport\":   // 49\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentVerticalTiltAngle\": // 50\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CurrentVisibilityState\":   // 51\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DataStreamHAPTransport\":   // 52\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DataStreamHAPTransportInterrupt\":   // 53\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DayoftheWeek\":   // 54\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DiagonalFieldOfView\":   // 55\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DigitalZoom\":   // 56\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DiscoverBridgedAccessories\":   // 57\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DiscoveredBridgedAccessories\":   // 58\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"DisplayOrder\":   // 59\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"EventRetransmissionMaximum\":   // 60\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"EventSnapshotsActive\":   // 61\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"EventTransmissionCounters\":   // 62\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"FilterChangeIndication\":   // 63\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"FilterLifeLevel\":   // 64\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"FirmwareRevision\":   // 65\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100.1.1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"HardwareRevision\":   // 66\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100.1.1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"HeartBeat\":   // 67\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"64\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"HeatingThresholdTemperature\":   // 68\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"25.2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"HoldPosition\": // 69\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"HomeKitCameraActive\": // 70\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Hue\":   // 71\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Identifier\":   // 77\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ){\n               // Each identifier needs a unique number\n               // Match this with what is in the config.json\n               switch( device )\n               {\n                  case \"HDMI1\":\n                       process.stdout.write( \"0\" );\n                       break;\n                  case \"HDMI2\":\n                       process.stdout.write( \"1\" );\n                       break;\n                  case \"HDMI3\":\n                       process.stdout.write( \"2\" );\n                       break;\n                  case \"HDMI4\":\n                       process.stdout.write( \"3\" );\n                       break;\n                  case \"Netflix\":\n                       process.stdout.write( \"4\" );\n                       break;\n                  default:\n                       process.stdout.write( \"0\" );\n               }\n            } else {\n                  process.stdout.write( `\"${ c }\"` );\n            }\n\n            break;\n         }\n         case \"Identify\":   // 73\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ImageMirroring\":   // 74\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ImageRotation\":   // 75\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"InUse\":   // 76\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"InputDeviceType\":   // 77\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"InputSourceType\":   // 78\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"IsConfigured\":   // 79\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LeakDetected\":   // 80\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LinkQuality\":   // 81\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ListPairings\":   // 82\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LockControlPoint\":   // 83\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LockCurrentState\":   // 84\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LockLastKnownAction\":   // 85\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LockManagementAutoSecurityTimeout\":   // 86\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"26\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LockPhysicalControls\":   // 87\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"LockTargetState\":   // 88\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Logs\":   // 89\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"MACRetransmissionMaximum\":   // 90\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"MACTransmissionCounters\":   // 91\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ManagedNetworkEnable\":   // 92\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ManuallyDisabled\":   // 93\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Manufacturer\":   // 94\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"Homebridge\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Model\": // 95\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"MotionDetected\":   // 96\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Mute\":   // 97\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Name\":   // 98\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( `\"${ device }\"` ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NetworkAccessViolationControl\":   // 99\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NetworkClientProfileControl\":   // 100\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NetworkClientStatusControl\":   // 101\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NightVision\":   // 102\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NitrogenDioxideDensity\":   // 103\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ObstructionDetected\":   // 104\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"OccupancyDetected\":   // 105\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"On\":   // 106\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"OperatingStateResponse\":   // 107\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"OpticalZoom\":   // 108\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"OutletInUse\":   // 109\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"OzoneDensity\":   // 110\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PM10Density\":   // 111\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PM2_5Density\":   // 112\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PairSetup\":   // 113\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PairVerify\":   // 114\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PairingFeatures\":   // 115\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PairingPairings\":   // 116\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PasswordSetting\":   // 117\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PeriodicSnapshotsActive\":   // 118\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PictureMode\":   // 119\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Ping\":   // 120\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PositionState\":   // 121\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"PowerModeSelection\":   // 122\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ProductData\":   // 123\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ProgramMode\":   // 124\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ProgrammableSwitchEvent\":   // 125\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ProgrammableSwitchOutputState\":   // 126\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Reachable\":   // 127\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ReceivedSignalStrengthIndication\":   // 128\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ReceiverSensitivity\":   // 129\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RecordingAudioActive\":   // 130\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RelativeHumidityDehumidifierThreshold\":   // 131\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RelativeHumidityHumidifierThreshold\":   // 132\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RelayControlPoint\":   // 133\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RelayEnabled\":   // 134\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RelayState\":   // 135\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RemainingDuration\":   // 136\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RemoteKey\":   // 137\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ResetFilterIndication\":   // 138\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RotationDirection\":   // 139\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RotationSpeed\":   // 140\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"RouterStatus\":   // 141\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Saturation\":   // 142\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SecuritySystemAlarmType\":   // 143\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SecuritySystemCurrentState\":   // 144\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"3\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SecuritySystemTargetState\":   // 145\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SelectedAudioStreamConfiguration\":   // 146\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SelectedCameraRecordingConfiguration\":   // 147\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SelectedRTPStreamConfiguration\":   // 148\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SerialNumber\":   // 149\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"ABC001\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ServiceLabelIndex\":   // 150\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ServiceLabelNamespace\":   // 151\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SetDuration\":   // 152\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SetupDataStreamTransport\":   // 153\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SetupEndpoints\":   // 154\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SetupTransferTransport\":   // 155\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SignalToNoiseRatio\":   // 156\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriInputType\":   // 157\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SlatType\":   // 158\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SleepDiscoveryMode\":   // 159\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SleepInterval\":   // 160\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SmokeDetected\":   // 161\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SoftwareRevision\":   // 162\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StatusActive\":   // 163\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StatusFault\":   // 164\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StatusJammed\":   // 165\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StatusLowBattery\": // 166\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StatusTampered\":   // 167\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StreamingStatus\":   // 168\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SulphurDioxideDensity\":   // 169\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedAudioRecordingConfiguration\":   // 170\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedAudioStreamConfiguration\":   // 171\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedCameraRecordingConfiguration\":   // 172\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedDataStreamTransportConfiguration\":   // 173\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedCharacteristicValueTransitionConfiguration\":   // 174\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedDiagnosticsSnapshot\":   // 175\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedRTPConfiguration\":   // 176\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedRouterConfiguration\":   // 177\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedTransferTransportConfiguration\":   // 178\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedVideoRecordingConfiguration\":   // 179\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedVideoStreamConfiguration\":   // 180\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SwingMode\":   // 181\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"100\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetAirPurifierState\":   // 182\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetAirQuality\":   // 183\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetControlList\":   // 184\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetControlSupportedConfiguration\":   // 185\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetDoorState\":   // 186\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetFanState\":   // 187\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetHeaterCoolerState\":   // 188\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetHeatingCoolingState\":   // 189\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetHorizontalTiltAngle\":   // 190\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetHumidifierDehumidifierState\":   // 191\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetMediaState\":   // 192\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetPosition\":   // 193\n         {\n\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetRelativeHumidity\":   // 194\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetSlatState\":   // 195\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetTemperature\":   // 196\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"22.2\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetTiltAngle\":   // 197\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetVerticalTiltAngle\":   // 198\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TargetVisibilityState\":   // 199\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TemperatureDisplayUnits\":   // 200\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ThirdPartyCameraActive\":   // 201\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TimeUpdate\":   // 202\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TransmitPower\":   // 203\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"MaximumTransmitPower\":   // 204\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TunnelConnectionTimeout\":   // 205\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"5000\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TunneledAccessoryAdvertising\":   // 206\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TunneledAccessoryConnected\":   // 207\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TunneledAccessoryStateNumber\":   // 208\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"VOCDensity\":   // 209\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50.0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ValveType\":   // 210\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Version\":   // 211\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"LockVersion\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"VideoAnalysisActive\":   // 212\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Volume\":   // 213\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"VolumeControlType\":   // 214\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"VolumeSelector\":   // 215\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"1\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WANConfigurationList\":   // 216\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WANStatusList\":   // 217\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WakeConfiguration\":   // 218\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WaterLevel\":  // 219\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WiFiCapabilities\":   // 220\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"50\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WiFiConfigurationControl\":   // 221\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"WiFiSatelliteStatus\":  // 222\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AssetUpdateReadiness\":  // 223\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedAssetTypes\":  // 224\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ConfigurationState\":  // 225\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NFCAccessControlPoint\":  // 226\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NFCAccessSupportedConfiguration\":  // 227\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriEndpointSessionStatus\":  // 228\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ThreadControlPoint\":  // 229\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ThreadNodeCapabilities\":  // 230\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"ThreadStatus\":  // 231\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            // To avoid hard coding values, characteristic definitions can be found in:\n            // Cmd4 Github pages -> http://ztalbot2000.github.io/homebridge-cmd4\n            // Homebridge developer documentation -> https://developers.homebridge.io/#/\n\n            break;\n         }\n         case \"ThreadOpenThreadVersion\":  // 232\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         // New Mar 2024\n         case \"AccessCodeControlPoint\":  // 233\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AccessCodeSupportedConfiguration\":  // 234\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"AirPlayEnable\":  // 235\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CharacteristicValueActiveTransitionCount\":  // 236\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"CryptoHash\":  // 237\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"FirmwareUpdateReadiness\":  // 238\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"FirmwareUpdateStatus\":  // 239\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"HardwareFinish\":  // 240\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"MetricsBufferFullState\":  // 241\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"MultifunctionButton\":  // 242\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"NetworkAccessViolationControl\":  // 243\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SelectedDiagnosticsModes\":  // 244\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SelectedSleepConfiguration\":  // 245\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriEnable\":  // 246\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriEngineVersion\":  // 247\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriLightOnUse\":  // 248\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriListening\":  // 249\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SiriTouchToUse\":  // 250\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"StagedFirmwareVersion\":  // 251\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedMetrics\":  // 252\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"SupportedFirmwareUpdateConfiguration\":  // 253\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"TapType\":  // 254\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         case \"Token\":  // 255\n         {\n            c = readData( device, characteristic );\n\n            if ( c == \"\" ) process.stdout.write( \"0\" ); else process.stdout.write( `\"${ c }\"` );\n\n            break;\n         }\n         default:\n            process.stderr.write( `Unknown Characteristic for: ${ io } Device: ${ device } Characteristic: ${ characteristic }` );\n            process.exit( -1 );\n       }\n\n       break;\n\n   } // End of Switch for \"Get\"\n   case \"Set\":\n   {\n      switch( characteristic )\n      {\n         case \"AccessControlLevel\":   // 0\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"AccessoryFlags\":   // 1\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"AccessoryIdentifier\":   // 2\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Active\":   // 3\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ActiveIdentifier\":   // 4\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ActivityInterval\":   // 5\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"AdministratorOnlyAccess\":   // 6\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"AirParticulateDensity\":   // 7\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"AirParticulateSize\":   // 8\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"AirQuality\":   // 9\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"AppMatchingIdentifier\":   // 10\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"AudioFeedback\":   // 11\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"BatteryLevel\":   // 12\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Brightness\":   // 13\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ButtonEvent\":   // 14\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CCAEnergyDetectThreshold\":   // 15\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CCASignalDetectThreshold\":   // 16\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CameraOperatingModeIndicator\":   // 17\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CarbonDioxideDetected\":   // 18\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CarbonDioxideLevel\":   // 19\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CarbonDioxidePeakLevel\":   // 20\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CarbonMonoxideDetected\":   // 21\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CarbonMonoxideLevel\":   // 22\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CarbonMonoxidePeakLevel\":   // 23\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Category\":   // 24\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CharacteristicValueTransitionControl\":   // 25\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ChargingState\":   // 26\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ClosedCaptions\":   // 27\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ColorTemperature\":   // 28\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ConfigureBridgedAccessory\":   // 29\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ConfigureBridgedAccessoryStatus\":   // 30\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ConfiguredName\":   // 31\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ContactSensorState\":   // 32\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CoolingThresholdTemperature\":   // 33\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CurrentAirPurifierState\":   // 34\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentAmbientLightLevel\":   // 35\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentDoorState\":   // 36\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentFanState\":   //  37\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentHeaterCoolerState\":   // 38\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentHeatingCoolingState\":   // 39\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentHorizontalTiltAngle\":   // 40\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentHumidifierDehumidifierState\":   // 41\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CurrentMediaState\":   // 42\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CurrentPosition\":   // 43\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentRelativeHumidity\":   // 44\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentSlatState\":   // 45\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentTemperature\":   // 46\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentTiltAngle\":   // 47\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentTime\":   // 48\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CurrentTransport\":   // 49\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentVerticalTiltAngle\":   // 50\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"CurrentVisibilityState\":   // 51\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"DataStreamHAPTransport\":   // 52\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"DataStreamHAPTransportInterrupt\":   // 53\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"DayoftheWeek\":   // 54\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"DiagonalFieldOfView\":   // 55\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"DigitalZoom\":   // 56\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"DiscoverBridgedAccessories\":   // 57\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"DiscoveredBridgedAccessories\":   // 58\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"DisplayOrder\":  // 59\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"EventRetransmissionMaximum\":  // 60\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"EventSnapshotsActive\":  // 61\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"EventTransmissionCounters\":  // 62\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"FilterChangeIndication\":   // 63\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"FilterLifeLevel\":   // 64\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"FirmwareRevision\":   // 65\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"HardwareRevision\":   // 66\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"HeartBeat\":   // 67\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"HeatingThresholdTemperature\": // 68\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"HoldPosition\":   // 69\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"HomeKitCameraActive\":   // 70\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Hue\":   // 71\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Identifier\":   // 72\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Identify\":   // 73\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ImageMirroring\":   // 74\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ImageRotation\":   // 75\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"InUse\":   // 76\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"InputDeviceType\":   // 77\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"InputSourceType\":   // 78\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"IsConfigured\":   // 79\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"LeakDetected\":   // 80\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"LinkQuality\":   // 81\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ListPairings\":   // 82\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"LockControlPoint\":   // 83\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"LockCurrentState\":   // 84\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"LockLastKnownAction\":   // 85\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"LockManagementAutoSecurityTimeout\":   // 86\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"LockPhysicalControls\":   // 87\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"LockTargetState\":   // 88\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData(device, \"LockCurrentState\", option);\n\n            break;\n         }\n         case \"Logs\":   // 89\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"MACRetransmissionMaximum\":   // 90\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"MACTransmissionCounters\":   // 91\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ManagedNetworkEnable\":   // 92\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ManuallyDisabled\":   // 93\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Manufacturer\":   // 94\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Model\":   // 95\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"MotionDetected\":   // 96\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Mute\":   // 97\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Name\":   // 98\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"NetworkAccessViolationControl\":   // 99\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NetworkClientProfileControl\":   // 100\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NetworkClientStatusControl\":   // 101\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NightVision\":   // 102\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NitrogenDioxideDensity\":   // 103\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ObstructionDetected\":   // 104\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"OccupancyDetected\":   // 105\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"On\":  // 106\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"OperatingStateResponse\":  // 107\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"OpticalZoom\":   // 108\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"OutletInUse\":   // 109\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"OzoneDensity\":   // 110\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"PM10Density\":   // 111\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"PM2_5Density\":   // 112\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"PairSetup\":   // 113\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"PairVerify\":   // 114\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"PairingFeatures\":   // 115\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"PairingPairings\":   // 116\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"PasswordSetting\":   // 117\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"PeriodicSnapshotsActive\":   // 118\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"PictureMode\":   // 119\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Ping\":   // 120\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"PositionState\":   // 121\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"PowerModeSelection\":   // 122\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ProductData\":   // 123\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ProgramMode\":   // 124\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ProgrammableSwitchEvent\":   // 125\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ProgrammableSwitchOutputState\":   // 126\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Reachable\":   // 127\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ReceivedSignalStrengthIndication\":   // 128\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ReceiverSensitivity\":   // 129\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"RecordingAudioActive\":   // 130\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RelativeHumidityDehumidifierThreshold\":   // 131\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RelativeHumidityHumidifierThreshold\":   // 132\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RelayControlPoint\":   // 133\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"RelayEnabled\":   // 134\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RelayState\":   // 135\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"RemainingDuration\":   // 136\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"RemoteKey\":   // 137\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ResetFilterIndication\":   // 138\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RotationDirection\":   // 139\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RotationSpeed\":   // 140\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"RouterStatus\":   // 141\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Saturation\":   // 142\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SecuritySystemAlarmType\":   // 143\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SecuritySystemCurrentState\":   // 144\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SecuritySystemTargetState\":   // 145\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"SecuritySystemCurrentState\", option);\n\n            break;\n         }\n         case \"SelectedAudioStreamConfiguration\":   // 146\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SelectedCameraRecordingConfiguration\":   // 147\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SelectedRTPStreamConfiguration\":   // 148\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SerialNumber\":   // 149\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ServiceLabelIndex\":   // 150\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ServiceLabelNamespace\":   // 151\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SetDuration\":   // 152\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SetupDataStreamTransport\":   // 153\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SetupEndpoints\":   // 154\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SetupTransferTransport\":   // 155\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SignalToNoiseRatio\":   // 156\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriInputType\":   // 157\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SlatType\":   // 158\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SleepDiscoveryMode\":   // 159\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SleepInterval\":   // 160\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SmokeDetected\":   // 161\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SoftwareRevision\":   // 162\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StatusActive\":   // 163\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StatusFault\":   // 164\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StatusJammed\":   // 165\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StatusLowBattery\":   // 166\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StatusTampered\":   // 167\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"StreamingStatus\":   // 168\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SulphurDioxideDensity\":   // 169\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedAudioRecordingConfiguration\":   // 170\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedAudioStreamConfiguration\":   // 171\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedCameraRecordingConfiguration\":   // 172\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedDataStreamTransportConfiguration\":   // 173\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedCharacteristicValueTransitionConfiguration\":   // 174\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedDiagnosticsSnapshot\":   // 175\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedRTPConfiguration\":   // 176\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedRouterConfiguration\":   // 177\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedTransferTransportConfiguration\":   // 178\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedVideoRecordingConfiguration\":   // 179\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SupportedVideoStreamConfiguration\":   // 180\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"SwingMode\":   // 181\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"TargetAirPurifierState\":   // 182\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentAirPurifierState\", option);\n\n            break;\n         }\n         case \"TargetAirQuality\":   // 183\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device, \"AirQuality\", option);\n\n            break;\n         }\n         case \"TargetControlList\":   // 184\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"TargetControlSupportedConfiguration\":   // 185\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"TargetDoorState\":   // 186\n         {\n            writeData( device, characteristic, option );\n\n            // Set to Done\n            writeData(device, \"CurrentDoorState\", option);\n\n            break;\n         }\n         case \"TargetFanState\":   // 187\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData(device, \"CurrentFanState\", option);\n\n            break;\n         }\n         case \"TargetHeaterCoolerState\":   // 188\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData(device, \"CurrentHeaterCoolerState\", option);\n\n            break;\n         }\n         case \"TargetHeatingCoolingState\":   // 189\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it Done\n            writeData(device, \"CurrentHeatingCoolingState\", option);\n\n            break;\n         }\n         case \"TargetHorizontalTiltAngle\":   // 190\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentHorizontalTiltAngle\", option);\n\n            break;\n         }\n         case \"TargetHumidifierDehumidifierState\":   // 191\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentHumidifierDehumidifierState\", option);\n\n            break;\n         }\n         case \"TargetMediaState\":   // 192\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentMediaState\", option);\n\n            break;\n         }\n         case \"TargetPosition\":   // 193\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentPosition\", option);\n\n            break;\n         }\n         case \"TargetRelativeHumidity\":   // 194\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device, \"CurrentRelativeHumidity\", option);\n\n            break;\n         }\n         case \"TargetSlatState\":   // 195\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device, \"CurrentSlatState\", option);\n\n            break;\n         }\n         case \"TargetTemperature\":   // 196\n         {\n            writeData( device, characteristic, option );\n\n            // Fake it\n            writeData(device, \"CurrentTemperature\", option);\n\n            break;\n         }\n         case \"TargetTiltAngle\":   // 197\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentTiltAngle\", option);\n\n            break;\n         }\n         case \"TargetVerticalTiltAngle\":   // 198\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentVerticalTiltAngle\", option);\n\n            break;\n         }\n         case \"TargetVisibilityState\":   // 199\n         {\n            writeData( device, characteristic, option );\n\n            // Set to done\n            writeData(device,\"CurrentVisibilityState\", option);\n\n            break;\n         }\n         case \"TemperatureDisplayUnits\":   // 200\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ThirdPartyCameraActive\":   // 201\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"TimeUpdate\":   // 202\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"TransmitPower\":   // 203\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"MaximumTransmitPower\":   // 204\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"TunnelConnectionTimeout\":   // 205\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"TunneledAccessoryAdvertising\":   // 206\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"TunneledAccessoryConnected\":   // 207\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"TunneledAccessoryStateNumber\":   // 208\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"VOCDensity\":   // 209\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"ValveType\":   // 210\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"Version\":   // 211\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"VideoAnalysisActive\":   // 212\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Volume\":   // 213\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"VolumeControlType\":   // 214\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"VolumeSelector\":   // 215\n         {\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"WANConfigurationList\":   // 216\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"WANStatusList\":   // 217\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"WakeConfiguration\":   // 218\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"WaterLevel\":   // 219\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"WiFiCapabilities\":   // 220\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"WiFiConfigurationControl\":   // 221\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n         case \"WiFiSatelliteStatus\":   // 222\n         {\n            writeData( device, characteristic, option );\n\n            // Not settable in Hap Spec, here for debugging.\n            break;\n         }\n\n         case \"AssetUpdateReadiness\":  // 223\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SupportedAssetTypes\":  // 224\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ConfigurationState\":  // 225\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NFCAccessControlPoint\":  // 226\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NFCAccessSupportedConfiguration\":  // 227\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriEndpointSessionStatus\":  // 228\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ThreadControlPoint\":  // 229\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ThreadNodeCapabilities\":  // 230\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ThreadStatus\":  // 231\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"ThreadOpenThreadVersion\":  // 232\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         // New Mar 2024\n         case \"AccessCodeControlPoint\":  // 233\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"AccessCodeSupportedConfiguration\":  // 234\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"AirPlayEnable\":  // 235\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CharacteristicValueActiveTransitionCount\":  // 236\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"CryptoHash\":  // 237\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"FirmwareUpdateReadiness\":  // 238\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"FirmwareUpdateStatus\":  // 239\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"HardwareFinish\":  // 240\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"MetricsBufferFullState\":  // 241\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"MultifunctionButton\":  // 242\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"NetworkAccessViolationControl\":  // 243\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SelectedDiagnosticsModes\":  // 244\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SelectedSleepConfiguration\":  // 245\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriEnable\":  // 246\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriEngineVersion\":  // 247\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriLightOnUse\":  // 248\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriListening\":  // 249\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SiriTouchToUse\":  // 250\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"StagedFirmwareVersion\":  // 251\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SupportedMetrics\":  // 252\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"SupportedFirmwareUpdateConfiguration\":  // 253\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"TapType\":  // 254\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         case \"Token\":  // 255\n         {\n            c = readData( device, characteristic );\n\n            writeData( device, characteristic, option );\n\n            break;\n         }\n         default:\n            process.stderr.write( `Unknown Characteristic for: ${ io } Device:${ device  } Characteristic:${ characteristic }` );\n            process.exit( -1 );\n      }\n\n      break;\n   } // End of Switch Device for \"Set\"\n   default:\n      process.stderr.write( `Unknown IO ${ io }` );\n      process.exit( -1 );\n}\n\n//process.stdout.write( `Say What Device: ${ device } Characteristic: ${ characteristic } Option: ${ option }` );\n\nprocess.exit( 0 );\n\n\n"
  },
  {
    "path": "Extras/config.json",
    "content": "{\n   \"bridge\":\n   {\n      \"name\": \"MAC Test Homebridge\",\n      \"username\": \"CC:22:3D:E3:CE:30\",\n      \"port\": 51826,\n      \"pin\": \"555-55-555\"\n   },\n   \"platforms\" :\n   [\n      {\n         \"platform\":                       \"Cmd4\",\n         \"name\":                           \"Cmd4\",\n         \"debug\":                           false,\n         \"allowTLV8\":                       false,\n         \"outputConstants\":                 false,\n         \"accessories\" :\n         [\n            {\n               \"type\":                     \"Fanv1\",\n               \"displayName\":              \"MyV1Fan\",\n               \"on\":                       \"FALSE\",\n               \"name\":                     \"MyV1Fan\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Fan\",\n               \"displayName\":              \"MyFan\",\n               \"on\":                       \"FALSE\",\n               \"rotationDirection\":        \"COUNTER_CLOCKWISE\",\n               \"rotationSpeed\":             100,\n               \"name\":                     \"MyFan\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"outputConstants\":           true,\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Fanv2\",\n               \"displayName\":              \"MyV2Fan\",\n               \"active\":                   \"INACTIVE\",\n               \"currentFanState\":          \"IDLE\",\n               \"targetFanState\":           \"AUTO\",\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",\n               \"rotationDirection\":        \"CLOCKWISE\",\n               \"rotationSpeed\":             100,\n               \"swingMode\":                \"SWING_ENABLED\",\n               \"name\":                     \"MyV2Fan\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"GarageDoorOpener\",\n               \"displayName\":              \"MyGarageDoorOpener\",\n               \"currentDoorState\":         \"OPEN\",\n               \"targetDoorState\":          \"OPEN\",\n               \"obstructionDetected\":      \"FALSE\",\n               \"lockCurrentState\":         \"UNSECURED\",\n               \"lockTargetState\":          \"UNSECURED\",\n               \"name\":                     \"MyGarageDoorOpener\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   10,\n               \"state_cmd_prefix\":         \"node\"\n            },\n            {\n               \"type\":                     \"Lightbulb\",\n               \"displayName\":              \"MyOnOffLight\",\n               \"on\":                       \"FALSE\",\n               \"name\":                     \"MyOnOffLight\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Lightbulb\",\n               \"displayName\":              \"MyDimmableLight\",\n               \"on\":                       \"FALSE\",\n               \"brightness\":                8,\n               \"hue\":                       8,\n               \"saturation\":                8,\n               \"colorTemperature\":          8,\n               \"name\":                     \"MyDimmableLight\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"LockManagement\",\n               \"displayName\":              \"MyLockManagement\",\n               \"version\":                  \"1.2.3\",\n               \"audioFeedback\":            \"FALSE\",\n               \"lockManagementAutoSecurityTimeout\":\n                                            20,\n               \"administratorOnlyAccess\":  \"FALSE\",\n               \"lockLastKnownAction\":      \"SECURED_PHYSICALLY_INTERIOR\",\n               \"currentDoorState\":         \"OPEN\",\n               \"motionDetected\":           \"FALSE\",\n               \"name\":                     \"MyLockManagement\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"LockMechanism\",\n               \"displayName\":              \"MyLockMechanism\",\n               \"lockCurrentState\":         \"UNSECURED\",\n               \"lockTargetState\":          \"UNSECURED\",\n               \"name\":                     \"MyLockMechanism\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Outlet\",\n               \"displayName\":              \"MyOutlet\",\n               \"on\":                       \"FALSE\",\n               \"outletInUse\":              \"FALSE\",\n               \"name\":                     \"MyOutlet\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Switch\",\n               \"displayName\":              \"MySwitch\",\n               \"on\":                       \"FALSE\",\n               \"name\":                     \"MySwitch\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Thermostat\",\n               \"displayName\":              \"MyThermostat\",\n               \"currentHeatingCoolingState\":\n                                           \"OFF\",\n               \"targetHeatingCoolingState\":\n                                           \"OFF\",\n               \"currentTemperature\":        22.2,\n               \"targetTemperature\":         22.2,\n               \"temperatureDisplayUnits\":  \"CELSIUS\",\n               \"currentRelativeHumidity\":   60,\n               \"targetRelativeHumidity\":    60,\n               \"coolingThresholdTemperature\":\n                                            22.2,\n               \"heatingThresholdTemperature\":\n                                            25.2,\n               \"name\":                     \"MyThermostat\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   10\n            },\n            {\n               \"type\":                     \"AirQualitySensor\",\n               \"displayName\":              \"MyAirQualitySensor\",\n               \"airQuality\":               \"EXCELLENT\",\n               \"ozoneDensity\":              50,\n               \"nitrogenDioxideDensity\":    50,\n               \"sulphurDioxideDensity\":     50,\n               \"pm2_5Density\":              50,\n               \"pm10Density\":               50,\n               \"vocDensity\":                50,\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyAirQualitySensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"SecuritySystem\",\n               \"displayName\":              \"MySecuritySystem\",\n               \"securitySystemCurrentState\":\n                                           \"DISARMED\",\n               \"securitySystemTargetState\":\n                                           \"DISARM\",\n               \"securitySystemAlarmType\":   0,\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"name\":                     \"MySecuritySystem\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"CarbonMonoxideSensor\",\n               \"displayName\":              \"MyCOSensor\",\n               \"carbonMonoxideDetected\":   \"CO_LEVELS_NORMAL\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"carbonMonoxideLevel\":       0,\n               \"carbonMonoxidePeakLevel\":   0,\n               \"name\":                     \"MyCOSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"ContactSensor\",\n               \"displayName\":              \"MyContactSensor\",\n               \"contactSensorState\":       \"CONTACT_DETECTED\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyContactSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Door\",\n               \"displayName\":              \"MyDoor\",\n               \"currentPosition\":           0,\n               \"targetPosition\":            0,\n               \"positionState\":            \"STOPPED\",\n               \"holdPosition\":             \"FALSE\",\n               \"obstructionDetected\":      \"FALSE\",\n               \"name\":                     \"MyDoor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"HumiditySensor\",\n               \"displayName\":              \"MyHumiditySensor\",\n               \"currentRelativeHumidity\":   1,\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyHumiditySensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"LeakSensor\",\n               \"displayName\":              \"MyLeakSensor\",\n               \"leakDetected\":             \"LEAK_NOT_DETECTED\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyLeakSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"LightSensor\",\n               \"displayName\":              \"MyLightSensor\",\n               \"currentAmbientLightLevel\":  1,\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyLightSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"MotionSensor\",\n               \"displayName\":              \"MyMotionSensor\",\n               \"motionDetected\":           \"FALSE\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyMotionSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"OccupancySensor\",\n               \"displayName\":              \"MyOccupancySensor\",\n               \"occupancyDetected\":        \"OCCUPANCY_NOT_DETECTED\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyOccupancySensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"SmokeSensor\",\n               \"displayName\":              \"MySmokeSensor\",\n               \"smokeDetected\":            \"SMOKE_NOT_DETECTED\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MySmokeSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"StatefulProgrammableSwitch\",\n               \"displayName\":              \"MyStatefulProgrammableSwitch\",\n               \"programmableSwitchEvent\":  \"SINGLE_PRESS\",\n               \"programmableSwitchOutputState\":\n                                            0,\n               \"name\":                     \"MyStatefulProgrammableSwitch\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"StatelessProgrammableSwitch\",\n               \"displayName\":              \"MyStatelessProgrammableSwitch\",\n               \"programmableSwitchEvent\":  \"SINGLE_PRESS\",\n               \"name\":                     \"MyStatelessProgrammableSwitch\",\n               \"serviceLabelIndex\":         1,\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"TemperatureSensor\",\n               \"displayName\":              \"MyTemperatureSensor\",\n               \"currentTemperature\":        22.2,\n               \"currentRelativeHumidity\":   20,\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyTemperatureSensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Window\",\n               \"displayName\":              \"MyWindow\",\n               \"currentPosition\":           0,\n               \"targetPosition\":            0,\n               \"positionState\":            \"STOPPED\",\n               \"holdPosition\":             \"FALSE\",\n               \"obstructionDetected\":      \"FALSE\",\n               \"name\":                     \"MyWindow\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"WindowCovering\",\n               \"displayName\":              \"MyWindowCovering\",\n               \"currentPosition\":           0,\n               \"targetPosition\":            0,\n               \"positionState\":            \"STOPPED\",\n               \"holdPosition\":             \"FALSE\",\n               \"currentHorizontalTiltAngle\":0,\n               \"targetHorizontalTiltAngle\": 0,\n               \"currentVerticalTiltAngle\":  0,\n               \"targetVerticalTiltAngle\":   0,\n               \"obstructionDetected\":      \"FALSE\",\n               \"name\":                     \"MyWindowCovering\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Battery\",\n               \"displayName\":              \"MyBattery\",\n               \"batteryLevel\":              50,\n               \"chargingState\":            \"NOT_CHARGING\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"name\":                     \"MyBatteryService\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"CarbonDioxideSensor\",\n               \"displayName\":              \"MyCO2Sensor\",\n               \"carbonDioxideDetected\":    \"CO2_LEVELS_NORMAL\",\n               \"statusActive\":             \"TRUE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"statusTampered\":           \"NOT_TAMPERED\",\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",\n               \"carbonDioxideLevel\":        0,\n               \"carbonDioxidePeakLevel\":    0,\n               \"name\":                     \"MyCO2Sensor\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"interval\":                  540,\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Microphone\",\n               \"displayName\":              \"MyMicrophone\",\n               \"mute\":                     \"FALSE\",\n               \"volume\":                    5,\n               \"name\":                     \"MyMicrophone\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Speaker\",\n               \"displayName\":              \"MySpeaker\",\n               \"mute\":                     \"FALSE\",\n               \"volume\":                    5,\n               \"name\":                     \"MySpeaker\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"DoorBell\",\n               \"displayName\":              \"MyDoorBell\",\n               \"programmableSwitchEvent\":  \"SINGLE_PRESS\",\n               \"brightness\":                8,\n               \"volume\":                    5,\n               \"name\":                     \"MyDoorBell\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Slats\",\n               \"displayName\":              \"MySlats\",\n               \"slatType\":                 \"HORIZONTAL\",\n               \"currentSlatState\":         \"FIXED\",\n               \"name\":                     \"MySlat\",\n               \"currentTiltAngle\":          0,\n               \"targetTiltAngle\":           0,\n               \"swingMode\":                \"SWING_ENABLED\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"interval\":                  540,\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                    \"FilterMaintenance\",\n               \"displayName\":             \"MyFilterMaintenance\",\n               \"filterChangeIndication\":   \"FILTER_OK\",\n               \"filterLifeLevel\":           50,\n               \"resetFilterIndication\":     1,\n               \"name\":                     \"MyFilterMaintenance\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"AirPurifier\",\n               \"displayName\":              \"MyAirPurifier\",\n               \"active\":                   \"ACTIVE\",\n               \"currentAirPurifierState\":  \"INACTIVE\",\n               \"targetAirPurifierState\":   \"MANUAL\",\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",\n               \"name\":                     \"MyAirPurifier\",\n               \"swingMode\":                \"SWING_DISABLED\",\n               \"rotationSpeed\":             0,\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"ServiceLabel\",\n               \"displayName\":              \"MyServiceLabel\",\n               \"serviceLabelNamespace\":    \"DOTS\",\n               \"name\":                     \"MyServiceLabel\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                      \"Television\",\n               \"displayName\":               \"Tv_Combo\",\n               \"publishExternally\":          true,\n               \"category\":                  \"TELEVISION\",\n               \"active\":                    \"ACTIVE\",\n               \"activeIdentifier\":           1,\n               \"configuredName\":            \"TV_Combo\",\n               \"sleepDiscoveryMode\":        \"ALWAYS_DISCOVERABLE\",\n               \"linkedTypes\":\n               [\n                  {\n                     \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI1\",\n                     \"configuredName\":         \"HDMI1\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n                     \"identifier\":              1,\n                     \"targetVisibilityState\":  \"SHOWN\",\n                     \"name\":                   \"HDMI1\",\n                     \"manufacturer\":           \"Somebody\",\n                     \"model\":                  \"Anything\",\n                     \"serialNumber\":           \"12345\"\n                 },\n                 {   \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI2\",\n                     \"configuredName\":         \"HDMI2\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n                     \"identifier\":             2,\n                     \"targetVisibilityState\":  \"SHOWN\",\n                     \"name\":                   \"HDMI2\",\n                     \"manufacturer\":           \"Somebody\",\n                     \"model\":                  \"Anything\",\n                     \"serialNumber\":           \"12345\"\n                  },\n                  {  \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI3\",\n                     \"configuredName\":         \"HDMI3\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n                     \"identifier\":              3,\n                     \"targetVisibilityState\":  \"SHOWN\",\n                     \"name\":                   \"HDMI3\",\n                     \"manufacturer\":           \"Somebody\",\n                     \"model\":                  \"Anything\",\n                     \"serialNumber\":           \"12345\"\n                  },\n                  {  \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI4\",\n                     \"configuredName\":         \"HDMI4\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n                     \"identifier\":              4,\n                     \"targetVisibilityState\":  \"SHOWN\",\n                     \"name\":                   \"HDMI4\",\n                     \"manufacturer\":           \"Somebody\",\n                     \"model\":                  \"Anything\",\n                     \"serialNumber\":           \"12345\"\n                  },\n                  {  \"type\":                   \"InputSource\",\n                     \"displayName\":            \"Netflix\",\n                     \"configuredName\":         \"Netflix\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"APPLICATION\",\n                     \"isConfigured\":           \"CONFIGURED\",\n                     \"identifier\":              5,\n                     \"targetVisibilityState\":  \"SHOWN\",\n                     \"name\":                   \"Netflix\",\n                     \"manufacturer\":           \"Somebody\",\n                     \"model\":                  \"Anything\",\n                     \"serialNumber\":           \"12345\"\n                  },\n                  {  \"type\":                   \"TelevisionSpeaker\",\n                     \"displayName\":            \"TVSpeaker\",\n                     \"mute\":                   \"FALSE\",\n                     \"active\":                 \"ACTIVE\",\n                     \"volume\":                 10,\n                     \"volumeControlType\":      \"ABSOLUTE\",\n                     \"volumeSelector\":         \"INCREMENT\",\n                     \"name\":                   \"TVSpeaker\",\n                     \"manufacturer\":           \"Somebody\",\n                     \"model\":                  \"Anything\",\n                     \"serialNumber\":           \"12345\"\n                  }\n               ],\n               \"brightness\":                8,\n               \"closedCaptions\":           \"DISABLED\",\n               \"currentMediaState\":        \"STOP\",\n               \"targetMediaState\":         \"STOP\",\n               \"pictureMode\":              \"STANDARD\",\n               \"remoteKey\":                \"SELECT\",\n               \"manufacturer\":             \"Sony\",\n               \"model\":                    \"Android TV\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\": \"TelevisionSpeaker\",\n               \"displayName\": \"MyTVSpeaker\",\n               \"mute\":                     \"FALSE\",\n               \"active\":                   \"ACTIVE\",\n               \"volume\":                    5,\n               \"volumeControlType\":        \"ABSOLUTE\",\n               \"volumeSelector\":           \"INCREMENT\",\n               \"name\":                     \"MyTVSpeaker\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"InputSource\",\n               \"displayName\":              \"MyInputSource\",\n               \"configuredName\":           \"MyInputSource\",\n               \"inputSourceType\":          \"HDMI\",\n               \"isConfigured\":            \"CONFIGURED\",\n               \"currentVisibilityState\":  \"SHOWN\",\n               \"inputDeviceType\":          \"TV\",\n               \"targetVisibilityState\":    \"SHOWN\",\n               \"name\":                     \"MyInputSource\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"IrrigationSystem\",\n               \"displayName\":              \"MyIrrigationSystem\",\n               \"active\":                   \"ACTIVE\",\n               \"programMode\":              \"PROGRAM_SCHEDULED\",\n               \"inUse\":                    \"IN_USE\",\n               \"remainingDuration\":         60,\n               \"statusFault\":              \"NO_FAULT\",\n               \"name\":                     \"MyIrrigationSystem\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"Faucet\",\n               \"displayName\":              \"MyFaucet\",\n               \"active\":                   \"ACTIVE\",\n               \"statusFault\":              \"NO_FAULT\",\n               \"name\":                     \"MyFaucet\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"CloudRelay\",\n               \"displayName\":              \"MyCloudRelay\",\n               \"relayEnabled\":             \"FALSE\",\n               \"relayState\":                0,\n               \"stateChangeResponseTime\":   10\n            },\n            {\n               \"type\":                     \"Valve\",\n               \"displayName\":              \"MyValve\",\n               \"active\":                   \"ACTIVE\",\n               \"inUse\":                    \"NOT_IN_USE\",\n               \"valveType\":                \"GENERIC_VALVE\",\n               \"setDuration\":               0,\n               \"remainingDuration\":         0,\n               \"isConfigured\":             \"CONFIGURED\",\n               \"serviceLabelIndex\":         1,\n               \"statusFault\":              \"NO_FAULT\",\n               \"name\":                     \"MyValve\",\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"HeaterCooler\",\n               \"displayName\":              \"MyHeaterCooler\",\n               \"active\":                   \"ACTIVE\",\n               \"currentHeaterCoolerState\": \"HEATING\",\n               \"targetHeaterCoolerState\":  \"AUTO\",\n               \"currentTemperature\":        37.0,\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",\n               \"name\":                     \"MyHeaterCooler\",\n               \"swingMode\":                \"SWING_ENABLED\",\n               \"coolingThresholdTemperature\":\n                                            22.2,\n               \"heatingThresholdTemperature\":\n                                            25.2,\n               \"temperatureDisplayUnits\":  \"CELSIUS\",\n               \"rotationSpeed\":             100,\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"HumidifierDehumidifier\",\n               \"displayName\":              \"MyHumidifierDehumidifier\",\n               \"currentRelativeHumidity\":   60,\n               \"currentHumidifierDehumidifierState\":\n                                           \"HUMIDIFYING\",\n               \"targetHumidifierDehumidifierState\":\n                                           \"HUMIDIFIER\",\n               \"active\":                   \"ACTIVE\",\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",\n               \"name\":                     \"MyHumidifierDehumidifier\",\n               \"swingMode\":                \"SWING_DISABLED\",\n               \"waterLevel\":                0,\n               \"relativeHumidityDehumidifierThreshold\":\n                                            0,\n               \"relativeHumidityHumidifierThreshold\":\n                                            0,\n               \"rotationSpeed\":             0,\n               \"manufacturer\":             \"Somebody\",\n               \"model\":                    \"Anything\",\n               \"serialNumber\":             \"12345\",\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"AccessControl\",\n               \"displayName\":              \"MyAccessControl\",\n               \"accessControlLevel\":        0,\n               \"stateChangeResponseTime\":   3\n            },\n            {\n               \"type\":                     \"CameraOperatingMode\",\n               \"displayName\":              \"MyCameraOperatingMode\",\n               \"eventSnapshotsActive\":     \"DISABLE\",\n               \"homeKitCameraActive\":      \"OFF\",\n               \"manuallyDisabled\":         \"DISABLED\",\n               \"nightVision\":              \"FALSE\",\n               \"thirdPartyCameraActive\":   \"OFF\",\n               \"periodicSnapshotsActive\":  \"DISABLE\"\n            },\n            {\n               \"type\":                     \"SmartSpeaker\",\n               \"displayName\":              \"MySmartSpeaker\",\n               \"currentMediaState\":        \"STOP\",\n               \"targetMediaState\":         \"STOP\",\n               \"name\":                     \"MySmartSpeaker\",\n               \"configuredName\":           \"MySmartSpeaker\",\n               \"volume\":                    5,\n               \"mute\":                     \"FALSE\"\n            },\n            {\n               \"type\":                     \"TargetControl\",\n               \"displayName\":              \"MyTargetControl\",\n               \"activeIdentifier\":          1183,\n               \"active\":                   \"ACTIVE\"\n            },\n            {\n               \"type\":                    \"WiFiSatellite\",\n               \"displayName\":             \"MyWiFiSatellite\",\n               \"wifiSatelliteStatus\":     \"NOT_CONNECTED\"\n            }\n          ]\n       }\n   ]\n}\n"
  },
  {
    "path": "Extras/config.min.json",
    "content": "{\n   \"bridge\":\n   {\n      \"name\": \"MAC Test Homebridge\",\n      \"username\": \"CC:22:3D:E3:CE:30\",\n      \"port\": 51826,\n      \"pin\": \"555-55-555\"\n   },\n   \"platforms\" :\n   [\n      {\n         \"platform\":                       \"Cmd4\",\n         \"name\":                           \"Cmd4\",\n         \"debug\":                           false,                   // Output debug logs\n\n         \"allowTLV8\":                       false,                   // Allow TLV8 Characteristics\n                                                                     // These cannot be described easily\n                                                                     // in JSON format. They are usually\n                                                                     // binary formats.\n                                                                     // The default is false.\n         \"outputConstants\":                 false,                   // Instead of numeric values, output\n                                                                     // the value in string form.\n                                                                     // The default is false.\n         \"accessories\" :\n         [\n            {\n               \"type\":                     \"Fanv1\",\n               \"displayName\":              \"MyV1Fan\",                // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"on\":                       \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"name\":                     \"MyV1Fan\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n\n               // Paramaters to state_cmd are:\n               // Get <accessory name> <characteristic>\n               // Set <accessory name> <characteristic> <value>\n               // \"Note\": There is no need for an on_cmd or off_cmd\n               //       with this kind of detail.\n\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Fan\",\n               \"displayName\":              \"MyFan\",                  // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"on\":                       \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"rotationDirection\":        \"COUNTER_CLOCKWISE\",      // 0 - \"CLOCKWISE\"\n                                                                     // 1 - \"COUNTER_CLOCKWISE\"\n\n\n               \"rotationSpeed\":             100,                     // Range: 0-100, Step: 1\n\n               \"name\":                     \"MyFan\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"outputConstants\":           true,                    // For this accessory, output constants\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"rotationDirection\",    \"interval\": 40, \"timeout\": 8000},\n               //   {\"characteristic\": \"on\",                   \"interval\": 40, \"timeout\": 8000}\n               //],\n\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n\n               // Paramaters to state_cmd are:\n               // Get <accessory name> <characteristic>\n               // Set <accessory name> <characteristic> <value>\n               // \"Note\": There is no need for an on_cmd or off_cmd\n               //       with this kind of detail.\n\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Fanv2\",\n               \"displayName\":              \"MyV2Fan\",                // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"active\":                   \"INACTIVE\",               // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               // Optional Characteristics\n               \"currentFanState\":          \"IDLE\",\n                                                                     // 0 - \"INACTIVE\"\n                                                                     // 1 - \"IDLE\"\n                                                                     // 2 - \"BLOWING_AIR\"\n\n               \"targetFanState\":           \"AUTO\",\n                                                                     // 0 - \"MANUAL\"\n                                                                     // 1 - \"AUTO\"\n\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",  // 0 - \"CONTROL_LOCK_DISABLED\"\n                                                                     // 1 - \"CONTROL_LOCK_ENABLED\"\n\n               \"rotationDirection\":        \"CLOCKWISE\",              // 0 - \"COUNTER_CLOCKWISE\"\n                                                                     // 1 - \"CLOCKWISE\"\n\n               \"rotationSpeed\":             100,                     // Range: 0-100, Step: 1\n\n               \"swingMode\":                \"SWING_ENABLED\",          // 0 - \"SWING_DISABLED\",\n                                                                     // 1 - \"SWING_ENABLED\"\n\n               \"name\":                     \"MyV2Fan\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"GarageDoorOpener\",\n               \"displayName\":              \"MyGarageDoorOpener\",     // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentDoorState\":         \"OPEN\",                   // 0 - \"OPEN\"\n                                                                     // 1 - \"CLOSED\"\n                                                                     // 2 - \"OPENING\"\n                                                                     // 3 - \"CLOSING\"\n                                                                     // 4 - \"STOPPED\"\n\n               \"targetDoorState\":          \"OPEN\",                   // 0 - \"OPEN\"\n                                                                     // 1 - \"CLOSED\"\n\n               \"obstructionDetected\":      \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"lockCurrentState\":         \"UNSECURED\",              // 0 - \"UNSECURED\"\n                                                                     // 1 - \"SECURED\"\n                                                                     // 2 - \"JAMMED\"\n                                                                     // 3 - \"UNKNOWN\"\n\n               \"lockTargetState\":          \"UNSECURED\",              // 0 - \"UNSECURED\"\n                                                                     // 1 - \"SECURED\"\n\n               \"name\":                     \"MyGarageDoorOpener\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n               // Define the characteristic, its Interval and Timeout\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               // \"polling\": [\n               //    {\"characteristic\": \"currentDoorState\",     \"interval\": 540, \"timeout\": 8000},\n               //    {\"characteristic\": \"obstructionDetected\",  \"interval\": 540, \"timeout\": 8000},\n               //    {\"characteristic\": \"lockCurrentState\",     \"interval\": 540, \"timeout\": 8000}\n               // ],\n               \"stateChangeResponseTime\":   10,                      // Default (Seconds)\n\n               // This is just a dumb example of a prefix\n               \"state_cmd_prefix\":         \"node\"\n\n               //\"state_cmd\":                \".homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Lightbulb\",\n               \"displayName\":              \"MyOnOffLight\",           // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"on\":                       \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               // Not Defining brightness determines that it is an On/Off Light\n               // \"Brightness\":\n               // \"Hue\":\n               // \"Saturation\":\n\n               \"name\":                     \"MyOnOffLight\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // \"ColorTemperature\":\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Lightbulb\",\n               \"displayName\":              \"MyDimmableLight\",       // Not a characteristic, but a function parameter\n\n               // Required\n               \"on\":                       \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               // Defining brightness determines that it is dimmmable\n               \"brightness\":                8,                       // Range: 0-100, Step: 1\n\n               \"hue\":                       8,                       // Range: 0-360, Step: 1\n\n               \"saturation\":                8,                       // Range: 0-100, Step: 1\n\n               \"colorTemperature\":          8,                       // Range: 140-500, Step: 1\n\n               \"name\":                     \"MyDimmableLight\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"LockManagement\",\n               \"displayName\":              \"MyLockManagement\",       // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n\n               // All TLV8 Characteristics are removed by default,\n               // unless 'allowTLV8' is set, at your own peril.\n               // Setting most will cause Homebridge with HomeKit or Eve.\n               // to not allow you to connect.\n               // \"lockControlPoint\":          0,                    // Format TLV8\n\n               \"version\":                  \"1.2.3\",                  // Format: String\n\n\n               // Optional Characteristics\n\n               // All TLV8 Characteristics are removed by default,\n               // unless 'allowTLV8' is set, at your own peril.\n               // Setting most will cause Homebridge with HomeKit or Eve.\n               // to not allow you to connect.\n               // \"logs\":                   0,                       // Format: TLV8\n\n               \"audioFeedback\":            \"FALSE\",\n                                                                     // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"lockManagementAutoSecurityTimeout\":\n                                            20,                      // Format: UINT32\n                                                                     // \"Units\": Seconds\n\n               \"administratorOnlyAccess\":  \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"lockLastKnownAction\":      \"SECURED_PHYSICALLY_INTERIOR\",\n                                                                     // 0 - \"SECURED_PHYSICALLY_INTERIOR\"\n                                                                     // 1 - \"UNSECURED_PHYSICALLY_INTERIOR\"\n                                                                     // 2 - \"SECURED_PHYSICALLY_EXTERIOR\"\n                                                                     // 3 - \"UNSECURED_PHYSICALLY_EXTERIOR\"\n                                                                     // 4 - \"SECURED_BY_KEYPAD\"\n                                                                     // 5 - \"UNSECURED_BY_KEYPAD\"\n                                                                     // 6 - \"SECURED_REMOTELY\"\n                                                                     // 7 - \"UNSECURED_REMOTELY\"\n                                                                     // 8 - \"SECURED_BY_AUTO_SECURE_TIMEOUT\"\n\n               \"currentDoorState\":         \"OPEN\",                   // 0 - \"OPEN\"\n                                                                     // 1 - \"CLOSED\"\n                                                                     // 2 - \"OPENING\"\n                                                                     // 3 - \"CLOSING\"\n                                                                     // 4 - \"STOPPED\"\n\n               \"motionDetected\":           \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"name\":                     \"MyLockManagement\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"LockMechanism\",\n               \"displayName\":              \"MyLockMechanism\",        // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"lockCurrentState\":         \"UNSECURED\",              // 0 - \"UNSECURED\"\n                                                                     // 1 - \"SECURED\"\n                                                                     // 2 - \"JAMMED\"\n                                                                     // 3 - \"UNKNOWN\"\n\n               \"lockTargetState\":          \"UNSECURED\",              // 0 - \"UNSECURED\"\n                                                                     // 1 - \"SECURED\"\n\n               \"name\":                     \"MyLockMechanism\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Outlet\",\n               \"displayName\":              \"MyOutlet\",               // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"on\":                       \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"outletInUse\":              \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"name\":                     \"MyOutlet\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Switch\",\n               \"displayName\":              \"MySwitch\",               // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"on\":                       \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"name\":                     \"MySwitch\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Thermostat\",\n               \"displayName\":              \"MyThermostat\",           // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentHeatingCoolingState\":\n                                           \"OFF\",                    // 0 - \"OFF\"\n                                                                     // 1 - \"HEAT\"\n                                                                     // 2 - \"COOL\"\n\n               \"targetHeatingCoolingState\":\n                                           \"OFF\",                    // 0 - \"OFF\"\n                                                                     // 1 - \"HEAT\"\n                                                                     // 2 - \"COOL\"\n                                                                     // 3 - \"AUTO\"\n\n               \"currentTemperature\":        22.2,                    // Range: 0-100, Step: 0.1\n                                                                     // \"Units\": CELCIUS\n\n               \"targetTemperature\":         22.2,                    // Range: 10-38, Step: 0.1\n                                                                     // \"Units\": CELCIUS\n\n               \"temperatureDisplayUnits\":  \"CELSIUS\",                // 0 - \"CELSIUS\"\n                                                                     // 1 - \"FAHRENHEIT\"\n\n               // Optional Characteristics\n               \"currentRelativeHumidity\":   60,                      // Range: 0-100, Step: 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               \"targetRelativeHumidity\":    60,                      // Range: 0-100, Step: 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               \"coolingThresholdTemperature\":\n                                            22.2,                    // Range 10-35, Step: 0.1\n                                                                     // Units: CELCIUS\n\n               \"heatingThresholdTemperature\":\n                                            25.2,                    // Range 0-25, Step: 0.1\n                                                                     // Units: CELCIUS\n\n               \"name\":                     \"MyThermostat\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // - Notice Two characteristics being polled !!!\n               //   at different intervals.\n               // - Also Required as fakegato option below uses them.\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"currentHeatingCoolingState\", \"interval\": 540,  \"timeout\": 8000},\n               //   {\"characteristic\": \"currentTemperature\",         \"interval\": 60,   \"timeout\": 8000},\n               //   {\"characteristic\": \"targetTemperature\",          \"interval\": 60,   \"timeout\": 8000}\n               //],\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   10                       // (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\",\n\n               // Cmd4 fakegato lets you specify what type of logging and\n               // the characteristics to be logged.\n               // i.e. thermo and tracking currentTemperature and\n               //      targetTemperature.\n               // See https://github.com/simont77/fakegato-history\n               // for full description of fields.\n               // You must also define them for polling, or the value would never change.\n               // fakegato requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"fakegato\": {\"eve\":           \"thermo\",\n               //             \"currentTemp\":   \"CurrentTemperature\",\n               //             \"setTemp\":       \"TargetTemperature\",\n               //             \"valvePosition\":  0,\n               //             \"storage\":       \"fs\",\n               //             \"storagePath\":   \".homebridge/FakegatoStorage\",\n               //             \"folder\":        \"folderName\",\n               //             \"keyPath\":       \"/place/to/store/my/keys/\"\n               //            }\n\n            },\n            {\n               \"type\":                     \"AirQualitySensor\",\n               \"displayName\":              \"MyAirQualitySensor\",     // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"airQuality\":               \"EXCELLENT\",              // 0 - \"UNKNOWN\"\n                                                                     // 1 - \"EXCELLENT\"\n                                                                     // 2 - \"GOOD\"\n                                                                     // 3 - \"FAIR\"\n                                                                     // 4 - \"INFERIOR\"\n                                                                     // 5 - \"POOR\"\n\n               \"ozoneDensity\":              50,                      // Range 0-1000, Step 1\n\n               \"nitrogenDioxideDensity\":    50,                      // Range 0-1000, Step 1\n\n               \"sulphurDioxideDensity\":     50,                      // Range 0-1000, Step 1\n\n               \"pm2_5Density\":              50,                      // Range 0-1000, Step 1\n\n               // Optional Characteristics\n               \"pm10Density\":               50,                      // Range 0-1000, Step 1\n\n               \"vocDensity\":                50,                      // Range 0-1000, Step 1\n\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyAirQualitySensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"SecuritySystem\",\n               \"displayName\":              \"MySecuritySystem\",       // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"securitySystemCurrentState\":\n                                           \"DISARMED\",               // 0 - \"STAY_ARM\"\n                                                                     // 1 - \"AWAY_ARM\"\n                                                                     // 2 - \"NIGHT_ARM\"\n                                                                     // 3 - \"DISARMED\"\n                                                                     // 4 - \"ALARM_TRIGGERED\"\n\n               \"securitySystemTargetState\":\n                                           \"DISARM\",                 // 0 - \"STAY_ARM\"\n                                                                     // 1 - \"AWAY_ARM\"\n                                                                     // 2 - \"NIGHT_ARM\"\n                                                                     // 3 - \"DISARM\"\n\n               // Optional Characteristics\n               \"securitySystemAlarmType\":   0,                       // Range: 0-1, Step 1\n                                                                     // Meaning Unknown\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"name\":                     \"MySecuritySystem\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"CarbonMonoxideSensor\",\n               \"displayName\":              \"MyCOSensor\",             // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"carbonMonoxideDetected\":   \"CO_LEVELS_NORMAL\",       // 0 - \"CO_LEVELS_NORMAL\"\n                                                                     // 1 - \"CO_LEVELS_ABNORMAL\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"carbonMonoxideLevel\":       0,                       // Range: 0-100,\n                                                                     // Format: float\n\n               \"carbonMonoxidePeakLevel\":   0,                       // Range: 0-100,\n                                                                     // Format: float\n\n               \"name\":                     \"MyCOSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"ContactSensor\",\n               \"displayName\":              \"MyContactSensor\",        // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"contactSensorState\":       \"CONTACT_DETECTED\",       // 0 - \"CONTACT_DETECTED\"\n                                                                     // 1 - \"CONTACT_NOT_DETECTED\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyContactSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Door\",\n               \"displayName\":              \"MyDoor\",                 // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentPosition\":           0,                       // Range: 0 - 100, Step 1\n\n               \"targetPosition\":            0,                       // Range: 0 - 100, Step 1\n\n               \"positionState\":            \"STOPPED\",                // 0 - \"DECREASING\"\n                                                                     // 1 - \"INCREASING\"\n                                                                     // 2 - \"STOPPED\"\n\n               // Optional Characteristics\n               \"holdPosition\":             \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"obstructionDetected\":      \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"name\":                     \"MyDoor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n               // Required as fakegato option below uses them.\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"currentPosition\",     \"interval\": 80, \"timeout\": 8000},\n               //   {\"characteristic\": \"obstructionDetected\", \"interval\": 50, \"timeout\": 8000}\n               //],\n\n               // Cmd4 fakegato lets you specify what type of logging and\n               // the characteristics to be logged.\n               // i.e. door and tracking statusActive\n               // You must also define them for polling, or the value would never change.\n               // fakegato requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"fakegato\": {\"eve\":         \"door\",\n               //             \"status\":      \"currentPosition\",\n               //             \"storage\":     \"fs\",\n               //             \"storagePath\": \".homebridge/FakegatoStorage\",\n               //             \"folder\":      \"folderName\",\n               //             \"keyPath\":     \"/place/to/store/my/keys/\"\n               //            },\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"HumiditySensor\",\n\n               \"displayName\":              \"MyHumiditySensor\",       // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentRelativeHumidity\":   1,                       // Range: 0-100, Step: 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyHumiditySensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\",\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n               // Required as fakegato option below uses them.\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"currentRelativeHumidity\", \"interval\": 50, \"timeout\": 8000}\n               //],\n\n               // Cmd4 fakegato lets you specify what type of logging and\n               // the characteristics to be logged.\n               // i.e. thermo and tracking currentTemperature and\n               //      targetTemperature.\n               // You must also define them for polling, or the value would never change.\n               // fakegato requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"fakegato\": {\"eve\":         \"room\",\n               //             \"temp\":        0,\n               //             \"humidity\":    \"currentRelativeHumidity\",\n               //             \"ppm\":          0,\n               //             \"storage\":     \"fs\",\n               //             \"storagePath\": \".homebridge/FakegatoStorage\",\n               //             \"folder\":      \"folderName\",\n               //             \"keyPath\":     \"/place/to/store/my/keys/\"\n               //            }\n            },\n            {\n               \"type\":                     \"LeakSensor\",\n               \"displayName\":              \"MyLeakSensor\",           // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"leakDetected\":             \"LEAK_NOT_DETECTED\",      // 0 - \"LEAK_NOT_DETECTED\"\n                                                                     // 1 - \"LEAK_DETECTED\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyLeakSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"LightSensor\",\n               \"displayName\":              \"MyLightSensor\",          // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentAmbientLightLevel\":  1,                       // Range: 0.0001-100000\n                                                                     // Format: float\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyLightSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"MotionSensor\",\n               \"displayName\":              \"MyMotionSensor\",         // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"motionDetected\":           \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyMotionSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"OccupancySensor\",\n               \"displayName\":              \"MyOccupancySensor\",      // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"occupancyDetected\":        \"OCCUPANCY_NOT_DETECTED\", // 0 - \"OCCUPANCY_NOT_DETECTED\"\n                                                                     // 1 - \"OCCUPANCY_DETECTED\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyOccupancySensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"SmokeSensor\",\n               \"displayName\":              \"MySmokeSensor\",          // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"smokeDetected\":            \"SMOKE_NOT_DETECTED\",     // 0 - \"SMOKE_NOT_DETECTED\"\n                                                                     // 1 - \"SMOKE_DETECTED\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MySmokeSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"StatefulProgrammableSwitch\",\n               \"displayName\":              \"MyStatefulProgrammableSwitch\",\n                                                                     // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"programmableSwitchEvent\":  \"SINGLE_PRESS\",           // 0 - \"SINGLE_PRESS\"\n                                                                     // 1 - \"DOUBLE_PRESS\"\n                                                                     // 2 - \"LONG_PRESS\"\n\n               \"programmableSwitchOutputState\":\n                                            0,                       // Range: 0-1, Step 1\n                                                                     // \"Meaning\": ???\n\n               // Optional Characteristics\n               \"name\":                     \"MyStatefulProgrammableSwitch\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"StatelessProgrammableSwitch\",\n               \"displayName\":              \"MyStatelessProgrammableSwitch\",\n                                                                     // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"programmableSwitchEvent\":  \"SINGLE_PRESS\",\n                                                                     // 0 - \"SINGLE_PRESS\"\n                                                                     // 1 - \"DOUBLE_PRESS\"\n                                                                     // 2 - \"LONG_PRESS\"\n\n               // Optional Characteristics\n               \"name\":                     \"MyStatelessProgrammableSwitch\",\n\n               \"serviceLabelIndex\":         1,                       // Range: 1-255, Step: 1\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"TemperatureSensor\",\n               \"displayName\":              \"MyTemperatureSensor\",\n                                                                     // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentTemperature\":        22.2,                    // Range: 0-100, Step: 0.1\n                                                                     // Format: float\n                                                                     // \"Units\": CELCIUS\n\n               // This characteristic is not available on a temperature sensor\n               // but configurable in homebridge-cmd4. How Homekit behaves is\n               // undeterministic. Eve however is more flexible.\n               \"currentRelativeHumidity\":   20,                      // Range: 0-100, Step: 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"name\":                     \"MyTemperatureSensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n               // Required as fakegato option below uses them.\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\":\n               //[\n               //   {\"characteristic\": \"currentTemperature\",       \"interval\": 50, \"timeout\": 8000},\n               //   {\"characteristic\": \"currentRelativeHumidity\",  \"interval\": 40, \"timeout\": 8000}\n               //],\n\n               // Cmd4 Specific (Fakegate )\n               // You must also define them for polling, or the value would never change.\n               // fakegato requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"fakegato\": {\"eve\":         \"room\",\n               //             \"temp\":        \"currentTemperature\",\n               //             \"humidity\":    \"currentRelativeHumidity\",\n               //             \"storage\":     \"fs\",\n               //             \"storagePath\": \".homebridge/FakegatoStorage\",\n               //             \"folder\":      \"folderName\",\n               //             \"keyPath\":     \"/place/to/store/my/keys/\"\n               //            },\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Window\",\n               \"displayName\":              \"MyWindow\",               // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentPosition\":           0,                       // Range: 0 - 100, Step 1\n\n               \"targetPosition\":            0,                       // Range: 0 - 100, Step 1\n\n               \"positionState\":            \"STOPPED\",                // 0 - \"DECREASING\"\n                                                                     // 1 - \"INCREASING\"\n                                                                     // 2 - \"STOPPED\"\n\n               // Optional Characteristics\n               \"holdPosition\":             \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"obstructionDetected\":      \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"name\":                     \"MyWindow\",\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"WindowCovering\",\n               \"displayName\":              \"MyWindowCovering\",       // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"currentPosition\":           0,                       // Range: 0 - 100, Step 1\n\n               \"targetPosition\":            0,                       // Range: 0 - 100, Step 1\n\n               \"positionState\":            \"STOPPED\",                // 0 - \"DECREASING\"\n                                                                     // 1 - \"INCREASING\"\n                                                                     // 2 - \"STOPPED\"\n\n               // Optional Characteristics\n               \"holdPosition\":             \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"currentHorizontalTiltAngle\":0,                       // Range: -90 to 90, Step 1\n                                                                     // \"Units\": ARC_DEGREE\n\n               \"targetHorizontalTiltAngle\": 0,                       // Range: -90 to 90, Step 1\n                                                                     // \"Units\": ARC_DEGREE\n\n               \"currentVerticalTiltAngle\":  0,                       // Range: -90 to 90, Step 1\n                                                                     // \"Units\": ARC_DEGREE\n\n               \"targetVerticalTiltAngle\":   0,                       // Range: -90 to 90, Step 1\n                                                                     // \"Units\": ARC_DEGREE\n\n               \"obstructionDetected\":      \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"name\":                     \"MyWindowCovering\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Battery\",                // Was BatteryService\n               \"displayName\":              \"MyBattery\",              // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"batteryLevel\":              50,                      // Range: 0 - 100, Step 1\n\n               \"chargingState\":            \"NOT_CHARGING\",           // 0 - \"NOT_CHARGING\"\n                                                                     // 1 - \"CHARGING\"\n                                                                     // 2 - \"NOT_CHARGEABLE\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               // Optional Characteristics\n               \"name\":                     \"MyBatteryService\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"CarbonDioxideSensor\",\n               \"displayName\":              \"MyCO2Sensor\",\n\n               // Required Characteristics\n               \"carbonDioxideDetected\":    \"CO2_LEVELS_NORMAL\",      // 0 - \"CO2_LEVELS_NORMAL\"\n                                                                     // 1 - \"CO2_LEVELS_ABNORMAL\"\n\n               // Optional Characteristics\n               \"statusActive\":             \"TRUE\",                   // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"statusTampered\":           \"NOT_TAMPERED\",           // 0 - \"NOT_TAMPERED\"\n                                                                     // 1 - \"TAMPERED\"\n\n               \"statusLowBattery\":         \"BATTERY_LEVEL_NORMAL\",   // 0 - \"BATTERY_LEVEL_NORMAL\"\n                                                                     // 1 - \"BATTERY_LEVEL_LOW\"\n\n               \"carbonDioxideLevel\":        0,                       // Range: 0-100000\n                                                                     // \"Format\": float\n\n               \"carbonDioxidePeakLevel\":    0,                       // Range: 0-100000\n                                                                     // \"Format\": float\n\n               \"name\":                     \"MyCO2Sensor\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\":                 false,                   // Default is false.\n\n               \"interval\":                  540,                     // Interval is in seconds.\n                                                                     // Default is 10\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n               // Not Possible in this implementation\n               // {\n               //    \"type\": \"CameraRTPStreamManagement\",\n               //    \"name\": \"MyCameraRTPStreamManagement\",\n               //\n               //    // Cmd4 Specific\n               //    \"stateChangeResponseTime\": 1,                      // Default (Seconds)\n               //    \"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n               // },\n            {\n               \"type\":                     \"Microphone\",\n               \"displayName\":              \"MyMicrophone\",           // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"mute\":                     \"FALSE\",                  // 0 - \"FALSE\" (Off)\n                                                                     // 1 - \"TRUE\" (On)\n\n               // Optional Characteristics\n               \"volume\":                    5,                       // Range: 0-100, Step 1\n\n               \"name\":                     \"MyMicrophone\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               // \"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Speaker\",\n               \"displayName\":              \"MySpeaker\",\n\n               // Required Characteristics\n               \"mute\":                     \"FALSE\",                  // 0 - \"FALSE\" (Off)\n                                                                     // 1 - \"TRUE\" (On)\n\n               // Optional Characteristics\n               \"volume\":                    5,                       // Range: 0-100, Step 1\n\n               \"name\":                     \"MySpeaker\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"DoorBell\",\n               \"displayName\":              \"MyDoorBell\",             // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"programmableSwitchEvent\":  \"SINGLE_PRESS\",           // 0 - \"SINGLE_PRESS\"\n                                                                     // 1 - \"DOUBLE_PRESS\"\n                                                                     // 2 - \"LONG_PRESS\"\n\n               // Optional Characteristics\n               \"brightness\":                8,                       // Range: 0-100, Step: 1\n\n               \"volume\":                    5,                       // Range: 0-100, Step 1\n\n               \"name\":                     \"MyDoorBell\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Slats\",\n               \"displayName\":              \"MySlats\",                // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"slatType\":                 \"HORIZONTAL\",             // 0 - \"HORIZONTAL\"\n                                                                     // 1 - VERTICAL\"\n\n               \"currentSlatState\":         \"FIXED\",                  // 0 - \"FIXED\"\n                                                                     // 1 - \"JAMMED\"\n                                                                     // 2 - \"SWINGING\"\n\n               // Optional Characteristics\n               \"name\":                     \"MySlat\",\n\n               \"currentTiltAngle\":          0,                       // Range: -90 to 90, Step 1\n                                                                     // \"Units\": ARC_DEGREE\n\n               \"targetTiltAngle\":           0,                       // Range: -90 to 90, Step 1\n                                                                     // \"Units\": ARC_DEGREE\n\n               \"swingMode\":                \"SWING_ENABLED\",          // 0 - \"SWING_DISABLED\"\n                                                                     // 1 - \"SWING_ENABLED\"\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\":                 false,                   // Default is false.\n               \"interval\":                  540,                     // Interval is in seconds. Default is 10\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                    \"FilterMaintenance\",\n               \"displayName\":             \"MyFilterMaintenance\",     // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"filterChangeIndication\":   \"FILTER_OK\",\n                                                                     // 0 - \"FILTER_OK\"\n                                                                     // 1 - \"CHANGE_FILTER\"\n\n\n               // Optional Characteristics\n               \"filterLifeLevel\":           50,                      // Range: 0-100\n                                                                     // \"Format\": float\n               \"resetFilterIndication\":     1,                       // Range: 1 - ???\n\n               \"name\":                     \"MyFilterMaintenance\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"AirPurifier\",\n               \"displayName\":              \"MyAirPurifier\",          // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               \"currentAirPurifierState\":  \"INACTIVE\",               // 0 - \"INACTIVE\"\n                                                                     // 1 - \"IDLE\"\n                                                                     // 2 - \"PURIFYING_AIR\"\n\n               \"targetAirPurifierState\":   \"MANUAL\",                 // 0 - \"MANUAL\"\n                                                                     // 1 - \"AUTO\"\n\n\n               // Optional Characteristics\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",  // 0 - \"CONTROL_LOCK_DISABLED\"\n                                                                     // 1 - \"CONTROL_LOCK_ENABLED\"\n\n               \"name\":                     \"MyAirPurifier\",\n\n               \"swingMode\":                \"SWING_DISABLED\",\n                                                                     // 0 - \"SWING_DISABLED\"\n                                                                     // 1 - \"SWING_ENABLED\"\n\n               \"rotationSpeed\":             0,                       // Range: 0 - 100, Step 1\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"ServiceLabel\",\n               \"displayName\":              \"MyServiceLabel\",         // Not a characteristic, but a function parameter\n\n               // Required Characteristics\n               \"serviceLabelNamespace\":    \"DOTS\",                   // 0 - \"DOTS\"\n                                                                     // 1 - \"ARABIC_NUMERALS\"\n\n               // Optional Characteristics\n               \"name\":                     \"MyServiceLabel\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                      \"Television\",\n               \"displayName\":               \"Tv_Combo\",              // Not a characteristic, but a function parameter\n\n               // Televisions should be published externally to get the icon\n               \"publishExternally\":          true,\n               \"category\":                  \"TELEVISION\",            // The hint to Homekit of which icon to use.\n\n               // Required characteristics\n               \"active\":                    \"ACTIVE\",                // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               \"activeIdentifier\":           1,                      // This is which inputSource is active\n                                                                     // We gave HDMI2 the identifier of 1.\n                                                                     // Format: UINT32\n\n               \"configuredName\":            \"TV_Combo\",\n\n               \"sleepDiscoveryMode\":        \"ALWAYS_DISCOVERABLE\",   // 0 - \"NOT_DISCOVERABLE\"\n                                                                     // 1 - \"ALWAYS_DISCOVERABLE\"\n\n               \"linkedTypes\":\n               [\n                  {\n                     \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI1\",              // Not a characteristic, but a function parameter\n\n                     // Required Characteristics\n                     \"configuredName\":         \"HDMI1\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n\n                     // Optional Characteristics\n                     \"identifier\":              1,                   // Selector for activeIdentifier\n                                                                     // Format: UINT32\n\n                     //\"InputDeviceType\":     \"TUNER\",               // 0 - \"OTHER\"\n                                                                     // 1 - \"TV\"\n                                                                     // 2 - \"RECORDING\"\n                                                                     // 3 - \"TUNER\"\n                                                                     // 4 - \"PLAYBACK\"\n                                                                     // 5 - \"AUDIO_SYSTEM\"\n                                                                     // 6 - \"UNKNOWN_6\" (Added in IOS 14)\n \n                     \"targetVisibilityState\":  \"SHOWN\",              // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n                                                                     // 2 - \"STOP\"\n\n                     \"name\":                   \"HDMI1\",\n\n                     \"manufacturer\":           \"Somebody\",           // Available for all accessories\n\n                     \"model\":                  \"Anything\",           // Available for all accessories\n\n                     \"serialNumber\":           \"12345\"               // Available for all accessories\n\n                 },\n                 {   \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI2\",              // Not a characteristic, but a function parameter\n\n                     // Required Characteristics\n                     \"configuredName\":         \"HDMI2\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n\n                     // Optional Characteristics\n                     \"identifier\":             2,                    // Selector for activeIdentifier\n                                                                     // Format: UINT32\n\n                     //\"inputDeviceType\":                            // \"TUNER\",\n                                                                     // 0 - \"OTHER\"\n                                                                     // 1 - \"TV\"\n                                                                     // 2 - \"RECORDING\"\n                                                                     // 3 - \"TUNER\"\n                                                                     // 4 - \"PLAYBACK\"\n                                                                     // 5 - \"AUDIO_SYSTEM\"\n\n                     \"targetVisibilityState\":  \"SHOWN\",              // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n                                                                     // 2 - \"STOP\"\n\n                     \"name\":                   \"HDMI2\",\n\n                     \"manufacturer\":           \"Somebody\",           // Available for all accessories\n\n                     \"model\":                  \"Anything\",           // Available for all accessories\n\n                     \"serialNumber\":           \"12345\"               // Available for all accessories\n\n                  },\n                  {  \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI3\",              // Not a characteristic, but a function parameter\n\n                     // Required Characteristics\n                     \"configuredName\":         \"HDMI3\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n\n                     // Optional Characteristics\n                     \"identifier\":              3,                   // Selector for activeIdentifier\n                                                                     // Format: UINT32\n\n                     //\"InputDeviceType\":                            // \"TUNER\",\n                                                                     // 0 - \"OTHER\"\n                                                                     // 1 - \"TV\"\n                                                                     // 2 - \"RECORDING\"\n                                                                     // 3 - \"TUNER\"\n                                                                     // 4 - \"PLAYBACK\"\n                                                                     // 5 - \"AUDIO_SYSTEM\"\n\n                     \"targetVisibilityState\":  \"SHOWN\",              // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n                                                                     // 2 - \"STOP\"\n\n                     \"name\":                   \"HDMI3\",\n\n                     \"manufacturer\":           \"Somebody\",           // Available for all accessories\n\n                     \"model\":                  \"Anything\",           // Available for all accessories\n\n                     \"serialNumber\":           \"12345\"               // Available for all accessories\n\n                  },\n                  {  \"type\":                   \"InputSource\",\n                     \"displayName\":            \"HDMI4\",              // Not a characteristic, but a function parameter\n\n                     // Required Characteristics\n                     \"configuredName\":         \"HDMI4\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"HDMI\",\n                     \"isConfigured\":           \"CONFIGURED\",\n\n                     // Optional Characteristics\n                     \"identifier\":              4,                   // Selector for activeIdentifier\n                                                                     // Format: UINT32\n\n                     //\"inputDeviceType\":      \"TUNER\",              // 0 - \"OTHER\"\n                                                                     // 1 - \"TV\"\n                                                                     // 2 - \"RECORDING\"\n                                                                     // 3 - \"TUNER\"\n                                                                     // 4 - \"PLAYBACK\"\n                                                                     // 5 - \"AUDIO_SYSTEM\"\n\n                     \"targetVisibilityState\":  \"SHOWN\",              // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n                                                                     // 2 - \"STOP\"\n\n                     \"name\":                   \"HDMI4\",\n\n                     \"manufacturer\":           \"Somebody\",           // Available for all accessories\n\n                     \"model\":                  \"Anything\",           // Available for all accessories\n\n                     \"serialNumber\":           \"12345\"               // Available for all accessories\n\n                  },\n                  {  \"type\":                   \"InputSource\",\n                     \"displayName\":            \"Netflix\",            // Not a characteristic, but a function parameter\n\n                     // Required Characteristics\n                     \"configuredName\":         \"Netflix\",\n                     \"currentVisibilityState\": \"SHOWN\",\n                     \"inputSourceType\":        \"APPLICATION\",\n                     \"isConfigured\":           \"CONFIGURED\",\n\n                     // Optional Characteristics\n                     \"identifier\":              5,                   // Selector for activeIdentifier\n                                                                     // Format: UINT32\n\n                     // \"inputDeviceType\":    \"OTHER\",               // 0 - \"OTHER\"\n                                                                     // 1 - \"TV\"\n                                                                     // 2 - \"RECORDING\"\n                                                                     // 3 - \"TUNER\"\n                                                                     // 4 - \"PLAYBACK\"\n                                                                     // 5 - \"AUDIO_SYSTEM\"\n\n                     \"targetVisibilityState\":  \"SHOWN\",              // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n                                                                     // 2 - \"STOP\"\n\n                     \"name\":                   \"Netflix\",\n\n                     \"manufacturer\":           \"Somebody\",           // Available for all accessories\n\n                     \"model\":                  \"Anything\",           // Available for all accessories\n\n                     \"serialNumber\":           \"12345\"               // Available for all accessories\n                  },\n                  {  \"type\":                   \"TelevisionSpeaker\",\n                     \"displayName\":            \"TVSpeaker\",          // Not a characteristic, but a function parameter\n\n                     // Required Characteristics\n                     \"mute\":                   \"FALSE\",\n\n                     // Optional Characteristics\n                     \"active\":                 \"ACTIVE\",             // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n\n                     \"volume\":                 10,                   // Range: 0-100, Step 1\n\n                     \"volumeControlType\":      \"ABSOLUTE\",           // 0 - \"NONE\"\n                                                                     // 1 - \"RELATIVE\"\n                                                                     // 2 - \"RELATIVE_WITH_CURRENT\"\n                                                                     // 3 - \"ABSOLUTE\"\n\n                     \"volumeSelector\":         \"INCREMENT\",          // 0 - \"INCREMENT\"\n                                                                     // 1 - \"DECREMENT\"\n\n                     \"name\":                   \"TVSpeaker\",\n\n                     \"manufacturer\":           \"Somebody\",           // Available for all accessories\n\n                     \"model\":                  \"Anything\",           // Available for all accessories\n\n                     \"serialNumber\":           \"12345\"               // Available for all accessories\n\n\n                  }\n               ],\n\n               // Optional Characteristics\n               \"brightness\":                8,                       // Range: 0-100, Step: 1\n\n               \"closedCaptions\":           \"DISABLED\",\n                                                                     // 0 - \"DISABLED,\n                                                                     // 1 - \"ENABLED\n\n               // All TLV8 Characteristics are removed by default,\n               // unless 'allowTLV8' is set, at your own peril.\n               // Setting most will cause Homebridge with HomeKit or Eve.\n               // to not allow you to connect.\n               // \"DisplayOrder\":              0,  //  Format: TLV8\n\n               \"currentMediaState\":        \"STOP\",                   // 0 - \"PLAY\"\n                                                                     // 1 - \"PAUSE\"\n                                                                     // 2 - \"STOP\"\n                                                                     // 3 -  ???\n\n               \"targetMediaState\":         \"STOP\",                   // 0 - \"PLAY\"\n                                                                     // 1 - \"PAUSE\"\n                                                                     // 2 - \"STOP\"\n                                                                     // 3 -  ???\n\n               \"pictureMode\":              \"STANDARD\",               // 0 - \"OTHER\"\n                                                                     // 1 - \"STANDARD\"\n                                                                     // 2 - \"CALIBRATED\"\n                                                                     // 3 - \"CALIBRATED_DARK\"\n                                                                     // 4 - \"VIVID\"\n                                                                     // 5 - \"GAME\"\n                                                                     // 6 - \"COMPUTER\"\n                                                                     // 7 - \"CUSTOM\"\n\n               \"remoteKey\":                \"SELECT\",                 // 0 - \"REWIND,\"\n                                                                     // 1 - \"FAST_FORWARD\"\n                                                                     // 2 - \"NEXT_TRACK\"\n                                                                     // 3 - \"PREVIOUS_TRACK\"\n                                                                     // 4 - \"ARROW_UP\"\n                                                                     // 5 - \"ARROW_DOWN\"\n                                                                     // 6 - \"ARROW_LEFT\"\n                                                                     // 7 - \"ARROW_RIGHT\"\n                                                                     // 8 - \"SELECT\"\n                                                                     // 9 - \"BACK\"\n                                                                     // 10 - \"EXIT\"\n                                                                     // 11 - \"PLAY_PAUSE\"\n                                                                     // 12 - \"INFORMATION\"\n\n               // Optional Characteristics\n               \"manufacturer\":             \"Sony\",\n\n               \"model\":                    \"Android TV\",\n\n               \"serialNumber\":             \"12345\",\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"active\",                \"interval\": 50,  \"timeout\": 5000},\n               //   {\"characteristic\": \"activeIdentifier\",      \"interval\": 50,  \"timeout\": 5000},\n               //   {\"characteristic\": \"currentMediaState\",     \"interval\": 540, \"timeout\": 5000}\n               //],\n\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\": \"TelevisionSpeaker\",\n               \"displayName\": \"MyTVSpeaker\",                        // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"mute\":                     \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               // Optional Characteristics\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               \"volume\":                    5,                       // Range: 0-100, Step 1\n\n               \"volumeControlType\":        \"ABSOLUTE\",               // 0 - \"NONE\"\n                                                                     // 1 - \"RELATIVE\"\n                                                                     // 2 - \"RELATIVE_WITH_CURRENT\"\n                                                                     // 3 - \"ABSOLUTE\"\n\n               \"volumeSelector\":           \"INCREMENT\",              // 0 - \"INCREMENT\"\n                                                                     // 1 - \"DECREMENT\"\n\n               \"name\":                     \"MyTVSpeaker\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"active\",               \"interval\": 50, \"timeout\": 5000},\n               //   {\"characteristic\": \"volume\",               \"interval\": 50, \"timeout\": 5000}\n               //],\n\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"InputSource\",\n               \"displayName\":              \"MyInputSource\",          // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"configuredName\":           \"MyInputSource\",\n\n               \"inputSourceType\":          \"HDMI\",                   // 0 - \"OTHER\"\n                                                                     // 1 - \"HOME_SCREEN\"\n                                                                     // 2 - \"TUNER\"\n                                                                     // 3 - \"HDMI\"\n                                                                     // 4 - \"COMPOSITE_VIDEO\"\n                                                                     // 5 - \"S_VIDEO\"\n                                                                     // 6 - \"COMPONENT_VIDEO\"\n                                                                     // 7 - \"DVI\"\n                                                                     // 8 - \"AIRPLAY\"\n                                                                     // 9 - \"USB\"\n                                                                     // 10 - \"APPLICATION\"\n\n               \"isConfigured\":            \"CONFIGURED\",              // 0 - \"NOT_CONFIGURED\"\n                                                                     // 1 - \"CONFIGURED\"\n\n               \"currentVisibilityState\":  \"SHOWN\",                   // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n\n               // Optional Characteristics\n               \"inputDeviceType\":          \"TV\",                     // 0 - \"OTHER\"\n                                                                     // 1 - \"TV\"\n                                                                     // 2 - \"RECORDING\"\n                                                                     // 3 - \"TUNER\"\n                                                                     // 4 - \"PLAYBACK\"\n                                                                     // 5 - \"AUDIO_SYSTEM\"\n\n               \"targetVisibilityState\":    \"SHOWN\",\n                                                                     // 0 - \"SHOWN\"\n                                                                     // 1 - \"HIDDEN\"\n                                                                     // 2 - \"STOP\"\n\n               \"name\":                     \"MyInputSource\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"IrrigationSystem\",\n               \"displayName\":              \"MyIrrigationSystem\",     // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               \"programMode\":              \"PROGRAM_SCHEDULED\",      // 0 - \"NO_PROGRAM_SCHEDULED\"\n                                                                     // 1 - \"PROGRAM_SCHEDULED\"\n                                                                     // 2 - \"PROGRAM_SCHEDULED_MANUAL_MODE\"\n\n               \"inUse\":                    \"IN_USE\",                 // 0 - \"NOT_IN_USE\"\n                                                                     // 1 - \"IN_USE\"\n\n\n               // Optional Characteristics\n               \"remainingDuration\":         60,                      // Range: 0-3600, Step: 1\n\n               \"statusFault\":              \"NO_FAULT\",\n                                                                     // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"name\":                     \"MyIrrigationSystem\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"active\",               \"interval\": 50,  \"timeout\": 5000},\n               //   {\"characteristic\": \"statusFault\",          \"interval\": 300, \"timeout\": 5000}\n               //],\n\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Faucet\",\n               \"displayName\":              \"MyFaucet\",               // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               // Optional Characteristics\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"name\":                     \"MyFaucet\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific - Interval is in second, Timeout in msec\n               // (polling per characteristic)\n\n               // polling requires a state_cmd and state_cmd is\n               // used with your own scripts. Here for example only.\n               //\"polling\": [\n               //   {\"characteristic\": \"active\",               \"interval\": 50,  \"timeout\": 5000},\n               //   {\"characteristic\": \"statusFault\",          \"interval\": 300, \"timeout\": 5000}\n               //],\n\n\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"CloudRelay\",             // Was Relay\n               \"displayName\":              \"MyCloudRelay\",           // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"relayEnabled\":             \"FALSE\",\n                                                                     // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"relayState\":                0,                       // Format: UINT8\n                                                                     // Read-only\n\n               // All TLV8 Characteristics are removed by default,\n               // unless 'allowTLV8' is set, at your own peril.\n               // Setting most will cause Homebridge with HomeKit or Eve.\n               // to not allow you to connect.\n               // \"relayControlPoint\":      0,                       // TLV8\n\n\n               // Optional Characteristics\n               // - None\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   10                       // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"Valve\",\n               \"displayName\":              \"MyValve\",                // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               \"inUse\":                    \"NOT_IN_USE\",             // 0 - \"NOT_IN_USE\"\n                                                                     // 1 - \"IN_USE\"\n\n               \"valveType\":                \"GENERIC_VALVE\",          // 0 - \"GENERIC_VALVE\"\n                                                                     // 1 - \"IRRIGATION\"\n                                                                     // 2 - \"SHOWER_HEAD\"\n                                                                     // 3 - \"WATER_FAUCET\"\n\n               // Optional Characteristics\n\n               \"setDuration\":               0,                       // Format: Uint32\n\n               \"remainingDuration\":         0,                       // Format: Uint32\n                                                                     // Range: 0 - 3600, Step: 1\n\n               \"isConfigured\":             \"CONFIGURED\",             // 0 - \"NOT_CONFIGURED\"\n                                                                     // 1 - \"CONFIGURED\"\n\n               \"serviceLabelIndex\":         1,                       // Range: 1-255, Step: 1\n\n               \"statusFault\":              \"NO_FAULT\",               // 0 - \"NO_FAULT\"\n                                                                     // 1 - \"GENERAL_FAULT\"\n\n               \"name\":                     \"MyValve\",\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"HeaterCooler\",\n               \"displayName\":              \"MyHeaterCooler\",       // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               \"currentHeaterCoolerState\": \"HEATING\",                // 0 - \"INACTIVE\"\n                                                                     // 1 = \"IDLE\"\n                                                                     // 2 - \"HEATING\"\n                                                                     // 3 = \"COOLING\"\n\n               \"targetHeaterCoolerState\":  \"AUTO\",                   // 0 - \"AUTO\"\n                                                                     // 1 - \"HEAT\"\n                                                                     // 2 - \"COOL\"\n\n               \"currentTemperature\":        37.0,                    // Range: 0-100, Step: 0.1\n                                                                     // Format: float\n                                                                     // \"Units\": CELCIUS\n\n               // Optional Characteristics\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",\n                                                                     // 0 - \"CONTROL_LOCK_DISABLED\"\n                                                                     // 1 - \"CONTROL_LOCK_ENABLED\"\n\n               \"name\":                     \"MyHeaterCooler\",\n\n               \"swingMode\":                \"SWING_ENABLED\",          // 0 - \"SWING_DISABLED\",\n                                                                     // 1 - \"SWING_ENABLED\"\n\n               \"coolingThresholdTemperature\":\n                                            22.2,                    // Range 10-35, Step: 0.1\n                                                                     // Units: CELCIUS\n\n               \"heatingThresholdTemperature\":\n                                            25.2,                    // Range 0-25, Step: 0.1\n                                                                     // Format: float\n                                                                     // Units: CELCIUS\n\n               \"temperatureDisplayUnits\":  \"CELSIUS\",\n                                                                     // 0 - \"CELSIUS\"\n                                                                     // 1 - \"FAHRENHEIT\"\n\n               \"rotationSpeed\":             100,                     // Range: 0-100, Step: 1\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"HumidifierDehumidifier\",\n               \"displayName\":              \"MyHumidifierDehumidifier\",// Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"currentRelativeHumidity\":   60,                      // Range: 0-100, Step: 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               \"currentHumidifierDehumidifierState\":\n                                           \"HUMIDIFYING\",            // 0 - \"INACTIVE\"\n                                                                     // 1 - \"IDLE\"\n                                                                     // 2 - \"HUMIDIFYING\"\n                                                                     // 3 - \"DEHUMIDIFYING\"\n\n               \"targetHumidifierDehumidifierState\":\n                                           \"HUMIDIFIER\",             // 0 - \"HUMIDIFIER_OR_DEHUMIDIFIER\"\n                                                                     // 1 - \"HUMIDIFIER\"\n                                                                     // 2 - \"DEHUMIDIFIER\"\n\n               \"active\":                   \"ACTIVE\",                 // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               // Optional Characteristics\n               \"lockPhysicalControls\":     \"CONTROL_LOCK_DISABLED\",  // 0 - \"CONTROL_LOCK_DISABLED\"\n                                                                     // 1 - \"CONTROL_LOCK_ENABLED\"\n\n\n               \"name\":                     \"MyHumidifierDehumidifier\",\n\n               \"swingMode\":                \"SWING_DISABLED\",         // 0 - \"SWING_DISABLED\"\n                                                                     // 1 - \"SWING_ENABLED\"\n\n               \"waterLevel\":                0,                       // Range: 0 - 100\n                                                                     // Format: float\n\n               \"relativeHumidityDehumidifierThreshold\":\n                                            0,                       // Range: 0 - 100, Step 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               \"relativeHumidityHumidifierThreshold\":\n                                            0,                       // Range: 0 - 100, Step 1\n                                                                     // Format: float\n                                                                     // Units: Percentage\n\n               \"rotationSpeed\":             0,                       // Range: 0 - 100, Step 1\n\n               \"manufacturer\":             \"Somebody\",               // Available for all accessories\n\n               \"model\":                    \"Anything\",               // Available for all accessories\n\n               \"serialNumber\":             \"12345\",                  // Available for all accessories\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"AccessControl\",\n               \"displayName\":              \"MyAccessControl\",        // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"accessControlLevel\":        0,                       // 0-2\n\n               // Cmd4 Specific\n               \"stateChangeResponseTime\":   3                        // Default (Seconds)\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"CameraOperatingMode\",\n               \"displayName\":              \"MyCameraOperatingMode\",  // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"eventSnapshotsActive\":     \"DISABLE\",                // 0 - \"DISABLE\"\n                                                                     // 1 - \"ENABLE\"\n\n               \"homeKitCameraActive\":      \"OFF\",                    // 0 - \"OFF\"\n                                                                     // 1 - \"ON\"\n\n               // Optional Characteristics\n               \"manuallyDisabled\":         \"DISABLED\",               // 0 - \"ENABLED\"\n                                                                     // 1 - \"DISABLED\"\n\n               \"nightVision\":              \"FALSE\",                  // 0 - \"FALSE\"\n                                                                     // 1 - \"TRUE\"\n\n               \"thirdPartyCameraActive\":   \"OFF\",                    // 0 - \"OFF\"\n                                                                     // 1 - \"ON\"\n\n               \"periodicSnapshotsActive\":  \"DISABLE\"                 // 0 - \"DISABLE\"\n                                                                     // 1 - \"ENABLE\"\n\n               // Cmd4 Specific\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"SmartSpeaker\",\n               \"displayName\":              \"MySmartSpeaker\",         // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"currentMediaState\":        \"STOP\",                   // 0 - \"PLAY\"\n                                                                     // 1 - \"PAUSE\"\n                                                                     // 2 - \"STOP\"\n                                                                     // 3 - ???\n\n               \"targetMediaState\":         \"STOP\",                   // 0 - \"PLAY\"\n                                                                     // 1 - \"PAUSE\"\n                                                                     // 2 - \"STOP\"\n                                                                     // 3 - ???\n\n               // Optional Characteristics\n               \"name\":                     \"MySmartSpeaker\",\n               \"configuredName\":           \"MySmartSpeaker\",\n               \"volume\":                    5,\n               \"mute\":                     \"FALSE\"                   // 0 - \"FALSE\" (Off)\n                                                                     // 1 - \"TRUE\" (On)\n\n\n\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                     \"TargetControl\",\n               \"displayName\":              \"MyTargetControl\",        // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"activeIdentifier\":          1183,\n               \"active\":                   \"ACTIVE\"                  // 0 - \"INACTIVE\"\n                                                                     // 1 - \"ACTIVE\"\n\n               // All TLV8 Characteristics are removed by default,\n               // unless 'allowTLV8' is set, at your own peril.\n               // Setting most will cause Homebridge with HomeKit or Eve.\n               // to not allow you to connect.\n               //\"buttonEvent\":             0,                       // TLV8\n\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            },\n            {\n               \"type\":                    \"WiFiSatellite\",\n               \"displayName\":             \"MyWiFiSatellite\",         // Not a characteristic, but a function parameter\n\n               // Required characteristics\n               \"wifiSatelliteStatus\":     \"NOT_CONNECTED\"            // 0 - UNKNOWN\n                                                                     // 1 - CONNECTED\n                                                                     // 2 - NOT_CONNECTED\n\n               // Cmd4 Specific\n               //\"state_cmd\": \"node .homebridge/< yourScriptHere >\"\n            }\n          ]\n       }\n   ]\n}\n"
  },
  {
    "path": "Extras/jsmin.c",
    "content": "/* jsmin.c\n\nCopyright (c) 2017 John Talbot (www.BeNiceGames.com)\n\n\n- Inspired by jsmin from Douglas Crockford (www.crockford.com)\n- As compared to his, This jsmin leaves the output uncompacted\n  so that it is legible and ONLY removes C & C++ style comments.\n- This code was rewritten from scratch, only the Permissions\n  are the same, but Kudos to Douglas for coming up with a solution\n  for allowing comments in json files. I just needed something\n  that I could debug the output of more easily. \n\n- Execution is the same:    jsmin < config.min.json > config.json\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nThe Software shall be used for Good, not Evil.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n#include <stdlib.h>\n#include <stdio.h>\n\nint   theCurrentChar;\nint   theNextChar;\nint   insideSingleQuote = 0;\nint   insideDoubleQuote = 0;\nunsigned long theCharacterPositionInLine = 0;\n\nunsigned long lineCounter =1;\n\n// Return the next character from stdin. increasing line number count accordingly.\nint getCharFromStdin()\n{\n    int c = getc(stdin);\n\n    if (c == '\\r') \n       c = '\\n';\n\n    if (c == '\\n') {\n       lineCounter ++;\n       theCharacterPositionInLine = 0;\n    } else {\n       theCharacterPositionInLine ++;\n    }\n    return c;\n}\n\n\n// jsmin -- Copy stdin to stdout, deleting 'C' or 'C++' style comments.\n//       -- Everything else is left the same, except:\n//             - any \\r characters are changed to \\n.\n//             - any empty blank lines are removed.\n//             - any trailing blanks are removed.\n\n// Errors:  The only error possible is for unterminated 'C' style comments.\n\nvoid outputChar(int c)\n{\n   static unsigned long consecutiveSpaceCounter = 0;\n   static int printableCharFoundOnLine = 0;\n\n   // Do not print anything if no characters were on the line.\n   if (c == '\\n' && printableCharFoundOnLine == 0)\n   {\n      consecutiveSpaceCounter = 0;\n      return;\n   }\n\n   // Count the spaces before printing them so that empty lines\n   // are removed. (This looks better for blank lines with comments removed).\n   if (c == ' ')\n   {\n      consecutiveSpaceCounter ++;\n\n   } else {\n\n      // This will print any spaces counted before a real character\n      // and not when EOL is found.\n      if (c != '\\n')\n      { \n         // Since consecutiveSpaceCounter is unsigned, there is no\n         // possability of being stuck in a loop forever.\n         while (consecutiveSpaceCounter !=  0)\n         {\n            putc(' ', stdout);\n            consecutiveSpaceCounter --;\n         }\n         printableCharFoundOnLine = 1;\n      } else {\n\n         // A new line means the next line needs to reset char found flag.\n         printableCharFoundOnLine = 0 ;\n      }\n\n      putc(c, stdout);\n\n      // Since a char was printed, reset the space counter.\n      consecutiveSpaceCounter = 0;\n   }\n}\n\nstatic void\njsmin()\n{\n    // Prime the pump.\n    theCurrentChar = getCharFromStdin();\n\n    while (theCurrentChar != EOF)\n    {\n\n       if (theCurrentChar == '\\'') \n       {\n          insideSingleQuote = 1;\n\n          outputChar(theCurrentChar);\n\n          theCurrentChar = getCharFromStdin();\n\n          // Continue until out of single quotes\n          // or forced out of single quotes by a newline\n          while (insideSingleQuote == 1 &&\n                 theCurrentChar !=EOF)\n          {\n             theNextChar = getCharFromStdin();\n\n             // Skip passed escaped single quotes\n             if (theCurrentChar == '\\\\' && theNextChar == '\\'' )\n             {\n                outputChar(theCurrentChar);\n                theCurrentChar = theNextChar;\n                continue;\n             }\n\n             // Found end of single quotes\n             if (theCurrentChar == '\\'')\n             {\n                insideSingleQuote = 0;\n             }\n\n             // Newline and inside single quotes breaks\n             // out automatically\n             if (theCurrentChar == '\\n')\n             {\n                insideSingleQuote = 0;\n             }\n\n             outputChar(theCurrentChar);\n             theCurrentChar = theNextChar;\n          }\n       }\n\n       if (theCurrentChar == '\\\"')\n       {\n          insideDoubleQuote = 1;\n\n          outputChar(theCurrentChar);\n\n          theCurrentChar = getCharFromStdin();\n\n          // Continue until out of single quotes\n          // or forced out of single quotes by a newline\n          while (insideDoubleQuote == 1 &&\n                 theCurrentChar !=EOF)\n          {\n             theNextChar = getCharFromStdin();\n\n             // Skip passed escaped double quotes\n             if (theCurrentChar == '\\\\' && theNextChar == '\\\"' )\n             {\n                outputChar(theCurrentChar);\n                outputChar(theNextChar);\n                theCurrentChar = getCharFromStdin();\n                theNextChar = getCharFromStdin();\n             }\n\n             // Found end of double quotes\n             if (theCurrentChar == '\\\"')\n             {\n                insideDoubleQuote = 0;\n             }\n\n             // Newline and inside double quotes breaks\n             // out automatically\n             if (theCurrentChar == '\\n')\n             {\n                insideDoubleQuote = 0;\n             }\n\n             outputChar(theCurrentChar);\n             theCurrentChar = theNextChar;\n          }\n       }\n\n\n       // Look for the start of a 'C' or 'C++' style comment.\n       if (theCurrentChar == '/' )\n       {\n          theNextChar = getCharFromStdin();\n\n          // Found a 'C++' style comment.\n          if (theNextChar == '/' )\n          {\n             // Continue until \\n\n             while (theCurrentChar != '\\n' )\n             {\n                theCurrentChar = getCharFromStdin();\n                if (theCurrentChar == EOF)\n                   break;\n             }\n             outputChar(theCurrentChar); // The EOL char\n\n             theCurrentChar = getCharFromStdin();\n             continue; // Main loop.\n          } \n\n          if (theNextChar == '*') // Found a 'C' style comment.\n          {\n             unsigned long openCommentLineNumber = lineCounter;\n\n             // Move past the start of the comment\n             theCurrentChar = getCharFromStdin();\n             theNextChar = getCharFromStdin();\n\n             // Continue until '*/'\n             while (theCurrentChar != '*' || theNextChar != '/' )\n             {\n                if (theCurrentChar == EOF)\n                {\n                   fprintf(stderr, \"Missing comment terminator for line %lu\\n\\n\", openCommentLineNumber);\n                   exit(-1);\n                } \n                theCurrentChar = theNextChar;\n                theNextChar = getCharFromStdin();\n             }\n\n             theCurrentChar = getCharFromStdin();\n\n             continue; // The main loop.\n          }\n\n          outputChar(theCurrentChar);\n\n          // The next char has already been read, use it.\n          theCurrentChar = theNextChar;\n\n          continue; // The main loop.\n       }\n       outputChar(theCurrentChar);\n\n       // Read the char to be processed next.\n       theCurrentChar = getCharFromStdin();\n   }\n}\n\n\n// main -- Output any command line arguments to stderr and then minify the input.\n\nextern int\nmain(int argc, char* argv[])\n{\n    int i;\n    for (i = 1; i < argc; i += 1) {\n        fprintf(stderr, \"%s\\n\", argv[i]);\n    }\n    jsmin();\n    return 0;\n}\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "<span align=\"center\">\n  \n[![npm](https://badgen.net/npm/v/homebridge-cmd4/latest?icon=npm&label)](https://www.npmjs.com/package/homebridge-cmd4)\n[![npm](https://badgen.net/npm/dt/homebridge-cmd4?label=downloads)](https://www.npmjs.com/package/homebridge-cmd4)\n  \n</span>\n\n# Homebridges-cmd4 - CMD4 Plugin for Homebridge - Supports ~All Accessory Types and now all Characteristics, Custom Characteristics and Priority Queued Polling too!!\n<base _target=\"_self\">\n\n<BR><BR>\n## Cmd4 No longer supported:\nAs of September 2025, I will no longer be supporting Cmd4.<BR>\nCmd4 was cool in that it allowed me to discover how the Apple Home App can control all the different devices, but there are a number of reasons why I've decided to no longer support Cmd4.<BR>\n<UL>\n  <LI>Apple took all the fun away from a lot of the devices.  You can no longer do Apple TV for instance. Trying to keep up with Apple's API changes is a fast moving target. HomeBridge tries to minimize this but I have no interest in keeping up with them.</LI>\n  <LI>When homebridge went to TypeScript I was not a fan.  Personally the code bloat that it offers is not worth the effort as I believe good Unit testing and for javascript, JSLint is always a better method. I am also not a fan of Swift for the same reasons. Just try to do a bit shift in Swift.</LI>\n  <LI>Homebridge config-UI-X was always nasty for Cmd4. The latest beta of Config-UI-X has gone on for almost a year and it is probably because they too went to TypeScript.</LI>\n  <LI>My health is not what it used to be.  My little time left on this planet has no interest in supporting Cmd4.</LI>\n</UL>\nSo I did update Cmd4 for the latest Homebridge release which is still in Beta. It is not likely that I will pay any more attention to Cmd4.\n\n<BR><BR>\n## &nbsp;&nbsp;&nbsp; **Cmd4** is a plugin for [Homebridge] that lets you see what Homebridge and Homekit are all about, without actually owning a single accessory!  For the more advanced user, Cmd4 brings CLI support for all device types (Accessories) and characteristics.\n\n## Homebridge UI User. Do not click on any inline links. Homebridge UI does not supprt them. Bug#1098\n<BR><BR>\n## Table of Contents\n* [**About the Cmd4 Plugin**](#about-the-cmd4-plugin)\n* [**How the Cmd4 Plugin Works**](#how-the-cmd4-plugin-works)\n* [**Features**](#features)\n* [**ChangeLog**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/CHANGELOG.md)\n* [**Screenshots**](#screenshots)\n* [**Installation Details**](#installation-details)\n* [**Demo Mode**](#demo-mode)\n* [**Basic Troubleshooting**](#basic-troubleshooting)\n   * [***Error: Command failed***](#error-command-failed)\n   * [***Debug Steps***](#debug-steps)\n* [**Advanced Troubleshooting For Developers**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/AdvancedTroubleShooting.md)\n* [**Developers Guide**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/Developers.md)\n* [**Rationale**](#rationale)\n* [**Todo**](#todo)\n* [**Contributing**](#contributing)\n* [**Inspiration and special thanks**](#inspiration-and-special-thanks)\n* [**License**](#license)\n\n<BR><BR>\n## About the Cmd4 Plugin\n&nbsp;&nbsp;&nbsp; This plugin allows you to see what Homebridge is all about, without having any home control accessories.  If you can run Homebridge and install this plugin, all the possible accessories are now available to you within HomeKit or Eve. (Except Camera Streaming).\n\n&nbsp;&nbsp;&nbsp; Similar to other command plugins, you can use Cmd4 to execute command line interface (CLI) scripts, but with Cmd4 the devices don't just appear in HomeKit as a Switch or a Light, but now they can appear as a Garage Door opener, Air Purifier ... and you can control all of their characteristics too.\n\n<BR><BR>\n## How the Cmd4 Plugin Works\n&nbsp;&nbsp;&nbsp; Cmd4 comes with a fully populated and documented config.json file that is set to using just the cached entry's in the config file itself. This makes HomeKit behave as if you actually have all these Accessories!\n   If you choose to add in your own scripts, the Cmd4 Github pages at [ http://ztalbot2000.github.io/homebridge-cmd4](https://ztalbot2000.github.io/homebridge-cmd4) have example script templates and further development instructions.\n\n<BR><BR>\n## Features\n&nbsp;&nbsp;&nbsp; Cmd4 supports, Lights, Garage Door Openers, Outlets, Switches, Lock Maintenance Systems, Lock Management Systems, Humidity Sensors, Doors, Light Sensors, Temperature Sensors, Contact Sensors, Motion Sensors, Thermostats, Security Systems, Battery Services, Filter Maintenance Systems, Air Purifiers, Television, Television Speaker, Input Sources, Irrigation Systems,  ... everything but Camera Streaming since it is not pliable to a command line Interface.\n\n&nbsp;&nbsp;&nbsp; Cmd4 Polling is a way to in the background update the state of devices via the 'polling' dirctive.\n<UL>\n<LI> \"polling\": \"on\" - Implements polling of the default characteristics of the defined \"timeout\" and \"stateChangeResponseTime\".\n<LI> \"polling\": [{ \"characteristic\": \"<characteristic\">\", [ \"timeout\": <timeout in msec>, \"stateChangeResponseTime\": <stateChangeResponseTime in sec> ] }] - implements per characteristic polling.\n</UL>\n\n&nbsp;&nbsp;&nbsp; Cmd4 supports Fakegato History and retaining previous state over restarts.\n\n&nbsp;&nbsp;&nbsp; Since version 2.0 Cmd4 has supported linked Accessories and the latest 3.0 Version supports both Platform plugin and Accessory plugin configurations as documented on [developers.homebridge.io](https://developers.homebridge.io).\n\n&nbsp;&nbsp;&nbsp; Cmd4 Version 3.5 adds in support for Custom Characteristics.\n\n&nbsp;&nbsp;&nbsp; Cmd4 Version 3.6 allows you to configure Priority Queued Polling so that the accessory only receives one request at a time; with priority to all IOS requests first and polling second.\n\n<BR><BR>\n## Screenshots\n<H3 ALIGN=\"center\">\n  <img src=\"https://github.com/ztalbot2000/homebridge-cmd4/raw/master/screenshots/Homekit_screenshot.png\">\n</H3>\n\n<H3 align=\"center\">\n  <img src=\"https://github.com/ztalbot2000/homebridge-cmd4/raw/master/screenshots/Eve_screenshot.png\">\n</H3>\n\n<BR><BR>\n## Installation Details\n### Step 1.  Install Homebridge\nSee [homebridge](https://github.com/homebridge/homebridge) for complete details.<BR>\n\n\n### Step 2.  Install Cmd4 Plugin\n\n```bash\n   *SHELL*> sudo npm install -g --unsafe-perm homebridge-cmd4\n```\n\n<BR>\n\n### Step 3.  Install/Update your config.json file\n&nbsp;&nbsp;&nbsp; Use the provided config.json file or add it to your own.\n\n```bash\n   *SHELL*> cp /usr/local/lib/node_modules/homebridge-cmd4/Extras/config.json $HOME/.homebridge/\n```\n\n\n### Step 4. Restart homebridge\nSee [homebridge](https://github.com/homebridge/homebridge) for complete details.<BR>\n\n\n### Step 5.  Try Homekit\n&nbsp;&nbsp;&nbsp; If you are not already familiar with Homekit, you may wish to look at the documentation for Homebridge and how to configure it with Homekit. The gist of it is that you enter the manual code defined in the config.json file. I chose 5555555 for simplicity.\n\n### That's it! Enjoy all your new Virtual Accessories!. ✅\n\n<BR><BR>\n## Demo Mode\n&nbsp;&nbsp;&nbsp; The config.json provided has no polling defined. Demo mode is achieved when no polling of any kind for that accessory is defined. In this way all values are retrieved and set from cache.\n\n<BR><BR>\n## Basic Troubleshooting\n\n### Error: Command failed\n&nbsp;&nbsp;&nbsp; This error is indicative to many situations. The most common is that the command took to long to run.\n\n```\n  Error: Command failed: /homebridge/Server.sh Get 'Server' 'On'\n\n    at ChildProcess.exithandler (child_process.js:297:12)\n    at ChildProcess.emit (events.js:193:13)\n    at maybeClose (internal/child_process.js:1001:16)\n    at Process.ChildProcess._handle.onexit (internal/child_process.js:266:5)\n  killed: true\n  code: null\n  signal: SIGTERM,\n  cmd: \"/homebridge/Server.sh Get Server On\"\n\n```\n\nCheck that the command exists, but also that the timeout value in your config.json for that accessory is not too low.\n\n### Debug Steps\n   New in Cmd4 v4.0.0 is how to enable Debug mode. The logs are 100% the same, except that now that Cmd4 has its own logging system ( Copied from Homebridge for compatability ); Enabling Debug logs will not enable Debug logs in other plugins. <BR>\n   There are two ways to enable Cmd4 Debug logs.\n\n#### Method 1.  Modifying the Cmd4 Platform section\n&nbsp;&nbsp;&nbsp; The Cmd4 Platform section can contain the enable Debug directive.\n\n```json\n   {\n      \"platform\": \"Cmd4\",\n      \"name\": \"Cmd4\",\n      \"debug\": true\n   }\n```\n\n#### Method 2.  Add DEBUG environental variable\n\n```bash\n   *SHELL*> DEBUG=Cmd4\n```\nNote: For Homebridge-config-ui-x, you only need to write Cmd4 in the Environmental variable section.\n\n\n<BR><BR>\n## Rationale\n&nbsp;&nbsp;&nbsp; After playing with homebridge-cmd and then homebridge-cmdswitch2, I really wanted to control as much as I could.  I did not have all the devices, but I did have a light and a Sony Android TV.  I wanted to control these and see what else I could do.<BR>\n&nbsp;&nbsp;&nbsp; If you were wondering what happened to version 3, well I learned a lot, hence the working cmd4.\n\n<BR><BR>\n## Todo\n* [ ] Become Homebridge Certified. ( The schema file for Homebridg-ui  would be very difficult )\n\n<BR><BR>\n## Contributing\n&nbsp;&nbsp;&nbsp; Best ways to contribute\n* Star it on GitHub - if you use it and like it please at least star it :)\n* [Promote](#promotion)\n* Open [issues/tickets](https://github.com/ztalbot2000/homebridge-cmd4/issues)\n* Submit fixes and/or improvements with [Pull Requests](https://github.com/ztalbot2000/homebridge-cmd4/pulls)\n\n\n\n### Promotion\n&nbsp;&nbsp;&nbsp; Like the project? Please support to ensure continued development going forward:\n* Star this repo on [GitHub][homebridge-cmd4-repo]\n* Follow the repo on [GitHub][homebridge-cmd4-repo]\n* Follow me\n  * [ztalbot2000](https://github.com/ztalbot2000)\n\n\n<BR><BR>\n## Inspiration and special thanks\nBased on the best of:\n* [homebridge-cmd]https://github.com/senyoltw/homebridge-cmd.git\n* [homebridge-cmdswitch2]https://github.com/luisiam/homebridge-cmdswitch2.git\n* [homebridge-real-fake-garage-doors]https://github.com/plasticrake/homebridge-real-fake-garage-doors.git\n* [homebridge-homeseer]https://github.com/jrhubott/homebridge-homeseer.git\n* Thanks to [TimofeyK](https://github.com/TimofeyK) for all his help with fakegato and for suggesting it.\n* Thanks to [Mitch Williams](https://github.com/mitch7391) for his endless encouragement.\n* Thanks especially to those who continue to work on Homebridge and those who make it better.\n* And most importantly my Wife.\n\n<BR><BR>\n## License\nSee [LICENSE](LICENSE)\n\n\n\n<!---\nLink References (Not Local)\n-->\n\n[homebridge]:https://github.com/homebridge/homebridge\n[developers.homebridge.io]:https://developers.homebridge.io/#/\n[homekit_screenshot]:https://github.com/ztalbot2000/homebridge-cmd4/raw/master/screenshots/Homekit_screenshot.png\n[eve_screenshot]:https://github.com/ztalbot2000/homebridge-cmd4/raw/master/screenshots/Eve_screenshot.png\n[ztalbot2000]:https://github.com/ztalbot2000\n"
  },
  {
    "path": "RUNNING_CHANGELOG.md",
    "content": "# Homebridges-cmd4 - CMD4 Plugin for Homebridge - Supports ~All Accessory Types and now all Characteristics too!!\n<base _target=\"_self\">\n## Homebridge UI User. Do not click on any inline links. Homebridge UI does not supprt them. Bug#1098\n\n\n## ChangeLog\n* <a href=\"#Whats-new-in-8-0-4\">**Whats new in 8.0.4**</a>\n* <a href=\"#Whats-new-in-8-0-3\">**Whats new in 8.0.3**</a>\n* <a href=\"#Whats-new-in-8-0-2\">**Whats new in 8.0.2**</a>\n* <a href=\"#Whats-new-in-8-0-1\">**Whats new in 8.0.1**</a>\n* <a href=\"#Whats-new-in-8-0-0\">**Whats new in 8.0.0**</a>\n* <a href=\"#Whats-new-in-7-1-0\">**Whats new in 7.1.0**</a>\n* <a href=\"#Whats-new-in-7-0-3\">**Whats new in 7.0.3**</a>\n* <a href=\"#Whats-new-in-7-0-2\">**Whats new in 7.0.2**</a>\n<a name=\"Whats-new-in-7-0-1\">## Whats new in 7.0.0</a>\n#### 7.0.0 (2023-06-11)\n* <a href=\"#Whats-new-in-7.0.0\">**Whats new in 7.0.0**</a>\n* <a href=\"#Whats-new-in-6-3-0\">**Whats new in 6.3.0**</a>\n* <a href=\"#Whats-new-in-6-2-0\">**Whats new in 6.2.0**</a>\n* <a href=\"#Whats-new-in-6-1-2\">**Whats new in 6.1.2**</a>\n* <a href=\"#Whats-new-in-6-1-1\">**Whats new in 6.1.1**</a>\n* <a href=\"#Whats-new-in-6-1-0\">**Whats new in 6.1.0**</a>\n* <a href=\"#Whats-new-in-6-0-4\">**Whats new in 6.0.4**</a>\n* <a href=\"#Whats-new-in-6-0-3\">**Whats new in 6.0.3**</a>\n* <a href=\"#Whats-new-in-6-0-2\">**Whats new in 6.0.2**</a>\n* <a href=\"#Whats-new-in-6-0-1\">**Whats new in 6.0.1**</a>\n* <a href=\"#Whats-new-in-6-0-0\">**Whats new in 6.0.0**</a>\n* <a href=\"#Whats-new-in-6-0-0-beta1\">**Whats new in 6.0.0.beta1**</a>\n* <a href=\"#Whats-new-in-5-1-1\">**Whats new in 5.1.1**</a>\n* <a href=\"#Whats-new-in-5-1-0\">**Whats new in 5.1.0**</a>\n* <a href=\"#Whats-new-in-5-0-2\">**Whats new in 5.0.2**</a>\n* <a href=\"#Whats-new-in-5-0-1\">**Whats new in 5.0.1**</a>\n* <a href=\"#Whats-new-in-5-0-0\">**Whats new in 5.0.0**</a>\n* <a href=\"#Whats-new-in-4-2-3\">**Whats new in 4.2.3**</a>\n* <a href=\"#Whats-new-in-4-2-2\">**Whats new in 4.2.2**</a>\n* <a href=\"#Whats-new-in-4-2-1\">**Whats new in 4.2.1**</a>\n* <a href=\"#Whats-new-in-4-2-0\">**Whats new in 4.2.0**</a>\n* <a href=\"#Whats-new-in-4-0-1\">**Whats new in 4.0.1**</a>\n* <a href=\"#Whats-new-in-4-0-0\">**Whats new in 4.0.0**</a>\n* <a href=\"#Whats-new-in-3-10-1\">**Whats new in 3.10.1**</a>\n* <a href=\"#Whats-new-in-3-10-0\">**Whats new in 3.10.0**</a>\n* <a href=\"#Whats-new-in-3-9-0\">**Whats new in 3.9.0**</a>\n* <a href=\"#Whats-new-in-3-8-1\">**Whats new in 3.8.1**</a>\n* <a href=\"#Whats-new-in-3-8-0\">**Whats new in 3.8.0**</a>\n* <a href=\"#Whats-new-in-3-7-5\">**Whats new in 3.7.5**</a>\n* <a href=\"#Whats-new-in-3-7-4\">**Whats new in 3.7.4**</a>\n* <a href=\"#Whats-new-in-3-7-3\">**Whats new in 3.7.3**</a>\n* <a href=\"#Whats-new-in-3-7-2\">**Whats new in 3.7.2**</a>\n* <a href=\"#Whats-new-in-3-7-1\">**Whats new in 3.7.1**</a>\n* <a href=\"#Whats-new-in-3-7-0\">**Whats new in 3.7.0**</a>\n* <a href=\"#Whats-new-in-3-6-1\">**Whats new in 3.6.1**</a>\n* <a href=\"#Whats-new-in-3-6-0\">**Whats new in 3.6.0**</a>\n* <a href=\"#Whats-new-in-3-5-1\">**Whats new in 3.5.1**</a>\n* <a href=\"#Whats-new-in-3-5-0\">**Whats new in 3.5.0**</a>\n* <a href=\"#Whats-new-in-3-4-4\">**Whats new in 3.4.4**</a>\n* <a href=\"#Whats-new-in-3-4-3\">**Whats new in 3.4.3**</a>\n* <a href=\"#Whats-new-in-3-4-2\">**Whats new in 3.4.2**</a>\n* <a href=\"#Whats-new-in-3-4-1\">**Whats new in 3.4.1**</a>\n* <a href=\"#Whats-new-in-3-4-0\">**Whats new in 3.4.0**</a>\n* <a href=\"#Whats-new-in-3-3-2\">**Whats new in 3.3.2**</a>\n* <a href=\"#Whats-new-in-3-3-1\">**Whats new in 3.3.1**</a>\n* <a href=\"#Whats-new-in-3-3-0\">**Whats new in 3.3.0**</a>\n* <a href=\"#Whats-new-in-3-2-5-beta6\">**Whats new in 3.2.5-beta6**</a>\n* <a href=\"#Whats-new-in-3-2-5-beta5\">**Whats new in 3.2.5-beta5**</a>\n* <a href=\"#Whats-new-in-3-2-5-beta3\">**Whats new in 3.2.5-beta3**</a>\n* <a href=\"#Whats-new-in-3-2-5-beta2\">**Whats new in 3.2.5-beta2**</a>\n* <a href=\"#Whats-new-in-3-2-5-beta1\">**Whats new in 3.2.5-beta1**</a>\n* <a href=\"#Whats-new-in-3-2-3\">**Whats new in 3.2.3**</a>\n* <a href=\"#Whats-new-in-3-2-2\">**Whats new in 3.2.2**</a>\n* <a href=\"#Whats-new-in-3-2-1\">**Whats new in 3.2.1**</a>\n* <a href=\"#Whats-new-in-3-2-0\">**Whats new in 3.2.0**</a>\n* <a href=\"#Whats-new-in-3-1-3\">**Whats new in 3.1.3**</a>\n* <a href=\"#Whats-new-in-3-1-2\">**Whats new in 3.1.2**</a>\n* <a href=\"#Whats-new-in-3-1-1\">**Whats new in 3.1.1**</a>\n* <a href=\"#Whats-new-in-3-1-0\">**Whats new in 3.1.0**</a>\n* <a href=\"#Whats-new-in-3-0-15\">**Whats new in 3.0.15**</a>\n* <a href=\"#Whats-new-in-3-0-14\">**Whats new in 3.0.14**</a>\n* <a href=\"#Whats-new-in-3-0-12\">**Whats new in 3.0.12**</a>\n* <a href=\"#Whats-new-in-3-0-11\">**Whats new in 3.0.11**</a>\n* <a href=\"#Whats-new-in-3-0-9\">**Whats new in 3.0.9**</a>\n* <a href=\"#Whats-new-in-3-0-8\">**Whats new in 3.0.8**</a>\n* <a href=\"#Whats-new-in-3-0-7\">**Whats new in 3.0.7**</a>\n* <a href=\"#Whats-new-in-3-0-5\">**Whats new in 3.0.5**</a>\n* <a href=\"#Whats-new-in-3-0-4\">**Whats new in 3.0.4**</a>\n* <a href=\"#Whats-new-in-3-0-0\">**Whats new in 3.0.0**</a>\n* <a href=\"#Whats-new-in-2-4-2\">**Whats new in 2.4.2**</a>\n* <a href=\"#Whats-new-in-2-4-1\">**Whats new in 2.4.1**</a>\n* <a href=\"#Whats-new-in-2-4-0\">**Whats new in 2.4.0**</a>\n* <a href=\"#Whats-new-in-2-3-2\">**Whats new in 2.3.2**</a>\n* <a href=\"#Whats-new-in-2-3-1\">**Whats new in 2.3.1**</a>\n* <a href=\"#Whats-new-in-2-3-0\">**Whats new in 2.3.0**</a>\n* <a href=\"#Whats-new-in-2-2-5\">**Whats new in 2.2.5**</a>\n* <a href=\"#Whats-new-in-2-2-2\">**Whats new in 2.2.2**</a>\n* <a href=\"#Whats-new-in-2-2-1\">**Whats new in 2.2.1**</a>\n* <a href=\"#Whats-new-in-2-2\">**Whats new in 2.2**</a>\n* <a href=\"#Whats-new-in-2-1\">**Whats new in 2.1**</a>\n* <a href=\"#Whats-new-in-2-0\">**Whats new in 2.0**</a>\n\n<a name=\"Whats-new-in-8-0-4\">## Whats new in 8.0.4</a>\n#### 8.0.4 (2026-02-03)\n\n##### Bug Fixes\n\n*  Support Node v24 ([feb476b5](https://github.com/ztalbot2000/homebridge-cmd4/commit/feb476b5bbea98099f7ebaf4a8dcea03572dac82))\n\n\n<a name=\"Whats-new-in-8-0-3\">## Whats new in 8.0.3</a>\n#### 8.0.3 (2024-12-11)\n\n##### Bug Fixes\n\n*  Update node requirements to satisfy the current Node.js version of v22.12.0 ([22761c89](https://github.com/ztalbot2000/homebridge-cmd4/commit/22761c8954dfdb6086023585978836b36f531f65))\n\n\n<a name=\"Whats-new-in-8-0-2\">## Whats new in 8.0.2</a>\n#### 8.0.2 (2024-10-20)\n\n##### Bug Fixes\n\n*  github-version-checker is an unused dependency and is also obsolete, so remove it ([ad220e82](https://github.com/ztalbot2000/homebridge-cmd4/commit/ad220e82b66accf630021dc8c4c136948b720acd))\n*  Also for 146, put back reachable as per Wongs fix ([0e131097](https://github.com/ztalbot2000/homebridge-cmd4/commit/0e131097087899cad530c132b699639e384b3ce0))\n\n\n<a name=\"Whats-new-in-8-0-1\">## Whats new in 8.0.1</a>\n#### 8.0.1 (2024-08-16)\n\n##### Bug Fixes\n\n*  Bug [#147](https://github.com/ztalbot2000/homebridge-cmd4/pull/147) Accesories removed from home app after upgrade to 8.0 ([de25e94f](https://github.com/ztalbot2000/homebridge-cmd4/commit/de25e94fac8cf331142ea4523218db0f8cf447b0))\n\n\n<a name=\"Whats-new-in-8-0-0\">## Whats new in 8.0.0</a>\n### 8.0.0 (2024-06-28)\n\n\n##### Documentation Changes\n*  Document changes for homebridge v2 where TargetAirQuality and TargetSlatState are deprecated ([80ef143](https://github.com/ztalbot2000/homebridge-cmd4/commit/80ef143fa68ff7abedd6bcf4b715d2dab3ae8451))\n\n##### Bug Fixes\n*  fix for homebridge v2 where TargetSlateStte and TargetAirQuality are deprecated ([6acfbb2](https://github.com/ztalbot2000/homebridge-cmd4/commit/6acfbb26bf56a355d76f3f96dafabdfefd26bbb6))\n*  Fix for homebridge v2 Formats&Perms&Units only available directly from HAP ([2a9d6e9](https://github.com/ztalbot2000/homebridge-cmd4/commit/2a9d6e976647f1fa7e1a3ee34e5080a3c28eae73))\n*  Fix lint error ([286dc68](https://github.com/ztalbot2000/homebridge-cmd4/commit/286dc68441c776a93f0f0d913db326fa9ccafeec))\n*  Fix add beta tag ([9b36408](https://github.com/ztalbot2000/homebridge-cmd4/commit/9b364087ec489c5dfda503ceaf1429b626a929c0))\n*  Fix for homebridge v2 where some device types are deprecated ([e483326](https://github.com/ztalbot2000/homebridge-cmd4/commit/e483326d93d447f81be5978f337ce80834798145))\n*  stop committing npm package ([630f4fb](https://github.com/ztalbot2000/homebridge-cmd4/commit/630f4fb6f6cbd876b3fe21ee4689eb40a6adeacc))\n*  Fix: Update hap perms for homebridge v2 & deprecate devices for name changes ([5eb9ede](https://github.com/ztalbot2000/homebridge-cmd4/commit/5eb9ede93de6b80920defeacf704e7c560ee9bda))\n*  Fix: For homebridge V2 which removed Perms.READ and Perms.WRITE for PAIRED_READ & PAIRED_WRITE ([5e888b0](https://github.com/ztalbot2000/homebridge-cmd4/commit/5e888b09cee178ec722499e5429f2dba4fb5c8a9))\n*  Fix: homebridge V2 requires updated package fakegato-history ([61011e5](https://github.com/ztalbot2000/homebridge-cmd4/commit/61011e58378aff7eab351cc97ce05a167f759ca2))\n*  Fix: Set read for h omebridge v2 & Remove deprecated Characteristic.getValue() tests ([b1a8702](https://github.com/ztalbot2000/homebridge-cmd4/commit/b1a870288d73bdcd7abb26a439b9d8e722ad53ea))\n\n\n\n##### New Features\n\n*  Support only Platform Accessories as per Homebridge recommendation ([0ee6efc](https://github.com/ztalbot2000/homebridge-cmd4/commit/0ee6efcc09b7c87f346299fb9ccab5940fba7ee0))\n\n\n<a name=\"Whats-new-in-7-1-0\">## Whats new in 7.1.0</a>\n### 7.1.0 (2024-03-04)\n\n##### Documentation Changes\n\n*  Update for newest characteristics ([fccb9ebd](https://github.com/ztalbot2000/homebridge-cmd4/commit/fccb9ebdc18a2cd876b1512e0da2d5d28e8019b0))\n\n##### New Features\n\n*  Add in latest new characteristics and devices ([545112f0](https://github.com/ztalbot2000/homebridge-cmd4/commit/545112f0fa2122abf51d3217707012879db723b7))\n\n\n<a name=\"Whats-new-in-7-0-3\">## Whats new in 7.0.3</a>\n#### 7.0.3 (2024-01-27)\n\n##### Bug Fixes\n\n*  props is already an object. Also test setProps is called for more than one characteristic. Affects only those who change a characteristics property range ([276d0c0d](https://github.com/ztalbot2000/homebridge-cmd4/commit/276d0c0d58b435c59fb3c1fdfd322f55f6b24434))\n\n\n<a name=\"Whats-new-in-7-1-0\">## Whats new in 7.0.2</a>\n### 7.0.2 (2023-12-24)\n\n##### Change affectng AdvAir by their request\n\n*  For AdvAir.sh put accessory name in double quotes so it can contain a single quote ([023e91c0](https://github.com/ztalbot2000/homebridge-cmd4/commit/023e91c0bf1794a64bf0e18dec7d31b178ecb6d1))\n\n\n## ChangeLog\n* <a href=\"#Whats-new-in-7-0-1\">**Whats new in 7.0.1**</a>\n\n\n##### Chores\n\n*  Correct version to 7.0.1 ([62504e68](https://github.com/ztalbot2000/homebridge-cmd4/commit/62504e689a9483a9512a414d994514b04cbadcd5))\n\n##### Bug Fixes\n\n*  bug[#139](https://github.com/ztalbot2000/homebridge-cmd4/pull/139), add in link checkers to documentation ([f4a1ae79](https://github.com/ztalbot2000/homebridge-cmd4/commit/f4a1ae79fd8da2e0dc80181ab98dbc4817da6e78))\n\n<a name=\"Whats-new-in-7-0-0\">## Whats new in 7.0.0</a>\n#### 7.0.0 (2023-03-05)\n\n* The reason for the major version numbering update was to for deprecation warnings to throw an error.\n  These warnings were there for many major versions and are finally removed.\n\n  \"queueInterval\"         - Never put into production and will now throw an error.\n  \"queueMsg\"              - Never put into production and will now throw an error.\n  \"queueStatMsgInterval\"  - Never put into production and will now throw an error.\n  \"cmd4_Mode\"             - Obsolete for many versions and will now throw an error.\n  \"storage\"               - Obsolete outside of fakegato definition.\n  \"storagePath\"           - Obsolete outside of fakegato definition.\n  \"folder\"                - Obsolete outside of fakegato definition.\n  \"keyPath\"               - Obsolete outside of fakegato definition.\n  \"queueTypes\"            - Obsolete inside accessory definition.\n\n\n##### New Features\n\n*  add retries. Also formatting issues ([b8ddf9ce](https://github.com/ztalbot2000/homebridge-cmd4/commit/b8ddf9ceda8ace3a6e820bfad0c4a03c656cf419))\n\n##### Documentation Changes\n\nBeta2\n*  Update documentation for v7.0.0 ([12b6482a](https://github.com/ztalbot2000/homebridge-cmd4/commit/12b6482ac8e6d431e011f6f92c2d6f03a2ebe2ed))\n\n##### Bug Fixes\n\nBeta2\n*  remove unwanted debug message and test so that it cannot reoccur ([97b6b318](https://github.com/ztalbot2000/homebridge-cmd4/commit/97b6b31861ab34d04b798ec409b1f2e8c56244c2))\n*  Homebridge does not like underscores of accessory names. Remove from default config.json ([15f2170b](https://github.com/ztalbot2000/homebridge-cmd4/commit/15f2170be492b6dfb56e4eed5d76da0cd4d74419))\n\nBeta1\n*  retry logging starts from zero, but for user count starts from 1 ([38cdf417](https://github.com/ztalbot2000/homebridge-cmd4/commit/38cdf417feebeef2b75dcfec247e6bdfd4739604))\n*  By nature retryCount should start from zero ([b8e82ffe](https://github.com/ztalbot2000/homebridge-cmd4/commit/b8e82ffe262c092a301636993544be828a7a34a4))\n*  log message in wrong quotes ([6fc555b0](https://github.com/ztalbot2000/homebridge-cmd4/commit/6fc555b0d7bdc20bfc3a38310e3d4f66b968d55d))\n*  retries for WoRm should be zero. Can be overriden ([11351633](https://github.com/ztalbot2000/homebridge-cmd4/commit/1135163319c8d16e3886dbf0a0443ba5ed6c4b99))\n*  Accessory needs to go unresponsive via updateValue with error object ([cdfee1b2](https://github.com/ztalbot2000/homebridge-cmd4/commit/cdfee1b22ea21dc56edc320768ec6ebea1156cb8))\n\n##### Tests\n\n*  put back skipped tests ([0b0781fa](https://github.com/ztalbot2000/homebridge-cmd4/commit/0b0781faec7f94e43d67068e15e9505cc7c96414))\n*  Remove excess debug messages for commit with verify to work ([ea108470](https://github.com/ztalbot2000/homebridge-cmd4/commit/ea108470631f4abe3377f6d582c962dab141be0f))\n*  Don't know why HomeKit does not cause Cmd4 to generate a log that it is trying to reconnect after unavailable ([d45d7c09](https://github.com/ztalbot2000/homebridge-cmd4/commit/d45d7c095d0989c05b88c161a418402711e26677))\n*  Add unit testing to prove fix of bug[#130](https://github.com/ztalbot2000/homebridge-cmd4/pull/130) ([e9a902fc](https://github.com/ztalbot2000/homebridge-cmd4/commit/e9a902fcb01fb2ee7c7cb9f2b60e036d0fd5c0d6))\n\n\n<a name=\"Whats-new-in-6-3-0\">## Whats new in 6.3.0</a>\n### 6.3.0 (2022-04-12)\n\n##### Bug Fixes\n\n*  Bug [#130](https://github.com/ztalbot2000/homebridge-cmd4/pull/130), linked accessories not accesible after restart ([aeab5a40](https://github.com/ztalbot2000/homebridge-cmd4/commit/aeab5a40340631910ae6ac19f9af8453f46faa55))\n\n\n<a name=\"Whats-new-in-6-2-0\">## Whats new in 6.2.0</a>\n## 6.2.0 (2022-02-18)\n\n##### New Features\n\n*  Add new characteristics and device types ([c3560130](https://github.com/ztalbot2000/homebridge-cmd4/commit/c3560130e7092b698d0d750924c548a99c4e20f4))\n\nCharacteristics\n---------------\nAssetUpdateReadiness\nSupportedAssetTypes\nConfigurationState\nNFCAccessControlPoint\nNFCAccessSupportedConfiguration\nSiriEndpointSessionStatus\nThreadControlPoint\nThreadNodeCapabilities\nThreadStatus\nThreadOpenThreadVersion\n\nDevice Types\n------------\nAccessoryMetrics\nAssetUpdate\nAssistant\nAudioStreamManagement\nBattery\nCameraRecordingManagement\nCloudRelay\nDataStreamTransportManagement\nNFCAccess\nSiriEndpoint\nThreadTransport\n\nNote: While these are now available to use. Some may not be suitable for Cmd4 depending on their complexity.\n\n\n<a name=\"Whats-new-in-6-1-2\">## Whats new in 6.1.2</a>\n#### 6.1.2 (2022-02-12)\n\n##### Bug Fixes\n\n*  bug [#127](https://github.com/ztalbot2000/homebridge-cmd4/pull/127\") Resolve crash when no internet connection\n\n\n<a name=\"Whats-new-in-6-1-1\">## Whats new in 6.1.1</a>\n#### 6.1.1 (2022-01-31)\n\n##### Bug Fixes\n\n*  bug [#125](https://github.com/ztalbot2000/homebridge-cmd4/pull/125) Manufacturer, serialNumber and Model not displaying in Home ([715a2127](https://github.com/ztalbot2000/homebridge-cmd4/commit/715a21275229ffb395b98a2e7c4f9f3d3fd785dd))\n\n\n<a name=\"Whats-new-in-6-1-0\">## Whats new in 6.1.0</a>\n### 6.1.0 (2022-01-30)\n\n##### New Features\n\n*  See if WoRm2 Queue can resolve large scale AirCon accessories ([61b164ae](https://github.com/ztalbot2000/homebridge-cmd4/commit/61b164ae11ffb4731da0ac60bba51d7fbeefff94))\n\n##### Bug Fixes\n\n*  bug [#124](https://github.com/ztalbot2000/homebridge-cmd4/pull/124), Eve graph not being displayed ([929da3e3](https://github.com/ztalbot2000/homebridge-cmd4/commit/929da3e39548df645d316365ab1273d6b5ed250d))\n*  PROGRAM_SCHEDULED_MANUAL_MODE_ constant remove trailing underscore ([52e1fd3f](https://github.com/ztalbot2000/homebridge-cmd4/commit/52e1fd3f100e18588a171c96b8ef9f511180c1bd))\n\n\n<a name=\"Whats-new-in-6-0-4\">## Whats new in 6.0.4</a>\n#### 6.0.4 (2021-12-31)\n\n##### Bug Fixes\n\n*  Constants were not getting passed down to linked types ([b7252bf9](https://github.com/ztalbot2000/homebridge-cmd4/commit/b7252bf934e26535047008f343f4d6b627dd6ddb))\n\n\n<a name=\"Whats-new-in-6-0-3\">## Whats new in 6.0.3</a>\n### 6.0.3 (2021-11-11)\n\n##### Bug Fix\n\n*  Schema Prep for Homebridge-UI integration ([2c5df2c1](https://github.com/ztalbot2000/homebridge-cmd4/commit/2c5df2c1279ebe88fdaedbaa22ae0124e2841b6d))\n\n\n<a name=\"Whats-new-in-6-0-2\">## Whats new in 6.0.2</a>\n### 6.0.2 (2021-11-10)\n\n##### Bug Fix\n\n*  Schema Prep - For Homebridge-ui schema must have defined keys ([3053780b](https://github.com/ztalbot2000/homebridge-cmd4/commit/3053780b40eb3d4505dc407411257109977688a1))\n\n\n<a name=\"Whats-new-in-6-0-1\">## Whats new in 6.0.1</a>\n#### 6.0.1 (2021-11-07)\n\n##### Bug Fixes\n\n*  For bug[#116](https://github.com/ztalbot2000/homebridge-cmd4/pull/116) remove stateCmd validation and for AirCon add global const parsing ([e7bc4963](https://github.com/ztalbot2000/homebridge-cmd4/commit/e7bc49630c47d16d296ff9751df7c7666cf2ecd3))\n\n\n<a name=\"Whats-new-in-6-0-0\">## Whats new in 6.0.0</a>\n## 6.0.0 (2021-10-01)\n\n* Schema Prep - Found in Beta Check case of type ([9a394de0](https://github.com/ztalbot2000/homebridge-cmd4/commit/9a394de020b2ccf67a9c30194163807ea3a226a9))\n\n<a name=\"Whats-new-in-6-0-0-beta1\">## Whats new in 6.0.0-beta1</a>\n## 6.0.0-beta1 (2021-09-27)\n\n##### New Features\n\n*  Schema Prep - More documentation changes ([c6d68f1f](https://github.com/ztalbot2000/homebridge-cmd4/commit/c6d68f1f8a7c24e786a54dbf1660dba98a5d1b6a))\n*  Schema Prep - Documentation changes for feat ([5be7393d](https://github.com/ztalbot2000/homebridge-cmd4/commit/5be7393d4b722c602862a382b1bd710556ff196a))\n*  Schema Prep. More fakegato testing, Make cmd4Dbg not be file global scope ([50355797](https://github.com/ztalbot2000/homebridge-cmd4/commit/503557973758fd4103ab13f34680a4f08eaed3c2))\n*  Schema Prep - for fakegato and others, correct key/value pair the first time it is found ([335ca7e5](https://github.com/ztalbot2000/homebridge-cmd4/commit/335ca7e50958a089c21bfac61ee1982756b7965b))\n*  Schema Prep - Make sure fakegato characteristics are correct ([a8274c7a](https://github.com/ztalbot2000/homebridge-cmd4/commit/a8274c7adb9ffdc2c34d048057f8334d6da9ef8a))\n*  Schema Prep - Should save by index, like others ([20872e2b](https://github.com/ztalbot2000/homebridge-cmd4/commit/20872e2b0f8a5c52131bb9247ba6e6ae11b20fb4))\n*  Schema-Prep This works with all lower case, still sends Get/Set upper case ([d3764584](https://github.com/ztalbot2000/homebridge-cmd4/commit/d3764584f5e0faf369490ad85ed16ba3f19e41c8))\n*  Schema Prep - constants are now lower case and the input is lowered instead ([03b232a1](https://github.com/ztalbot2000/homebridge-cmd4/commit/03b232a152a622025ccfe7c6dc32ab3fa59d6df2))\n*  New tset tool to check where constant is defined ([4fc3668a](https://github.com/ztalbot2000/homebridge-cmd4/commit/4fc3668ad0e1fe51dde4a32ef83f3c78584f4e91))\n*  Schema Prep - Change variables to lower case, still check for Upper case ([2b8f4bf7](https://github.com/ztalbot2000/homebridge-cmd4/commit/2b8f4bf768d1c7aebb3c45f6b019de8201c1656e))\n*  Schema prep- Change constants to an object ([f0dd0de9](https://github.com/ztalbot2000/homebridge-cmd4/commit/f0dd0de923c12fe6dd52cf5469ff87b2d762ee37))\n*  Continue Schema Prep.  Cmd4Storage is now referenced accordingly ([79d85b01](https://github.com/ztalbot2000/homebridge-cmd4/commit/79d85b01bac8d1d3a79a407bcbec0163f19f4e4d))\n*  Schema Prep. FakeGato simplification ([fd26104b](https://github.com/ztalbot2000/homebridge-cmd4/commit/fd26104b0d9c35a53209e91b3efb9ccf820c0333))\n*  Prep for Schema. Stored data now version controlled and assoc array class ([59d7a229](https://github.com/ztalbot2000/homebridge-cmd4/commit/59d7a22903fbb95b4e1b55a7fca4629960c89bfe))\n*  Prep for schema. Warn keys must be lower case ([fe3c155c](https://github.com/ztalbot2000/homebridge-cmd4/commit/fe3c155c5b00574ca3b03baf6d3a32f942756988))\n*  \"Prep for Schema. Unclutter namespace\" ([12a63fb5](https://github.com/ztalbot2000/homebridge-cmd4/commit/12a63fb5339f346b31702bc2f52aa60f299c0de4))\n\n##### Bug Fixes\n\n*  Unit testing order is relevant. Add --bail for sanityTests ([3d3eb844](https://github.com/ztalbot2000/homebridge-cmd4/commit/3d3eb844499c768efbbfdbda88f2164b276e927e))\n*  missed with last update ([2282996c](https://github.com/ztalbot2000/homebridge-cmd4/commit/2282996c5056a1b37edc998766e29c90a74f2cfb))\n*  The warning should read Capitalized, not Upper case ([9b7f7957](https://github.com/ztalbot2000/homebridge-cmd4/commit/9b7f7957613c2c36cb61c86d1f66b3bfa34d49fc))\n*  Found in demo mode, polling for default characteristics was attempted ([01960b73](https://github.com/ztalbot2000/homebridge-cmd4/commit/01960b73c696d788ea06469c5749da2272662e55))\n*  For Demo mode, Target states must be defined so warning is not shown ([a1e00e3f](https://github.com/ztalbot2000/homebridge-cmd4/commit/a1e00e3f84e80300c190b50473ee44026bfe42bc))\n*  Testing Prep Schema fix. Added unit test so will not happen again ([85ab69f7](https://github.com/ztalbot2000/homebridge-cmd4/commit/85ab69f7c366d2ab37ffe76c9eda7ba0d480e3d1))\n\n\n<a name=\"Whats-new-in-5-1-1\">## Whats new in 5.1.1</a>\n#### 5.1.1 (2021-09-16)\n\n##### Bug Fixes\n\n*  Bug [#113](https://github.com/ztalbot2000/homebridge-cmd4/pull/113) Add example SecuritySystem script, fixing TargetState ([fc892370](https://github.com/ztalbot2000/homebridge-cmd4/commit/fc89237021e828831c3fef6b340fd9ae0211cfdf))\n\n\n<a name=\"Whats-new-in-5-1-0\">## Whats new in 5.1.0</a>\n### 5.1.0 (2021-08-16)\n\n##### Chores\n\n*  Add PS5.sh as an example script ([9921cd29](https://github.com/ztalbot2000/homebridge-cmd4/commit/9921cd296a040ec2257c867d689e32a2d045cf7b))\n\n##### New Features\n\n*  Change process.exit to throw new Error ([0a058100](https://github.com/ztalbot2000/homebridge-cmd4/commit/0a058100b1e7db9a6b94517a9d3de43c6568099f))\n*  Change process.exit to throw new Error ([203cc67a](https://github.com/ztalbot2000/homebridge-cmd4/commit/203cc67ad9305348e28aaef910966ac08776ff05))\n\n\n<a name=\"Whats-new-in-5-0-2\">## Whats new in 5.0.2</a>\n#### 5.0.2 (2021-08-14)\n\n##### Bug Fixes\n\n*  For bug [#112](https://github.com/ztalbot2000/homebridge-cmd4/pull/112) where configured fakegato can cause Cmd4 to not run ([53992de4](https://github.com/ztalbot2000/homebridge-cmd4/commit/53992de45b17aa94c367506868a90965ebb71f0d))\n\n\n<a name=\"Whats-new-in-5-0-1\">## Whats new in 5.0.1</a>\n#### 5.0.1 (2021-08-09)\n\n##### Bug Fixes\n\n*  Drastic failure of wormQueue traps on incorrect use of this ([ccaf185d](https://github.com/ztalbot2000/homebridge-cmd4/commit/ccaf185dbe6dded7b2e82c6bde5b6267122b27e5))\n\n##### Tests\n\n*  Test drastic failure of WoRm queue ([82b3ab9c](https://github.com/ztalbot2000/homebridge-cmd4/commit/82b3ab9cef9b224d116511246a0b21ac0e8483e1))\n\n\n<a name=\"Whats-new-in-5-0-0\">## Whats new in 5.0.0</a>\n#### 5.0.0 (2021-08-07)\n\n##### New Features\n\n*  V5 Optimize features, found some older code still to remove ([c52884b](https://github.com/ztalbot2000/homebridge-cmd4/commit/c52884bee08352723debef95f0c5169ebb8cbabb))\n\n*  v5 Simplify, Restart Recover is now always done ([827e8a1](https://github.com/ztalbot2000/homebridge-cmd4/commit/827e8a10763c3ef062f55cb9be108727b0730cc0))\n\n*  v5.0 Simplify - Only 1 start polling message ([ac84270](https://github.com/ztalbot2000/homebridge-cmd4/commit/ac842705385ad8d9699cdf98fd84c6737a36c888))\n\n*  v5.0 Simplification, Remove unused QUEUEMSG ([f25dac8](https://github.com/ztalbot2000/homebridge-cmd4/commit/f25dac86b42ca603f3c0461455f1b2770b59689d))\n\n*  v5.0 Optimize to best config ([120f2a9](https://github.com/ztalbot2000/homebridge-cmd4/commit/120f2a9c3ec2eafb05c051b29e3efe7b1bfdd1f6))\n\n*  v5.0 Deprecate Cmd4Mode ([58d8323](https://github.com/ztalbot2000/homebridge-cmd4/commit/58d832301fc58a054646ae87ecf178a5d83aab83))\n\n*  v5.0 Optimize ([e41eca2](https://github.com/ztalbot2000/homebridge-cmd4/commit/e41eca2eaaf56a2605f564085f6df11111eecf82))\n\n<a name=\"Whats-new-in-4-2-3\">## Whats new in 4.2.3</a>\n#### 4.2.3 (2021-08-03)\n\n##### Bug Fixes\n\n*  For WoRm Queue if setValue script fails, lockup can occur ([c3abf782](https://github.com/ztalbot2000/homebridge-cmd4/commit/c3abf7827626cfd89786d767fd153d4f18ea6462))\n\n\n<a name=\"Whats-new-in-4-2-2\">## Whats new in 4.2.2</a>\n#### 4.2.2 (2021-07-27)\n\n##### Bug Fixes\n\n*  WoRm queues must act like cached for Aircon ([223c83c7](https://github.com/ztalbot2000/homebridge-cmd4/commit/223c83c7bc4219c54c0f70e6439cd3cc4bb6cf50))\n\n\n<a name=\"Whats-new-in-4-2-1\">## Whats new in 4.2.1</a>\n#### 4.2.1 (2021-07-25)\n\n##### Bug Fixes\n\n*  For ticket [#111](https://github.com/ztalbot2000/homebridge-cmd4/pull/111). Oddly node.js is not passing unused arguments in the correct order ([1b50675a](https://github.com/ztalbot2000/homebridge-cmd4/commit/1b50675a4ceebd2fa34ce69b2b4004dba6ae5a25))\n\n\n<a name=\"Whats-new-in-4-2-0\">## Whats new in 4.2.0</a>\n## v4.2.0 (2021-07-24)\n\n##### New Features\n\n*  For Queue (AirCon) ignore low priority polling failure messages ([f431e410](https://github.com/ztalbot2000/homebridge-cmd4/commit/f431e410acefc2025473475c7c986ec27994b4f8))\n\n*  Regular polling uses low priority queue, removing duplicate code ([70e53e73](https://github.com/ztalbot2000/homebridge-cmd4/commit/70e53e73fba0a4f5191e850324361b6462c5e33b))\n\n\n##### Bug Fixes\n\n*  For performance Cmd4 was to call the callback to IOS before the Queue ([7d957daf](https://github.com/ztalbot2000/homebridge-cmd4/commit/7d957daf1f4afb9d1fbdb2ad2c81a04f2978f859))\n\n\n* cross-spawn while maybe faster, fails killing timed out processes ([f12ad71](https://github.com/ztalbot2000/homebridge-cmd4/commit/f12ad7125711952d634b4226c23597d652a97d95))\n\n* Differentiate messages for Queued polling ([fdf6e18](https://github.com/ztalbot2000/homebridge-cmd4/commit/fdf6e186852ad74ed8bb32717de721601000a482))\n\n* Update unit tests for recent changes ([8940795](https://github.com/ztalbot2000/homebridge-cmd4/commit/894079596bace540d174927fd1e593d47f455f99))\n\n* Performance improvement, dont transpose values from homebridge ([c735ef2](https://github.com/ztalbot2000/homebridge-cmd4/commit/c735ef27303aa642ecfe8585d219045e2b53782e))\n##### Testing\n\n* Common unit testing messages ([b214fa8](https://github.com/ztalbot2000/homebridge-cmd4/commit/b214fa8cf6bee71bd854dc1f24f901b1dab8e466))\n\n<a name=\"Whats-new-in-4-0-1\">## Whats new in 4.0.1</a>\n#### 4.0.1 (2021-06-25)\n\n##### Enhancements\n\n*  performance improvement. Cost of every debug log not printed was 300ms ([3c44fab2](https://github.com/ztalbot2000/homebridge-cmd4/commit/3c44fab2800d39deb496cf8d4ad946f3a6368456))\n\n\n<a name=\"Whats-new-in-4-0-0\">## Whats new in 4.0.0</a>\n## 4.0.0 (2021-06-24)\n\n##### New Features\n\n*  Cmd4 gets its own logging mechanism ([048af55c](https://github.com/ztalbot2000/homebridge-cmd4/commit/048af55ca078603889e7d951ff897526d9239179))\n\n##### Bug Fixes\n\n*  For slower Aircon Queue, return current stored value and call updateValue later ([45355819](https://github.com/ztalbot2000/homebridge-cmd4/commit/4535581999256447bda1c16bf48f9bd047347ed1))\n*  if the queue is busy, the next Get entry should not even be tried ([56632c3c](https://github.com/ztalbot2000/homebridge-cmd4/commit/56632c3c4f92530242c83548c95a0d8111964d51))\n\n\n<a name=\"Whats-new-in-3-10-1\">## Whats new in 3.10.1</a>\n#### 3.10.1 (2021-06-13)\n\n##### Bug Fixes\n\n*  Queue \"Sets\" should always come before \"Gets\" and Replace duplicate Sets ([4da5e323](https://github.com/ztalbot2000/homebridge-cmd4/commit/4da5e323bf4971ec68ee60010b13cedab901cd73))\n*  All \"Gets\" should wait until the stateChangeResponseTime in Queues ([9dbfc768](https://github.com/ztalbot2000/homebridge-cmd4/commit/9dbfc76867ac6903a9cf64ad7afa52687d0a7d8a))\n\n\n<a name=\"Whats-new-in-3-10-0\">## Whats new in 3.10.0</a>\n### 3.10.0 (2021-05-29)\n\n##### Chores\n\n*  v3.10.0 packaging ([0a12da5a](https://github.com/ztalbot2000/homebridge-cmd4/commit/0a12da5a8d96dd060665f5ff07a1045eb08a46da))\n\n##### New Features\n\n*  Antifeat as queueBurst was a bust. Squash queue errors for 1min instead ([854fec2f](https://github.com/ztalbot2000/homebridge-cmd4/commit/854fec2f9dcbe393f7ab58dfc7ee9d484cb0b7cd))\n*  Remove feat burst as no added benefit ([afe6b021](https://github.com/ztalbot2000/homebridge-cmd4/commit/afe6b021dd2ecc6564b6396f4368e77836d438de))\n\n##### Bug Fixes\n\n*  runtime fix of this ([ce264c37](https://github.com/ztalbot2000/homebridge-cmd4/commit/ce264c374dbf35b9793baa44fd09dfabe30abcc8))\n\n\n<a name=\"Whats-new-in-3-9-0\">## Whats new in 3.9.0</a>\n### 3.9.0 (2021-05-26)\n\n##### New Features\n\n*  Unit test constants defined but not used and used but not defined ([e52fe8d0](https://github.com/ztalbot2000/homebridge-cmd4/commit/e52fe8d0728093644c0e27d25ebdec83625a00fb))\n\n##### Bug Fixes\n\n*  Pass down outputConstants like other Cmd4 Directives ([44c44b24](https://github.com/ztalbot2000/homebridge-cmd4/commit/44c44b24fa42404976c9cbfd538e3812f3bf3a7d))\n*  Possible crash when defining Default Polling before defining the Queue ([e125abab](https://github.com/ztalbot2000/homebridge-cmd4/commit/e125ababe194b2541f25c8f23ac78f4b138db10c))\n\n\n<a name=\"Whats-new-in-3-8-1\">## Whats new in 3.8.1</a>\n#### 3.8.1 (2021-05-23)\n\n##### Bug Fixes\n\n*  set to #!/usr/bin/env node for multi platform ([d3544fa1](https://github.com/ztalbot2000/homebridge-cmd4/commit/d3544fa13a9cf654e2b2b36c335ae19c7302a49d))\n*  First step of multiple related characteristics using an array; no functionality change ([3092e06e](https://github.com/ztalbot2000/homebridge-cmd4/commit/3092e06e1025cf39be924699108fbf17b2d6ff4f))\n*  Create variable burstMode instead of using burstGroupSize causing issues ([b403f679](https://github.com/ztalbot2000/homebridge-cmd4/commit/b403f679df9ceac72234ba1e0f307697be036b2b))\n\n##### Tests\n\n*  Add routine to check for unused constants ([1da024a0](https://github.com/ztalbot2000/homebridge-cmd4/commit/1da024a0dfaab4664384073a90759aab6c3beebb))\n\n\n<a name=\"Whats-new-in-3-8-0\">## Whats new in 3.8.0</a>\n### 3.8.0 (2021-05-21)\n\n##### Chores\n\n*  v3.8.0 packaging ([1cc9006f](https://github.com/ztalbot2000/homebridge-cmd4/commit/1cc9006ff3867cba44c150d87c028b0621f97c62))\n\n##### Documentation Changes\n\n*  Document Burst for Queue ([fe057931](https://github.com/ztalbot2000/homebridge-cmd4/commit/fe0579315ea79523fb979b1bec69cfddd71c9e55))\n\n##### New Features\n\n*  Add in burst read of Queued Polling ([8b3e8b6e](https://github.com/ztalbot2000/homebridge-cmd4/commit/8b3e8b6eabb07455f2acc90fb6fbe2b0061c79fa))\n*  rough in quash of error message for Queued Polling ([e1ec4947](https://github.com/ztalbot2000/homebridge-cmd4/commit/e1ec49474fdcda73bad780a2caae91b4ed9bab07))\n\n##### Bug Fixes\n\n*  Proper check for burst enabled ([7fab1be6](https://github.com/ztalbot2000/homebridge-cmd4/commit/7fab1be642cd70d28f5433c8b08a7535cb9405ca))\n*  For burst feat, Dont confuse interval and burstInterval ([59c6490b](https://github.com/ztalbot2000/homebridge-cmd4/commit/59c6490b2c5b4b9ea15ddfa63e1d790b3d3ff9f5))\n*  Added tests for Queue sanity timer which found stuff ([d1296b13](https://github.com/ztalbot2000/homebridge-cmd4/commit/d1296b13d91e6f7cdd60272ebc327bbe2d9f6e40))\n*  Change loop condition to bracketed && instead of comma ([3a213e0c](https://github.com/ztalbot2000/homebridge-cmd4/commit/3a213e0c0ef271786080013e3eeddf7a37e74e74))\n*  From previous rough in commit, fix burstGroupSize ([84e9a3da](https://github.com/ztalbot2000/homebridge-cmd4/commit/84e9a3daf987dc9f0a2eb76492713ab9fc64ab34))\n*  from previous commit. Adding burst changes the way entry can be parsed ([a1e5ae06](https://github.com/ztalbot2000/homebridge-cmd4/commit/a1e5ae0635dbb50b873033986eabce7920fb0f97))\n\n\n<a name=\"Whats-new-in-3-7-5\">## Whats new in 3.7.5</a>\n#### 3.7.5 (2021-05-13)\n\n##### Bug Fixes\n\n*  Queued sanity timer was not what it was supposed to be ([0b9314ab](https://github.com/ztalbot2000/homebridge-cmd4/commit/0b9314aba0495839c365ea817ef20da5d72cd277))\n\n\n<a name=\"Whats-new-in-3-7-4\">## Whats new in 3.7.4</a>\n#### 3.7.4 (2021-05-12)\n\n##### Bug Fixes\n\n*  Why does Homebridge check validity of values with invalid return codes affecting Queued polling ([387a13a7](https://github.com/ztalbot2000/homebridge-cmd4/commit/387a13a78483c32e316d4da3dfc187902f6e668e))\n\n\n<a name=\"Whats-new-in-3-7-3\">## Whats new in 3.7.3</a>\n#### 3.7.3 (2021-05-09)\n\n##### Chores\n\n*  Update whats in v3.7.3 ([adfe4444](https://github.com/ztalbot2000/homebridge-cmd4/commit/adfe4444bdf349fe20c86dfde9252cd715df6d5b))\n*  spelling ([394d4d0d](https://github.com/ztalbot2000/homebridge-cmd4/commit/394d4d0d29d773e8e9940618b04ecc62aa2f97d2))\n*  v3.7.3 packaging ([24cda9d8](https://github.com/ztalbot2000/homebridge-cmd4/commit/24cda9d846384d43fd55a50a70c8fe6b788bd8e9))\n\n##### New Features\n\n*  overall performance improvements ([80940ee2](https://github.com/ztalbot2000/homebridge-cmd4/commit/80940ee29bc84ecc1705102b489deec2698a90a0))\n\n##### Bug Fixes\n\n*  Enhance polling queue sanity timer. Fix unneeded related queue callback ([b7b35a68](https://github.com/ztalbot2000/homebridge-cmd4/commit/b7b35a68d181f3e5e1458e1ca2f714bb9736014c))\n*  Related characteristics are Device specific as some are optional in one and required in others ([3e0faf58](https://github.com/ztalbot2000/homebridge-cmd4/commit/3e0faf585032e6d047bd91da2b1dac1453b6cd74))\n\n\n<a name=\"Whats-new-in-3-7-2\">## Whats new in 3.7.2</a>\n#### 3.7.2 (2021-05-04)\n\n##### Bug Fixes\n\n*  PriorityPollingQueue (this) corruption ([f51b1976](https://github.com/ztalbot2000/homebridge-cmd4/commit/f51b1976b4e8b42023bf8029fa8ab9fbb275e39b))\n\n\n<a name=\"Whats-new-in-3-7-1\">## Whats new in 3.7.1</a>\n#### 3.7.1 (2021-05-04)\n\n##### Bug Fixes\n\n*  branch merge issue. Fix Prio queue timer ([146a558c](https://github.com/ztalbot2000/homebridge-cmd4/commit/146a558c6bd1bbee84ccd7d8c6146ce1e11007e4))\n\n\n<a name=\"Whats-new-in-3-7-0\">## Whats new in 3.7.0</a>\n### 3.7.0 (2021-05-03)\n\n##### Documentation Changes\n\n*  Doc generator for last commit was omitted ([81067fe2](https://github.com/ztalbot2000/homebridge-cmd4/commit/81067fe2d6ed18aa76969c29087c8c469644752e))\n*  For PriorityQueuePolling documentation of Sequential or WoRm ([4004f02c](https://github.com/ztalbot2000/homebridge-cmd4/commit/4004f02c86a792e578c670885f71a70c6e06da51))\n\n##### New Features\n\n*  For PriorityQueuePolling add the config.json implementation structure ([7924ec93](https://github.com/ztalbot2000/homebridge-cmd4/commit/7924ec931a4704bcefec6d9df0687573083ce1b8))\n*  Add WoRM as PriorityPollingQueue method ([268b44e9](https://github.com/ztalbot2000/homebridge-cmd4/commit/268b44e9ca3b1b54aa14b999f261d81ca3758f52))\n\n##### Bug Fixes\n\n*  Sequential Priority Queue Polling fix and add Queue Sanity timer ([f8073610](https://github.com/ztalbot2000/homebridge-cmd4/commit/f80736104a763d95c59a10cb3e0ea22343619056))\n*  Queue must be working before adding characteristics ([30a5c863](https://github.com/ztalbot2000/homebridge-cmd4/commit/30a5c863d7991e0c79e9ed29b9471367582c96bb))\n\n\n<a name=\"Whats-new-in-3-6-1\">## Whats new in 3.6.1</a>\n#### 3.6.1 (2021-04-26)\n\n##### Documentation Changes\n\n*  Add example of Priority Queue Polling accros Accessories ([a901a699](https://github.com/ztalbot2000/homebridge-cmd4/commit/a901a69999a804cbb0550582158f10f44769a454))\n\n##### Bug Fixes\n\n*  Incorrect message for staggered polling when also queued polling ([fb020063](https://github.com/ztalbot2000/homebridge-cmd4/commit/fb0200636f2b99b493131cc6b23a83d24df3601c))\n*  Obey stateChangeResponse time for PriorityQueuePolling. Change to constants as well ([eb94eeb6](https://github.com/ztalbot2000/homebridge-cmd4/commit/eb94eeb6a41ece62ee3b35154633e134235ff976))\n\n\n<a name=\"Whats-new-in-3-6-0\">## Whats new in 3.6.0</a>\n### 3.6.0 (2021-04-23)\n\n##### Documentation Changes\n\n*   Interval and Timeout are hierarchal directives ([2393261c](https://github.com/ztalbot2000/homebridge-cmd4/commit/2393261ce26322eaaca77416e487e3c8e877ae6d))\n*  Add interval to documentation ([93fec72b](https://github.com/ztalbot2000/homebridge-cmd4/commit/93fec72b2044471212819ba6cfa49ec6943158fb))\n*  Add missing Cmd4_Mode to platform directives ([685bef51](https://github.com/ztalbot2000/homebridge-cmd4/commit/685bef517229d744c66b1d19d963d0d3d563fce5))\n*  Add line number of where to specifically look ([e4829fd8](https://github.com/ztalbot2000/homebridge-cmd4/commit/e4829fd8a74d96f248f53d2244ba297dce45d4a1))\n*   Adjust docs for Custom Characteristic ([b39f8b7f](https://github.com/ztalbot2000/homebridge-cmd4/commit/b39f8b7f4ba9da1d42d2f62b2efedc4bcf456447))\n*  Documentation for custom characteristic feature previously submitted ([6f9ebb49](https://github.com/ztalbot2000/homebridge-cmd4/commit/6f9ebb49100ab3b82c62e7c467037333a875f1df))\n\n##### New Features\n\n*  Priority Polling Queue CLI, doc & tests ([c6c7fa36](https://github.com/ztalbot2000/homebridge-cmd4/commit/c6c7fa362d92c5c8dc90ef05e9ae467b5e513f82))\n*  Performance stats for Priority Queued Polling ([a9850885](https://github.com/ztalbot2000/homebridge-cmd4/commit/a98508859e02e59cee536780693f2483ae6f0e88))\n*  Create priority polling queue so there are no collisions ([b135ef79](https://github.com/ztalbot2000/homebridge-cmd4/commit/b135ef7985480575412a3dca2f7185a4b5392631))\n\n##### Tests\n\n*  Message order change ([5f330170](https://github.com/ztalbot2000/homebridge-cmd4/commit/5f330170a8641d68c366c3d4ebaa32ce787d711c))\n*  Add more code coverage around polling ([50b102af](https://github.com/ztalbot2000/homebridge-cmd4/commit/50b102afdf4983514ae0a16757e243d8901a6b08))\n*  Resolved still more tests that disrupted others ([7669d883](https://github.com/ztalbot2000/homebridge-cmd4/commit/7669d88366e12ee6a9114a2a813671473342dabc))\n*    Figured out how to add back in conflicting tests ([413f5a87](https://github.com/ztalbot2000/homebridge-cmd4/commit/413f5a87d2c4e1813d04d6f7da81540660af38c1))\n*  Add in more polling tests ([91b56817](https://github.com/ztalbot2000/homebridge-cmd4/commit/91b568175c044adddf3f55b2715ddb89a9de4dd2))\n\n\n<a name=\"Whats-new-in-3-5-1\">## Whats new in 3.5.1</a>\n#### 3.5.1 (2021-04-15)\n\n##### Bug Fixes\n\n*  For bug [#106](https://github.com/ztalbot2000/homebridge-cmd4/pull/106) polling was not able to go lower than 6 seconds ([51459211](https://github.com/ztalbot2000/homebridge-cmd4/commit/5145921132d64483d686175c9d6a316b7186d626))\n\n\n<a name=\"Whats-new-in-3-5-0\">## Whats new in 3.5.0</a>\n### 3.5.0 (2021-04-14)\n\n##### New Features\n\n*   Add custom characteristics ([e3c07d55](https://github.com/ztalbot2000/homebridge-cmd4/commit/e3c07d55ca7e73ed630b9ab072b3f0ec36a1b269))\n\n\n<a name=\"Whats-new-in-3-4-4\">## Whats new in 3.4.4</a>\n#### 3.4.4 (2021-04-09)\n\n##### Bug Fixes\n\n*  [#104](https://github.com/ztalbot2000/homebridge-cmd4/pull/104).  One day one bug, uncovered another ([9075bfe3](https://github.com/ztalbot2000/homebridge-cmd4/commit/9075bfe326a2561e9d511ff4bdc662767e953189))\n\n\n<a name=\"Whats-new-in-3-4-3\">## Whats new in 3.4.3</a>\n#### 3.4.3 (2021-04-08)\n\n##### Bug Fixes\n\n*  Polling has always used the wrong timeout ([74f1f908](https://github.com/ztalbot2000/homebridge-cmd4/commit/74f1f908ca3ab847ca37de2dd4b77f6b11e373c2))\n\n##### Tests\n\n*  Prep for using our own Logger in other than test ([8c4042a1](https://github.com/ztalbot2000/homebridge-cmd4/commit/8c4042a1c9b6d6f52e4699dfc67c19c19d6bbe9a))\n\n\n<a name=\"Whats-new-in-3-4-2\">## Whats new in 3.4.2</a>\n#### 3.4.2 (2021-04-05)\n\n##### New Features\n\n*  Only add new Cmd4 directives for feature in progress ([438462e0](https://github.com/ztalbot2000/homebridge-cmd4/commit/438462e0148d6b96f7da7d6726242c1f1194eed3))\n\n##### Tests\n\n*  Better technique for capturing logging during Unit Testing ([ee2c7dd3](https://github.com/ztalbot2000/homebridge-cmd4/commit/ee2c7dd3355785af35a8bb6221724cc6f5947cbb))\n\n\n<a name=\"Whats-new-in-3-4-1\">## Whats new in 3.4.1</a>\n#### 3.4.1 (2021-03-26)\n\n##### Bug Fixes\n\n*  for bug[#102](https://github.com/ztalbot2000/homebridge-cmd4/pull/102). Fumble fingers causing setCachedValue being called, instead of setValue ([b7ff2f68](https://github.com/ztalbot2000/homebridge-cmd4/commit/b7ff2f68c4d4f0e78c02e478fc43e6e2f81bfe35))\n\n\n<a name=\"Whats-new-in-3-4-0\">## Whats new in 3.4.0</a>\n### 3.4.0 (2021-03-25)\n\n##### Bug Fixes\n\n*  Resolve state being changed over restart ([910f44db](https://github.com/ztalbot2000/homebridge-cmd4/commit/910f44db78680c82892cfa5c163c00e0165ffb56))\n*  Show only start and end of polling kick off message ([7ba5dde9](https://github.com/ztalbot2000/homebridge-cmd4/commit/7ba5dde99924890c78b2ed864b4785f817831b5e))\n\n##### New Features\n\n*  Try to correct meaning of \"fetch\" by changing it to Cmd4_Mode ([3d47291e](https://github.com/ztalbot2000/homebridge-cmd4/commit/3d47291eb7e7dc5fa39440ba5f7155c8a19e462f))\n\n\n<a name=\"Whats-new-in-3-3-2\">## Whats new in 3.3.2</a>\n#### 3.3.2 (2021-03-22)\n\n##### New Features\n\n*  first part of description for config.schema.json, otherwise unused ([c4f60ded](https://github.com/ztalbot2000/homebridge-cmd4/commit/c4f60dedccd1b8694f9e4687f1135d7a14404f22))\n*  Further enhancements to polling ([ff559fc8](https://github.com/ztalbot2000/homebridge-cmd4/commit/ff559fc8d82ece0b0a9892d72877b7ddae3ea9b8))\n\n##### Bug Fixes\n\n*  fakegato humidity for eve room being undefined ([4fb9f7ea](https://github.com/ztalbot2000/homebridge-cmd4/commit/4fb9f7eaabf7b2232d0f32d18490eb1cc6f192ab))\n*  Do not respond until after related characteristic fetch, resolve possible polling collisions ([0b3ff3ca](https://github.com/ztalbot2000/homebridge-cmd4/commit/0b3ff3ca4c0b296b052a0cd1021583d8f6da419f))\n\n\n<a name=\"Whats-new-in-3-3-1\">## Whats new in 3.3.1</a>\n#### 3.3.1 (2021-03-15)\n\n##### Bug Fixes\n\n*  Not handling too much data well ([b4fd8a19](https://github.com/ztalbot2000/homebridge-cmd4/commit/b4fd8a1935817c011b34469fd4505c1cd3294c97))\n\n\n<a name=\"Whats-new-in-3-3-0\">## Whats new in 3.3.0</a>\n### 3.3.0 (2021-03-13)\n\n##### Chores\n\n*  packaging for 3.2.5-beta6 ([5ef6d0e8](https://github.com/ztalbot2000/homebridge-cmd4/commit/5ef6d0e8e4d29679e1550b69489aefbdb318d163))\n*  Missing file ([b95bb22e](https://github.com/ztalbot2000/homebridge-cmd4/commit/b95bb22e46121e36a4dc9dd741ad9a43e24491b9))\n\n##### New Features\n\n*  Now that polling uses updateValue, polling can be independent of fetch ([b3ca7f0](https://github.com/ztalbot2000/homebridge-cmd4/commit/b48d88b66ef1a715d347c6a712aee0a927f48741))\n*  Change to RUNNING_CHANGLOG for Homebeidge-UI bug that cannot follow inline URLs ([13e57946](https://github.com/ztalbot2000/homebridge-cmd4/commit/13e57946c187424f8bef4deb8b28860ba3276330))\n\n##### Bug Fixes\n\n*  properly handle removed platform accessories from cache ([2ce2e9a3](https://github.com/ztalbot2000/homebridge-cmd4/commit/2ce2e9a31030e1f931bc28ae2c55eca59d0c8899))\n*  Globally allow statusMsg option to be set ([cc173514](https://github.com/ztalbot2000/homebridge-cmd4/commit/cc17351407005926a9c3b218f889727b1fb852ef))\n\n##### Tests\n\n*  Test all constants, just in case accidentally changed ([b3ca7f07](https://github.com/ztalbot2000/homebridge-cmd4/commit/b3ca7f07a20d25750e10dee5e0b533dd6f7393fb))\n\n\n<a name=\"Whats-new-in-3-2-5-beta6\">## Whats new in 3.2.5-beta6</a>\n#### 3.2.5-beta6 (2021-03-12)\n\n##### Chores\n\n*  Missing file ([b95bb22e](https://github.com/ztalbot2000/homebridge-cmd4/commit/b95bb22e46121e36a4dc9dd741ad9a43e24491b9))\n\n##### New Features\n\n*  Change to RUNNING_CHANGLOG for Homebeidge-UI bug that cannot follow inline URLs ([13e57946](https://github.com/ztalbot2000/homebridge-cmd4/commit/13e57946c187424f8bef4deb8b28860ba3276330))\n\n##### Bug Fixes\n\n*  properly handle removed platform accessories from cache ([2ce2e9a3](https://github.com/ztalbot2000/homebridge-cmd4/commit/2ce2e9a31030e1f931bc28ae2c55eca59d0c8899))\n*  Globally allow statusMsg option to be set ([cc173514](https://github.com/ztalbot2000/homebridge-cmd4/commit/cc17351407005926a9c3b218f889727b1fb852ef))\n\n\n<a name=\"Whats-new-in-3-2-5-beta5\">## Whats new in 3.2.5-beta5</a>\n#### 3.2.5-beta5 (2021-03-11)\n\n##### New Features\n\n*  Polling now calls updateValue ([9c75b069](https://github.com/ztalbot2000/homebridge-cmd4/commit/9c75b0692ea687559a112269bdfa09fef5568e2e))\n*  Double check for polling or services not being created twice ([2d856289](https://github.com/ztalbot2000/homebridge-cmd4/commit/2d85628996fc3702b5b309754a6bde25dc95f605))\n\n##### Bug Fixes\n\n*  lower Temperature in config.json to match homebridges expected values without prop changes ([78cf3ea7](https://github.com/ztalbot2000/homebridge-cmd4/commit/78cf3ea7f4cae2438023888bf1084d8f649e7a20))\n*  transposing constants to strings and add subType to clarify accessory services ([99d69cec](https://github.com/ztalbot2000/homebridge-cmd4/commit/99d69cec5eb1902f0429a6a84276571fbe6e298a))\n\n##### Other Changes\n\n* Always ([1e144e9c](https://github.com/ztalbot2000/homebridge-cmd4/commit/1e144e9c027f3b0dc353b0bd1c2edd2819712654))\n\n\n<a name=\"Whats-new-in-3-2-5-beta3\">## Whats new in 3.2.5-beta3</a>\n#### 3.2.5-beta3 (2021-03-07)\n\n##### Chores\n\n*  packaging of 3.2.5-beta3 ([0686607b](https://github.com/ztalbot2000/homebridge-cmd4/commit/0686607b3fff0028054021bcf16c2917b242ae3e))\n\n##### Other Changes\n\n* Stagger Polling Starts ([1e144e9c](https://github.com/ztalbot2000/homebridge-cmd4/commit/1e144e9c027f3b0dc353b0bd1c2edd2819712654))\n\n\n<a name=\"Whats-new-in-3-2-6\">## Whats new in 3.2.5-beta2</a>\n#### 3.2.5-beta2 (2021-03-05)\n\n##### Bug Fixes\n\n*  use cross spawn instead of exec ([ab51b8dd](https://github.com/ztalbot2000/homebridge-cmd4/commit/ab51b8dd9b9a543d222d22f54348b06ff901d011))\n\n\n<a name=\"Whats-new-in-3-2-5-beta1\">## Whats new in 3.2.5-beta1</a>\n#### 3.2.5-beta1 (2021-03-03)\n\n##### Chores\n\n*  packaging for v3.2.3 ([504d2e23](https://github.com/ztalbot2000/homebridge-cmd4/commit/504d2e23cd1adfb6713dcdc74cb675a896b93cc9))\n\n##### Documentation Changes\n\n*  Homebridge-UI-X intercept message ([06858799](https://github.com/ztalbot2000/homebridge-cmd4/commit/06858799144b8066762925ba101f16824ce48749))\n\n##### Bug Fixes\n\n*  improve performance of getValue by pre-dfining conversion func based on char being fetched ([51509d6d](https://github.com/ztalbot2000/homebridge-cmd4/commit/51509d6d464d5c8a38c444dbf70acdb5526cafa2))\n*  resolve warnings for strings that could validly have multiple words ([c6642b6c](https://github.com/ztalbot2000/homebridge-cmd4/commit/c6642b6c519e81d5a3bbadcf503f3c4d1eb33569))\n*  [#97](https://github.com/ztalbot2000/homebridge-cmd4/pull/97) Handle both cases for input in config.json. Default should have been UC ([d105cdfe](https://github.com/ztalbot2000/homebridge-cmd4/commit/d105cdfe5848e533f1a0b8a56075e028161baf76))\n*  For [#96](https://github.com/ztalbot2000/homebridge-cmd4/pull/96) Warning message is for related device characteristics only ([f2c28f1a](https://github.com/ztalbot2000/homebridge-cmd4/commit/f2c28f1a46fad0baf073b47f1ccf4612a85c4eb2))\n\n##### Code Style Changes\n\n*  remove dead code ([a3d42a8d](https://github.com/ztalbot2000/homebridge-cmd4/commit/a3d42a8dfcac5263388106d6caf312df22980bb5))\n*  It seems passing structure is expensive ([0b7b4253](https://github.com/ztalbot2000/homebridge-cmd4/commit/0b7b425398bd0e081e2c5faadaefc7d686587da0))\n\n##### Tests\n\n*  Add full initPlugin test, cannot run with others so commented out ([a6de84ac](https://github.com/ztalbot2000/homebridge-cmd4/commit/a6de84ac6f0bd9c13ccbb9b796e1d4c1a1fc3745))\n*   fix unit test that was incomplete ([8c0e2dd0](https://github.com/ztalbot2000/homebridge-cmd4/commit/8c0e2dd0e5f78ab06c5726b89f326c777022d728))\n\n\n<a name=\"Whats-new-in-3-2-3\">## Whats new in 3.2.3</a>\n#### 3.2.3 (2021-03-01)\n\n##### Documentation Changes\n\n*  Homebridge-UI-X intercept message ([06858799](https://github.com/ztalbot2000/homebridge-cmd4/commit/06858799144b8066762925ba101f16824ce48749))\n\n##### Bug Fixes\n\n*  resolve warnings for strings that could validly have multiple words ([c6642b6c](https://github.com/ztalbot2000/homebridge-cmd4/commit/c6642b6c519e81d5a3bbadcf503f3c4d1eb33569))\n*  [#97](https://github.com/ztalbot2000/homebridge-cmd4/pull/97) Handle both cases for input in config.json. Default should have been UC ([d105cdfe](https://github.com/ztalbot2000/homebridge-cmd4/commit/d105cdfe5848e533f1a0b8a56075e028161baf76))\n*  For [#96](https://github.com/ztalbot2000/homebridge-cmd4/pull/96) Warning message is for related device characteristics only ([f2c28f1a](https://github.com/ztalbot2000/homebridge-cmd4/commit/f2c28f1a46fad0baf073b47f1ccf4612a85c4eb2))\n\n##### Tests\n\n*  Add full initPlugin test, cannot run with others so commented out ([a6de84ac](https://github.com/ztalbot2000/homebridge-cmd4/commit/a6de84ac6f0bd9c13ccbb9b796e1d4c1a1fc3745))\n*   fix unit test that was incomplete ([8c0e2dd0](https://github.com/ztalbot2000/homebridge-cmd4/commit/8c0e2dd0e5f78ab06c5726b89f326c777022d728))\n\n\n<a name=\"Whats-new-in-3-2-2\">## Whats new in 3.2.2</a>\n#### 3.2.2 (2021-02-26)\n\n##### Bug Fixes\n\n*  For [#95](https://github.com/ztalbot2000/homebridge-cmd4/pull/95) correct link to pull requests ([6547ff8b](https://github.com/ztalbot2000/homebridge-cmd4/commit/6547ff8be33cb40041d03bd40f523bdc69f7d549))\n*  [#94](https://github.com/ztalbot2000/homebridge-cmd4/pull/94) Changes affect unit testing and Auto generated docs ([876f9889](https://github.com/ztalbot2000/homebridge-cmd4/commit/876f9889c7c46575d0d207a384469389aacc6cbe))\n\n\n<a name=\"Whats-new-in-3-2-1\">## Whats new in 3.2.1</a>\n#### 3.2.1 (2021-02-24)\n\n##### Bug Fixes\n\n*  resolve setting Target characteristics that do not set thier Current characteristic counterpart ([278ffcc7](https://github.com/ztalbot2000/homebridge-cmd4/commit/278ffcc7f34fbd7b648971044a05dbad01189b36))\n*  [#90](https://github.com/ztalbot2000/homebridge-cmd4/pull/90) For Config-UI-X not displaying markdown properly. change to HTML anchors with base URL ([0b8cfef0](https://github.com/ztalbot2000/homebridge-cmd4/commit/0b8cfef05f0d2be0b2baaaad1aa106043dd6d0f3))\n\n##### Code Style Changes\n\n*  lint auto doc generator ([bd259c6f](https://github.com/ztalbot2000/homebridge-cmd4/commit/bd259c6f36231860b2ecebe52f780aeaed9d9cd0))\n\n##### Tests\n\n*  add markdown checker ([0dd19ca7](https://github.com/ztalbot2000/homebridge-cmd4/commit/0dd19ca7f5588390ec5a904a75199b4817f1353e))\n\n\n<a name=\"Whats-new-in-3-2-0\">## Whats new in 3.2.0</a>\n### 3.2.0 (2021-02-23)\n\n##### Bug Fixes\n\n*  cached data over restarts ([020797fe](https://github.com/ztalbot2000/homebridge-cmd4/commit/020797fe70cd82afaca5a0c5d713cdab1ca5b32a))\n\n\n<a name=\"Whats-new-in-3-1-3\">## Whats new in 3.1.3</a>\n#### 3.1.3 (2021-02-17)\n\n##### Chores\n\n*  Path for my m1mini changed ([81d5d7d0](https://github.com/ztalbot2000/homebridge-cmd4/commit/81d5d7d0da1c03eb5da03b3e086f6a4170034dd5))\n\n##### Documentation Changes\n\n*  Correct link for case change ([249c31f1](https://github.com/ztalbot2000/homebridge-cmd4/commit/249c31f188b55755644031c6d61d5aa79e149108))\n\n##### Bug Fixes\n\n*  Setting cached values should set their corresponding cached verify characteristic ([b8b34098](https://github.com/ztalbot2000/homebridge-cmd4/commit/b8b340986029ff11f3523c6b8b29fd1e8859b73c))\n*  Any stderr messages should be logged ([b6289133](https://github.com/ztalbot2000/homebridge-cmd4/commit/b6289133d4ceb6fd3f6c1744670df66741cf4ea2))\n\n##### Tests\n\n*  Check cached values should set their corresponding cached verify characteristic ([a9b380a5](https://github.com/ztalbot2000/homebridge-cmd4/commit/a9b380a582819c59df30d7ec0f57c7669c99844a))\n*  Check for stderr messages being logged ([442e6beb](https://github.com/ztalbot2000/homebridge-cmd4/commit/442e6beb463f56f11107518a779bf48e83c8bc64))\n\n\n<a name=\"Whats-new-in-3-1-2\">## Whats new in 3.1.2</a>\n#### 3.1.2 (2021-02-15)\n\n##### Bug Fixes\n\n*  A bit better answer to [#89](https://github.com/ztalbot2000/homebridge-cmd4/pull/89), with testcases to prove it ([569018b5](https://github.com/ztalbot2000/homebridge-cmd4/commit/569018b5a0f6bfc76b045d70acead590fa267de2))\n\n\n<a name=\"Whats-new-in-3-1-1\">## Whats new in 3.1.1</a>\n#### 3.1.1 (2021-02-15)\n\n##### Bug Fixes\n\n*  For [#89](https://github.com/ztalbot2000/homebridge-cmd4/pull/89).  No returned getValue results in \"Cannot read property reduce of null\" ([3d080d3d](https://github.com/ztalbot2000/homebridge-cmd4/commit/3d080d3dc85754ff9eac030507b5322f5faad5e9))\n\n\n<a name=\"Whats-new-in-3-1-0\">## Whats new in 3.1.0</a>\n### 3.1.0 (2021-02-14)\n\n##### Features\n* For #88 Log a Status change message and have it be optional statusMsg ([019c6d2](https://github.com/ztalbot2000/homebridge-cmd4/commit/ef9f57fc646eeab5a15e404f445545a2a2528391))\n\n##### Build System / Dependencies\n\n*  Remove images destined for github pages from npm distribution ([7a11296b](https://github.com/ztalbot2000/homebridge-cmd4/commit/7a11296b783e3d51237f9109b62696f684f0d902))\n*  Remove images destined for github pages from npm distribution ([7a11296b](https://github.com/ztalbot2000/homebridge-cmd4/commit/7a11296b783e3d51237f9109b62696f684f0d902))\n*  Add commit message rules and up version generator ([d6dfcb19](https://github.com/ztalbot2000/homebridge-cmd4/commit/d6dfcb19bd98e782ac103dcecd5b0e0dcce37a07))\n*  npm shoud ignore .github templates etc ... ([a457e0bc](https://github.com/ztalbot2000/homebridge-cmd4/commit/a457e0bc92b59e983ba33e8d11fb07207084d480))\n\n##### Chores\n\n*  Already merged. Try to fix Git tree ([33694479](https://github.com/ztalbot2000/homebridge-cmd4/commit/3369447934e2f328f2a69d37cf61ceedc97f6f63))\n\n##### Bug Fixes\n\n*  Store value to cache after successful set to device when fetch=\"Polled\" ([18a4f569](https://github.com/ztalbot2000/homebridge-cmd4/commit/18a4f5691fe67abc3c64d152822134b77b09aaa4))\n*  Cached characteristics were never stored if changed by other than polling ([fd3b4cc8](https://github.com/ztalbot2000/homebridge-cmd4/commit/fd3b4cc894598bf424371de03656054d713f3663))\n\n##### Other Changes\n\n* < true/false > ([ef9f57fc](https://github.com/ztalbot2000/homebridge-cmd4/commit/ef9f57fc646eeab5a15e404f445545a2a2528391))\n*  Update issue templates ([5eb330ad](https://github.com/ztalbot2000/homebridge-cmd4/commit/5eb330ad18a58f8c5f1a456ed261bb6c963c8217))\n*  Update issue templates ([f19bec63](https://github.com/ztalbot2000/homebridge-cmd4/commit/f19bec6322f77026c0da707a5b283fbe956beb6f))\n*  Rename Changelog.md to CHANGELOG.md for naming conventions and future use of standard-version ([c9a4b746](https://github.com/ztalbot2000/homebridge-cmd4/commit/c9a4b746aea2c9b003b4219ab4d042cc7b3eadbe))\n*  Add in Fetch Diagram ([7bd8b46e](https://github.com/ztalbot2000/homebridge-cmd4/commit/7bd8b46eecb62c232137dfba6c1356d7c619bf01))\n*  Fixed broken link to Developers Guide. ([a55e6235](https://github.com/ztalbot2000/homebridge-cmd4/commit/a55e6235c036992c2dd6fb6879f82635fe5a3d03))\n*  Fix broken link to LICENSE. ([9b702d0a](https://github.com/ztalbot2000/homebridge-cmd4/commit/9b702d0a704d19c4aae764003e527d47013663df))\n*  Fix links to 'raw' text versions of links. ([33e558b4](https://github.com/ztalbot2000/homebridge-cmd4/commit/33e558b41726dc5fb518933dd993387e0fe17e59))\n*  Fix broken link to LICENSE. ([82ab2aba](https://github.com/ztalbot2000/homebridge-cmd4/commit/82ab2aba3fb16cc6992fbc2c0fc1a0a0dec3cae6))\n*  Fixed broken link to Developers Guide ([f46b2b78](https://github.com/ztalbot2000/homebridge-cmd4/commit/f46b2b7873bbd89c7780c58b2916fc28b41e4873))\n*  Create issue templates. ([5059486f](https://github.com/ztalbot2000/homebridge-cmd4/commit/5059486fc65ef39e8aa7aed02c093f6fd95e0537))\n\n##### Tests\n\n*  fix tests that sometimes failed ([cd005d9b](https://github.com/ztalbot2000/homebridge-cmd4/commit/cd005d9b344aee92a03127c19947f4ba47f11eeb))\n*  Check if 0, \"0\" or \"0.0\" is handled correctly and it is ([019c6d26](https://github.com/ztalbot2000/homebridge-cmd4/commit/019c6d267fbe73a36099806eb79d4902e6698907))\n*  Add test for same config as polling ([4eb8c09a](https://github.com/ztalbot2000/homebridge-cmd4/commit/4eb8c09aed103edbf5d05d78269fc0835f198477))\n\n\n<a name=\"Whats-new-in-3-0-15\">## Whats new in 3.0.15</a>\n* Cached characteristics were never stored when not updated by other than polling.\n\n<a name=\"Whats-new-in-3-0-14\">## Whats new in 3.0.14</a>\n* Remove unwanted log.\n* Code cleanup of setValue. Stuff no longer relavent.\n\n<a name=\"Whats-new-in-3-0-12\">## Whats new in 3.0.12</a>\n* Absolutely no changes. Advertise deprecation notice of State.js and\n  new Cmd4 GitHub Pages at: https://ztalbot2000.github.io/homebridge-cmd4\n\n<a name=\"Whats-new-in-3-0-11\">## Whats new in 3.0.11</a>\n* Fix for output constants occuring if not default not set.\n\n<a name=\"Whats-new-in-3-0-9\">## Whats new in 3.0.9</a>\n* Fix removal of fetch, causing caching of the designation to result\n  in \"Invalid value: undefined for Fetch\"\n\n<a name=\"Whats-new-in-3-0-8\">## Whats new in 3.0.8</a>\n* Fix outputConstants not outputting anything if no translation\n* Fix debug message causing trap during outputConstants\n* Beginning of auto generated documentation in GitHub. Please\n  Do not criticize yet. Work in progress.\n\n<a name=\"Whats-new-in-3-0-7\">## Whats new in 3.0.7</a>\n* Fix Switch on/off being off/on\n\n<a name=\"Whats-new-in-3-0-6\">## Whats new in 3.0.6</a>\n* No changes, just packaging issue.\n\n<a name=\"Whats-new-in-3-0-5\">## Whats new in 3.0.5</a>\n* Fix of issue #78.  Most constants were not documented correctly and 3.0 no longer uppercased them for you. Put back this capability and fix the documentation.\n* Fix Bug: ReferenceError: Cannot access 'result' before initialization when Fetch is set to Cached and some other details.\n\n<a name=\"Whats-new-in-3-0-4\">## Whats new in 3.0.4</a>\n* BugFix of issue #76 for those who did not specify any polling type at all and \"fetch\": \"Always\" ( The default ) caused any characteristic state to be retrieved at all.\n* Minor improvement to the version checker that stopped post install notes from being displayed.\n* Allow Cmd4 cached directive changes, like \"polling\" to be overwritten over restarts.\n\n\n<a name=\"Whats-new-in-3-0-0\">## Whats new in 3.0.0</a>\n### Changes to support IOS 14.\n* Cmd4 now follows the [Homebridge Plugin Template](https://github.com/homebridge/homebridge-plugin-template). This means that:\n\n   * Accessories[] are now platformAccessories and can be published externally with an optional category. i.e.<BR>\n   ```json\n     { \"category\": \"TELEVISION\" }\n   ```\n   * This allows multiple TV's to be configured per Bridge as separate platforms.\n   * Accessory plugins can also be defined separately.\n   * This fixes TV icons not being displayed in the Home App of IOS 14.\n* Number of Devices increased from 52 to 64.\n* Number of Characteristics increased from 160 to 221.\n* Returned \"quoted strings\" or 'quoted strings' are now acceptable.\n* Reduced child processes with new \"fetch\" option\n   * { \"fetch\": \"Always\" } - As before ( Default )\n   * { \"fetch\": \"Cached\" } - Never fetch characteristic value. Use cached value. The cached value would have to be updated through polling.\n   * { \"fetch\": \"Polled\" } - Polled characteristics act like before, \"Always\". Non polled characteristic values are fetched from cache.\n* Added the ability to remember characteristic values over restarts. This also means that device name changes and the like are possible. Disabled by:<BR>\n```json\n   \"restartRecover\": false\n```\n   In the section of the config.json where \"platform\": \"Cmd4\" is defined. Default is true.\n* Retrieved characteristic values are now converted to those defined by homebridge, instead of guessed by their possible types.\n* Accessory polling definition changes from:<BR>\n```\n   [{ < characteristic >:< defaultValue >, \"interval\":< sec >, \"timeout\": < msec > }]\n```\nTo:<BR>\n```\n   [ \"characteristic\": < characteristic >, \"interval\":< sec >, \"timeout\": < msec > }]\n```\n   Note: Old style is still supported with warning.\n\n* Moved some functions to utilities for easier unit testing.\n* Splitting documentation into three different areas, README, Advanced Troubleshooting and a Developers guide.\n* Changed utility colors.js for package chalk.\n* Internally, any string is now a constant, limiting some possible typos.\n* Added eslint and resolved all recommended lint errors.\n\n# Important\nWhile this version appears backward compatible, there is a difference in that the Accessories are created as Platform Accessories as compared to Standard Accessories. The [Homebridge API](https://developers.homebridge.io/#/) documentation details the difference as does the new [Cmd4 Developers Guide](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/Developers.md).\n<BR><BR>\n\n<a name=\"Whats-new-in-2-4-2\">## Whats new in 2.4.2</a>\n* Bug fix for negative temperature values\n* Add in ability to change properties like minValue. Effect is none as not used, except for further testing.<BR>\n\n<a name=\"Whats-new-in-2-4-1\">## Whats new in 2.4.1</a>\n* Add check for duplicate UUID's that may be created and homebridge now complains about.\n* Fix issue were configuredName was not provided in users config.json.\n* Add an example of a DoorLock.sh with on a PI and using a GPIO to control it.\n* Add a tool to me debug users config.json files.\n\n<a name=\"Whats-new-in-2-4-0\">## Whats new in 2.4.0</a>\n* While a bump to the minor release, the changes are development only and also for any spelling errors.\n* The plugin was split into its respective program/lib/utility/ChangeLog modules.\n* Splitting the plugin allowed for better Unit testing.\n* What is new are some examples of scripts for ping and wake on lan and can be found in the Extras/CMD4Scripts/Examples sub-directory.\n\n<a name=\"Whats-new-in-2-3-2\">## Whats new in 2.3.2</a>\n* Minor changes for spelling and package updates. Nothing to see here. These are not the changes you are looking for.<BR>\n\n<a name=\"Whats-new-in-2-3-1\">## Whats new in 2.3.1</a>\n* Minor changes for spelling and package updates. Nothing to see here. These are not the changes you are looking for.<BR>\n* Updates for Homebridge 1.0.4.\n* Added 'AUTO' as current heating state matching Apples Development documentation.\n* Increased default timeout to 8 seconds as HomeBridge 1.04 seems slower.<BR>\n* Pull in README update noted by Daniel.\n\n<a name=\"Whats-new-in-2-3-0\">## Whats new in 2.3.0</a>\n* Added state_cmd_prefix and state_cmd_suffix to possible state_cmd options.  This does what they intend to where:<BR>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<I><B>state_cmd_prefix</B></I> - adds a string before the state_cmd. i.e. state_cmd_prefix=sudo would create the Set command to be:<BR>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sudo node .homebridge/Cmd4Scripts/State.js 'My_Fan' '1'<BR>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<I><B>state_cmd_suffix</B></I> - adds a string after the state_cmd. i.e. state_cmd_suffix=\"00:16:AA:BB:1F:2D\" would create the Set command to be:<BR>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node .homebridge/Cmd4Scripts/State.js Set 'My_Fan' '1' 00:16:AA:BB:1F:2D<BR>\n&nbsp;&nbsp;&nbsp; Combining the two i.e. state_cmd_prefix=sudo state_cmd_suffix=\"00:16:AA:BB:1F:2D\" would create the Get command to be:<BR>\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sudo node .homebridge/Cmd4Scripts/State.js Get 'My_Fan' 00:16:AA:BB:1F:2D<BR>\n\n<a name=\"Whats-new-in-2-2-5\">## Whats new in 2.2.5</a>\n* There is a bug in github-version-checker.  I can't get around it so change to a direct comparison of what is in npm.\n\n<a name=\"Whats-new-in-2-2-2\">## Whats new in 2.2.2</a>\n* This minor version adds an error message when accidentally defining multiple characteristics for characteristic polling.\n\n<a name=\"Whats-new-in-2-2-1\">## Whats new in 2.2.1</a>\n* This minor version differentiates the optional characteristic 'Name' from displayName.\n    displayName is used when creating the service.  It is essentially the same thing, but this follows the spec exactly.  You do not need to change your config.json file if you do not want too.\n* Internally all properties of all characteristics are defined.\n* Homebridge does not allow you to getCharacteristic information easily.  This allows Cmd4 to stop you from using characteristics with a format of TLV8 that causes HomeBridge to fail to start.  This is why the new option:'allowTLV8' was created and set to false by default. Again just ignore it.\n* With all the properties defined, Test cases increases to 7644.\n\n<a name=\"Whats-new-in-2-2\">## Whats new in 2.2</a>\n* This version adds in linked accessories. HDMI Input sources for a TV are now shown in HomeKit as an example.\n* This release also defines constants for all the characteristics that has them.  Look at the config.min.json file for descriptions of the constants per characteristic.\n* The number of test cases increases because of constants to 4500.  That equates to almost 61\\% more coverage, and less possible errors.\n* Finally this release adds in version checking so you are always up to date with the latest version of Homebridge-Cmd4.\n\n<a name=\"Whats-new-in-2-1\">## Whats new in 2.1</a>\n* This minor release fixes duplicate service calls for initializing an AccessoryInformation device, Television & TelevisionSpeaker.\n\nMostly importantly it wipes out 5600 duplicate lines of code to one bound function.\n\n<a name=\"Whats-new-in-2-0\">## Whats new in 2.0</a>\n* 2This release changes the philosophy of homebridge-Cmd4 from Accessories that have known characteristics as per the HAP Spec to assigning any characteristic to any Accessory.\n\nThere are 160 possible characteristics, 60 more than the previous version.  Also TV, TV Speaker, Input Source, Irrigation, Faucets and many other accessories are now available.\n"
  },
  {
    "path": "cmd4Constants.js",
    "content": "\"use strict\";\n\n// Naming convention\n// DEFAULT_    => Default values\n// _l          =>  Lower Case\n// _lv         =>  Lower Case Variable of same name\n\n// Triggers which Array CMD4Accessory will be placed\n// Either cmd4Accessories or cmd4StandaloneAccessories\n//\n\n\nvar cmd4Constants = {\n   STANDALONE:                \"Standalone\",\n   PLATFORM:                  \"Platform\",\n\n   // Default intervals\n   // 10 seconds\n   SLOW_STATE_CHANGE_RESPONSE_TIME:       10000,\n   // 3 seconds\n   MEDIUM_STATE_CHANGE_RESPONSE_TIME:     3000,\n   // 3 seconds\n   DEFAULT_STATE_CHANGE_RESPONSE_TIME:    3000,\n   // 1 second\n   FAST_STATE_CHANGE_RESPONSE_TIME:       1000,\n\n   // 1 minute\n   DEFAULT_INTERVAL:          60000,\n   // 1 minute\n   DEFAULT_TIMEOUT:           60000,\n\n   // Not a Bool, otherwise conditional check fails\n   DEFAULT_STATUSMSG:         \"TRUE\",\n\n   DEFAULT_QUEUE_TYPE:        \"WoRm\",\n   // 10 seconds\n   DEFAULT_QUEUE_PAUSE_TIMEOUT:  10000,\n\n   // No debug\n   DEFAULT_DEBUG:             false,\n   // No funny TLV8 characteristics\n   DEFAULT_ALLOW_TLV8:        false,\n   DEFAULT_OUTPUTCONSTANTS:   false,\n\n   // Fakegato Constants\n   FAKEGATO_TYPE_ENERGY:      \"energy\",\n   FAKEGATO_TYPE_ROOM:        \"room\",\n   FAKEGATO_TYPE_WEATHER:     \"weather\",\n   FAKEGATO_TYPE_DOOR:        \"door\",\n   FAKEGATO_TYPE_MOTION:      \"motion\",\n   FAKEGATO_TYPE_THERMO:      \"thermo\",\n   FAKEGATO_TYPE_AQUA:        \"aqua\",\n   EVE:                       \"eve\",\n   STORAGE:                   \"storage\",\n   STORAGEPATH:               \"storagePath\",\n   FOLDER:                    \"folder\",\n   KEYPATH:                   \"keyPath\",\n   STATUS:                    \"status\",\n   TEMP:                      \"temp\",\n   SETTEMP:                   \"setTemp\",\n   HUMIDITY:                  \"humidity\",\n   PPM:                       \"ppm\",\n   POWER:                     \"power\",\n   PRESSURE:                  \"pressure\",\n   CURRENTTEMP:               \"currentTemp\",\n   VALVEPOSITION:             \"valvePosition\",\n   WATERAMOUNT:               \"waterAmount\",\n   TIME:                      \"time\",\n   PATH:                      \"path\",\n\n   FS:                        \"fs\",\n   GOOGLE_DRIVE:              \"googleDrive\",\n\n   // Config Constants\n   DEBUG:                     \"debug\",\n   OUTPUTCONSTANTS:           \"outputConstants\",\n   STATUSMSG:                 \"statusMsg\",\n   QUEUETYPE:                 \"queueType\",\n   QUEUETYPES:                \"queueTypes\",\n\n   // Queue Types\n   QUEUETYPE_SEQUENTIAL:      \"Sequential\",\n   QUEUETYPE_WORM:            \"WoRm\",\n   QUEUETYPE_WORM2:           \"WoRm2\",\n   // Used internally to mean only polled entries go straight through the queue\n   QUEUETYPE_STANDARD:        \"StandarD\",\n   // Used internally to mean entries go straight through the queue\n   QUEUETYPE_PASSTHRU:        \"None\",\n   DEFAULT_STANDARD_QUEUE_RETRY_COUNT: 0,\n   DEFAULT_WORM_QUEUE_RETRY_COUNT: 0,\n   QUEUE_RETRIES:             \"retries\",\n\n\n\n   // Platform/Accessory Config Constants\n   TYPE:                      \"type\",\n   SUBTYPE:                   \"subType\",\n   DISPLAYNAME:               \"displayName\",\n   UUID:                      \"uuid\",\n   ACCESSORY:                 \"accessory\",\n   CATEGORY:                  \"category\",\n   PUBLISHEXTERNALLY:         \"publishExternally\",\n   CHARACTERISTIC:            \"characteristic\",\n   TIMEOUT:                   \"timeout\",\n   QUEUE:                     \"queue\",\n   POLLING:                   \"polling\",\n   INTERVAL:                  \"interval\",\n   STATECHANGERESPONSETIME:   \"stateChangeResponseTime\",\n   STATE_CMD_PREFIX:          \"state_cmd_prefix\",\n   STATE_CMD_SUFFIX:          \"state_cmd_suffix\",\n   STATE_CMD:                 \"state_cmd\",\n   FAKEGATO:                  \"fakegato\",\n   REQUIRES:                  \"requires\",\n   CONSTANTS:                 \"constants\",\n   VARIABLES:                 \"variables\",\n   LINKEDTYPES:               \"linkedTypes\",\n   ACCESSORIES:               \"accessories\",\n   URL:                       \"url\",\n   ALLOWTLV8:                 \"allowTLV8\",\n\n   DEFINITIONS:              \"definitions\",\n   PROPS:                    \"props\",\n\n   // While also characteristics, they are also used by\n   // the infomation service\n   MANUFACTURER:             \"manufacturer\",\n   SERIALNUMBER:             \"serialNumber\",\n   MODEL:                    \"model\",\n\n   // Internal list variables\n   ACCESSORY_lv:                    \"accessory\",\n   CHARACTERISTIC_STRING_lv:        \"characteristicString\",\n   CALLBACK_lv:                     \"callback\",\n   ACC_TYPE_ENUM_INDEX_lv:          \"accTypeEnumIndex\",\n   INTERVAL_lv:                     \"interval\",\n   IS_SET_lv:                       \"isSet\",\n   QUEUE_NAME_lv:                   \"queueName\",\n   QUEUE_GET_IS_UPDATE_lv:          \"queueGetIsUpdate\",\n   STATE_CHANGE_RESPONSE_TIME_lv:   \"stateChangeResponseTime\",\n   TIMEOUT_lv:                      \"timeout\",\n   VALUE_lv:                        \"value\",\n   CMD4_STORAGE_lv:                 \"cmd4Storage\",\n\n   ERROR_STRING_MIN:               -151,\n   ERROR_TIMER_EXPIRED:            -151,\n   // ERROR_CMD_FAILED_REPLY:         -152,\n   ERROR_NULL_REPLY:               -153,\n   ERROR_NULL_STRING_REPLY:        -154,\n   ERROR_EMPTY_STRING_REPLY:       -155,\n   ERROR_2ND_NULL_STRING_REPLY:    -156,\n   ERROR_NON_CONVERTABLE_REPLY:    -157,\n   ERROR_NO_DATA_REPLY:            -158,\n   ERROR_STRING_MAX:               -158,\n   ERROR_STRINGS:\n   [ // cmd4Constants.ERROR_TIMER_EXPIRED -151\n     \"Timer expired contacting accessory\",\n     // cmd4Constants.ERROR_CMD_FAILED_REPLY -152\n     \"Command failed\",\n     // cmd4Constants.ERROR_NULL_REPLY -153\n     \"Reply is NULL\",\n     // cmd4Constants.ERROR_NULL_STRING_REPLY -154\n     \"Reply is NULL string\",\n     // cmd4Constants.ERROR_EMPTY_STRING_REPLY -155\n     \"Reply is an empty string\",\n     // cmd4Constants.ERROR_2ND_NULL_STRING_REPLY -156\n     \"Reply is still NULL\",\n     // cmd4Constants.ERROR_NON_CONVERTABLE_REPLY -157\n     \"Cannot convert characteristic string\",\n     // cmd4Constants.ERROR_NO_DATA_REPLY -158\n     \"No data returned from accessory\"\n   ],\n\n   // Convert our known Error Codes to strings\n   errorString: function( index )\n   {\n      let offset = - index + cmd4Constants.ERROR_STRING_MIN ;\n      let max = cmd4Constants.ERROR_STRING_MIN - cmd4Constants.ERROR_STRING_MAX;\n\n      //console.log(\" index is \" + index );\n      //console.log(\" offset is \" + offset );\n      //console.log(\" max is \" + max );\n      // i.e 0-7\n      if ( index == 0 )\n         return \"Device returned SUCCESS; \" + index;\n\n      //if ( offset < 0  || offset > max )\n      if ( index > cmd4Constants.ERROR_STRING_MIN )\n         return \"Device returned its own error; \" + index;\n      if ( index < cmd4Constants.ERROR_STRING_MAX )\n         return \"Device returned its own error; \" + index;\n\n      // Should not happen because of the above checks\n      if ( offset < 0 )\n         return \"Invalid Error min index: \" + index;\n\n      // Should not happen because of the above checks\n      if ( offset > max )\n         return \"Invalid Error max index: \" + index;\n\n      return cmd4Constants.ERROR_STRINGS[ offset ];\n   },\n\n\n\n   // Static Messages\n   DBUSY:                          \"Perhaps your device is busy or unavailable?\"\n};\nmodule.exports = cmd4Constants;\n"
  },
  {
    "path": "cmd4Settings.js",
    "content": "\"use strict\";\n//\n// This is the name of the platform that users will use to register\n// the plugin in the Homebridge config.json\n//\nexports.PLATFORM_NAME = \"Cmd4\";\n\n//\n// This *MUST* match the name of your plugin as defined the package.json\n//\nexports.PLUGIN_NAME = \"homebridge-cmd4\";\n\n// These must be global so that all characteristics are not\n// polled at the same time. Specifically a MyAir that has\n// multiple fans, switches and temperature sensors, all in\n// the same device of which a linkedAccessory is not an option.\n//exports.arrayOfAllStaggeredPollingCharacteristics = [ ];\nexports.listOfCreatedPriorityQueues = { };\n\n\n// By using our own Logger, we don't trigger others\nexports.cmd4Dbg = false;\n"
  },
  {
    "path": "commitlint.config.js",
    "content": "module.exports = {\n   extends: ['@commitlint/config-conventional'] ,\n   plugins: ['commitlint-plugin-function-rules'],\n   rules: {\n      'header-case': [ 0 ],\n      'body-max-line-length': [0],  // level: disabled\n      'function-rules/header-case': [\n         2, // level: error\n         'always',\n         () => {\n            // I do not care about case in header\n            return [true];\n         }\n      ],\n      'body-case': [ 0 ],\n      'function-rules/body-case': [\n         2, // level: error\n         'always',\n         () => {\n            // I do not care about case in body\n            return [true];\n         }\n      ],\n      'subject-case': [ 0 ],\n      'function-rules/subject-case': [\n         2, // level: error\n         'always',\n         () => {\n            // I do not care about case in subject\n            return [true];\n         }\n      ]\n   }\n};\n"
  },
  {
    "path": "docs/AdvancedTroubleShooting.md",
    "content": "# Homebridges-cmd4 - Advanced Trouble Shooting.\n\n## Table of Contents\n* [**About Advanced Trouble Shooting**](#about-advanced-trouble-shooting)\n* [**The #1 Thing to Remember**](#the-1-thing-to-remember)\n* [**The Parameters sent by Cmd4**](#the-parameters-sent-by-cmd4)\n* [**Troubleshooting your own scripts**](#troubleshooting-your-own-scripts)\n* [***Create a middleWare shell script***](#create-a-middleware-shell-script)\n* [**Debug mode is your best friend**](#debug-mode-is-your-best-friend)\n* [**Debugging Fakegato history**](#debugging-fakegato-history)\n* [**Missing icons**](#missing-icons)\n* [**Child process error message**](#child-process-error-message)\n* [**License**](#license)\n\n## About Advanced Trouble Shooting\n&nbsp;&nbsp;&nbsp; Unlike Basic Trouble Shooting, this guide is more for those who are having problems with their own scripts and what problems can arise when integrating them with Cmd4.\n\n## The #1 Thing to Remember\n&nbsp;&nbsp;&nbsp; Cmd4 runs your script in the background *WITHOUT ANY ENVIRONMENT* defined. Any variables, alias, special paths are not seen by your script so even if you run the script from the command line and it works, it may not from within Cmd4. Create a bash session without any environment set up like Cmd4 does with the command:<BR>\n\n```bash\n   *SHELL*> env -i bash --noprofile --norc\n```\n<BR>\n&nbsp;&nbsp;&nbsp; From within this environment test your script like:<BR>\n\n```bash\n   *SHELL*> node .homebridge/YourScriptHere.js Get My_Fan On\n```\n\n### The Parameters Sent by Cmd4\n&nbsp;&nbsp;&nbsp; The second most important thing to remember is what Cmd4 sends for Get/Set requests. Your script must meet these requirements. These are defined as:<BR>\n\n```\n   Get < Accessory Name > < Characteristic >\n   Set < Accessory Name > < Characteristic > < Value >\n```\n\n## Troubleshooting your own scripts\n\n### Execute your script from the command line interface for *Get*\n&nbsp;&nbsp;&nbsp; Remembering that Cmd4 executes your script in a No environment setting. First execute your scripts from the CLI.<BR>\n\n```bash\n*SHELL*> env -i bash --noprofile --norc\n*SHELL*> <your script path> Get < Accessory Name > < Characteristic >\n```\n<BR>\nThe script must output a one word answer or multiple quoted words.<BR>\nNote: Your script must also exit with a 0 return code.\n<BR>\n### Execute your script from the command line interface for *Set*\n&nbsp;&nbsp;&nbsp;Your script must respond to the Set command.<BR>\n\n```bash\n   *SHELL*> env -i bash --noprofile --norc\n   *SHELL*> <your script path> Set < Accessory Name > < Characteristic > < value >\n```\n<BR>\nNote: Your script must also exit with a 0 return code.\n\n### Debug mode is your best friend\n&nbsp;&nbsp;&nbsp; As with Basic Troubleshooting, if your script passes at the CLI, run homebridge in debug mode:<BR>\n&nbsp;&nbsp;&nbsp; New in Cmd4 v4.0.0 is how to enable Debug mode. The logs are 100% the same, except that now that Cmd4 has its own logging system ( Copied from Homebridge for compatability ); Enabling Debug logs will not enable Debug logs in other plugins. <BR>\n   There are two ways to enable Cmd4 Debug logs.\n\n#### Method 1.  Modifying the Cmd4 Platform section\n&nbsp;&nbsp;&nbsp; The Cmd4 Platform section can contain the enable Debug directive.\n\n```json\n   {\n      \"platform\": \"Cmd4\",\n      \"name\": \"Cmd4\",\n      \"debug\": true\n   }\n```\n\n#### Method 2.  Add DEBUG environental variable\n\n```bash\n   *SHELL*> DEBUG=Cmd4\n```\nNote: For Homebridge-config-ui-x, you only need to write Cmd4 in the Environmental variable section.\n\n\n### Create a middleWare shell script\n&nbsp;&nbsp;&nbsp; To see when and what both Cmd4 is sending/receiving as well as what your script is sending and receiving, create a middleWare.sh script that is called from the config.json and then calls your script. A script similiar to:<BR>\n\n```\n#!/bin/bash\necho $( date ) >> /tmp/Cmd4.log\necho $* >> /tmp/Cmd4.log\nnode .homebridge/Cmd4Scripts/State.js $* 2>&1 | tee -a /tmp/Cmd4.log\n```\n\nRunning a \"tail -f /tmp/Cmd4.log\" in a seperate terminal window will show you everything that is going on between the processes.\n<BR>\n\n\n## Debugging Fakegato history\nSee [fakegato-history](https://github.com/simont77/fakegato-history)\n\n&nbsp;&nbsp;&nbsp; if you have added fakegato history, but no history is showing, there are things you can check.\n\n### Step 1.  Check that the characteristic is polled.\n&nbsp;&nbsp;&nbsp; Only polled characteristics are recorded. For history to be collected you will have to enable polling and interval for the accessory, and according to the fakegato-history documents it should be less than 10 minutes (600 seconds). The new polling config section allows for each characteristic to be polled at their individual times. Check your config.json for this setup. An example of polling is:\n```json\n\"polling\": [{\"characteristic\": \"currentHeatingCoolingState\",\n             \"interval\": 540,  \"timeout\": 4000},\n            {\"characteristic\": \"currentTemperature\",\n             \"interval\": 60,   \"timeout\": 4000}\n           ],\n```\n\n### Step 2.  Check the fakegato logs.\n&nbsp;&nbsp;&nbsp; The storagePath stores the history records. If there are no logs, run Cmd4 in Debug mode to see if the records are being created.\n\n### Step 3.  Check your fakegato configuration.\n&nbsp;&nbsp;&nbsp; In the following configuration, the value polled for the characteristic \"currentTemperature\" will be used for the designation \"currentTemp\".  Similarly the value polled for the characteristic \"targetTemperature\" will be used for the designation \"setTemp\". This follows the fakegato-history spec and this model is used for the other fakegato-history records.\n\n```json\n\"fakegato\":{\"eve\":\"thermo\",\n            \"currentTemp\": \"currentTemperature\",\n            \"setTemp\": \"targetTemperature\",\n            \"valvePosition\": \"0\",\n            \"storage\": \"fs\",\n            \"storagePath\": \".homebridge/FakegatoStorage\",\n            \"folder\": \"folderName\",\n            \"keyPath\": \"/place/to/store/my/keys/\"\n           }\n```\n\nNote: The value \"0\" should be used for any characteristics value which is not possible to retrieve.\n\n## Missing icons\n&nbsp;&nbsp;&nbsp;IOS 14 added a new category characteristic to give a hint to any GUI of which icon to use. The big impact was found in missing icons for Televisions. For Televisions you must add:<BR>\n\n```json\n\"category\": \"TELEVISION\"\n```\nThis category only takes effect for Platform Accessories.\n\n\n## Child process error message\n&nbsp;&nbsp;&nbsp; If you happen to see this error message:<BR>\n```\n  Error: Command failed: /homebridge/Server.sh Get 'Server' 'On'\n\n    at ChildProcess.exithandler (child_process.js:297:12)\n    at ChildProcess.emit (events.js:193:13)\n    at maybeClose (internal/child_process.js:1001:16)\n    at Process.ChildProcess._handle.onexit (internal/child_process.js:266:5)\n  killed: true\n  code: null\n  signal: SIGTERM,\n  cmd: \"/homebridge/Server.sh Get Server On\"\n\n  ```\n\nThe command may not exist, but also the timeout value in your config.json for that accessory may be too low.\n\n\n## License\nSee [LICENSE](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/LICENSE)\n\n\n\n<!---\nLink References (Not Local)\n-->\n\n[homebridge]:https://github.com/nfarina/homebridge\n[ztalbot2000]:https://github.com/ztalbot2000\n"
  },
  {
    "path": "docs/Developers.md",
    "content": "# Homebridges-cmd4 - Cmd4 Developers Guide.\n<base _target=\"_self\">\n\n\n## Table of Contents\n* [**About CMD4 Developers Guide**](#about-cmd4-developers-guide)\n* [**Where to Begin**](#where-to-begin)\n* [**Homebridge API**](#homebridge-api)\n* [**Platform Accessories**](#platform-accessories)\n* [**Television Accessories**](#television-accessories)\n* [**Cmd4 Directives**](#cmd4-directives)\n* [**Cmd4 Devices and Characteristics**](#cmd4-devices-and-characteristics)\n* [**Priority Queued Polling**](#priority-queued-polling)\n* [**Developer Notes**](#developer-notes)\n* [**Adding in Fakegato history**](#adding-in-fakegato-history)\n* [**Unit Testing**](#unit-testing)\n* [**License**](#license)\n\n## About CMD4 Developers Guide\n&nbsp;&nbsp;&nbsp; This document will help you understand what is needed to integrate your own scripts into Cmd4.\n\n## Where to begin\n&nbsp;&nbsp;&nbsp; Cmd4 comes with a fully populated and documented [**config.json**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/Extras/config.json) file, this Developers Guide, an [Advanced](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/AdvancedTroubleShooting.md) troubleshoting guide for you the script writer and finally some auto generated device and characteristic description documentation [https://ztalbot2000.github.io/homebridge-cmd4](https://ztalbot2000.github.io/homebridge-cmd4/#).<BR>\n\n&nbsp;&nbsp;&nbsp; Next you should look at scripts that might already exist. Within the Cmd4 directory structure there is a path of \"Extras/Cmd4Scripts/ExampleScripts\" that may already exist for you as a starting point.<BR>\n* [**basic_ping.sh**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/Extras/Cmd4Scripts/Examples/basic_ping.sh)\n* [**advanced_ping.sh**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/Extras/Cmd4Scripts/Examples/advanced_ping.sh)\n* [**wakeonlan.sh**](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/Extras/Cmd4Scripts/Examples/wakeonlan.sh)\n* [**homebridge-cmd4-AdvantageAir**](https://github.com/mitch7391/homebridge-cmd4-AdvantageAir/blob/master/AdvAir.sh)\n* [**cmd4-HisenseTV**](https://github.com/mitch7391/cmd4-HisenseTV/blob/main/HisenseTV.sh)   \n\n## Homebridge API\n&nbsp;&nbsp;&nbsp; Cmd4 is not possible without Homebridge. As of Cmd4 Version >= 8, Cmd4 only follows the Platform template definition as dictated by Homebridge. See: [deprecated templates](https://developers.homebridge.io/#/). This was everyone anyway and makes homebridge-ui easier to implement for Cmd4..<BR>\n\n\n## Platform Accessories\n&nbsp;&nbsp;&nbsp; An example Cmd4 Platform accessory for a Homebridge Television as described by: [Homebridge Television](https://developers.homebridge.io/#/service/Television) is:\n\n```json\n{\n   \"bridge\":\n   {\n      \"name\": \"MAC Test Homebridge\",\n      \"username\": \"CC:22:3D:E3:CE:30\",\n      \"port\": 51826,\n      \"pin\": \"555-55-555\"\n   },\n   \"platforms\" :\n   [\n      {\n         \"platform\": \"Cmd4\",\n         \"debug\":                          false,\n         \"outputConstants\":                false,\n         \"accessories\" :\n         [\n            {\n              \"type\":                      \"Television\",\n              \"category\":                  \"TELEVISION\",\n              \"publishExternally\":         true,\n              \"name\":                      \"Example TV\",\n              \"active\":                    \"ACTIVE\",\n              \"activeIdentifier\":           1,\n              \"configuredName\":            \"Example TV\",\n              \"sleepDiscoveryMode\":        \"ALWAYS_DISCOVERABLE\",\n              \"accessories\":\n              [\n                 {   \"type\":                   \"TelevisionSpeaker\",\n                     \"displayName\":            \"My_TelevisionSpeaker\",\n                     \"name\":                   \"My_TelevisionSpeaker\",\n                     \"active\":                 \"ENABLED\",\n                     \"volumeSelector\":         10,\n                     \"volumeControlType\":      \"ABSOLUTE\",\n                     \"state_cmd\": \"node .homebridge/YourScriptHere.js\",\n                     \"polling\": [\n                        {\"characteristic\": \"active\",         \"interval\": 50,  \"timeout\": 5000},\n                        {\"characteristic\": \"volumeSelector\", \"interval\": 50,  \"timeout\": 5000}\n                     ]\n                  }\n              ],\n              \"LinkedTypes\":\n              [\n                 {\"type\":                   \"InputSource\",\n                  \"displayName\":            \"HDMI1\",\n                  \"configuredName\":         \"HDMI 1\",\n                  \"currentVisibilityState\": \"SHOWN\",\n                  \"inputSourceType\":        \"HDMI\",\n                  \"isConfigured\":           \"CONFIGURED\",\n                  \"identifier\":              1,\n                  \"targetVisibilityState\":    \"SHOWN\",\n                  \"name\":                     \"HDMI 1\"\n                 },\n                 {\"type\":                    \"InputSource\",\n                  \"displayName\":             \"HDMI 2\",\n                   \"configuredName\":         \"HDMI 2\",\n                   \"currentVisibilityState\": \"SHOWN\",\n                   \"inputSourceType\":        \"HDMI\",\n                   \"isConfigured\":           \"CONFIGURED\",\n                   \"identifier\":              2,\n                   \"targetVisibilityState\":   \"SHOWN\",\n                   \"name\":                    \"HDMI 2\"\n                  },\n                  {\"type\":                    \"InputSource\",\n                   \"displayName\":             \"Netflix\",\n                   \"configuredName\":          \"Netflix\",\n                   \"currentVisibilityState\":  \"SHOWN\",\n                   \"inputSourceType\":         \"HDMI\",\n                   \"isConfigured\":            \"CONFIGURED\",\n                   \"identifier\":               3,\n                   \"targetVisibilityState\":    \"SHOWN\",\n                   \"name\":                     \"Netflix\"\n                  }\n               ],\n               \"displayOrder\":              0,\n               \"currentMediaState\":         \"STOP\",\n               \"targetMediaState\":          \"STOP\",\n               \"pictureMode\":               \"STANDARD\",\n               \"remoteKey\":                 \"SELECT\",\n               \"polling\": [\n                  {\"characteristic\": \"active\",            \"interval\": 50,  \"timeout\": 5000},\n                  {\"characteristic\": \"activeIdentifier\",  \"interval\": 50,  \"timeout\": 5000},\n                  {\"characteristic\": \"currentMediaState\", \"interval\": 540, \"timeout\": 5000}\n               ],\n               \"stateChangeResponseTime\":    3,\n               \"state_cmd\": \"node .homebridge/YourScriptHere.js\"\n             }\n          ]\n       }\n   ]\n}\n```\n\n### Television Accessories\n&nbsp;&nbsp;&nbsp;There are a few special Cmd4 designations for Televisions, implemented since Cmd4 3.0\n<UL>\n<LI> The first is \"category\"<BR>\n\n```json\n   \"category\": \"TELEVISION\"\n```\n\nThis is the hint to homekit of which icon to use and for Televisions, a TV icon will not show without it.\n<BR><BR>\n<LI>The second new designation is \"publishExternally\"<BR>\n\n```json\n   \"publishExternally\": true (Default is false)\n```\nAs per the Homebridge API, this allows the Platform Accessory to be published separately from the bridge and is a requirement for multiple TV's.\n</UL>\n\nSee the [Cmd4 Developers Guide](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/Developers.md) for further information.\n\n\n## Cmd4 Directives\n\n&nbsp;&nbsp;&nbsp; Homebridge-Cmd4 has many directives, the most important being the \"state_cmd\". The provided config.min.json file shows many of the directives in action. A complete list of all Cmd4 directives can be found in the auto generated Cmd4 documentation found at :[https://ztalbot2000.github.io/homebridge-cmd4](https://ztalbot2000.github.io/homebridge-cmd4).\n\n## Cmd4 Devices and Characteristics\n\n&nbsp;&nbsp;&nbsp; Homebridge-Cmd4 supports 62 Devices and over 200 Characteristics which are described in the previously mentioned config.min.json file and on the  auto generated github pages at: [https://ztalbot2000.github.io/homebridge-cmd4](https://ztalbot2000.github.io/homebridge-cmd4).\n\n## Priority Queued Polling\n\n&nbsp;&nbsp;&nbsp; Typically polling is pretty much a free for all.  While Cmd4 tries to eleviate this with staggered polling, Cmd4 supports two kinds of Priority Queued Polling; that being \"Sequential\" and \"WoRm\" ( Write Once Read Many).  If configured correctly, only one Set characteristic value can be sent or either one or multiple Gets from a device at a time. The priority given to requests from IOS first and background polling second.<BR>\n<BR>\n  Priority Queued Polling is only available when a queue is defined. The default \"QueueType\" being \"WoRm\". To configure Priority Queued Polling every characteristic to the device must be configured to be in the same queue.<BR>\n  The retries defaults to zero for \"Get\" commands from homebridge. You can alter this value as you like.<BR>\nFor Example of the default WoRm is:\n\n```json\n\"queueTypes\": [ { \"queue\": \"A\", \"queueType\": \"WoRm\", \"retries\": 0 } ],\n\"accessories\": [\n{\n   \"interval\": 5,\n   \"queue:    \"A\",\n   \"polling\": [ { \"characteristic\": \"currentTemperature\"  },\n                { \"characteristic\": \"targetTemperature\", \"interval\": 15 }\n              ]\n}\n```\n  The interval of the characteristic is defined through the heirarch of the Platform/Accessory and then the Characteristic, as always.<BR>\nExample 2:\n\n```json\n\"platforms\":\n [ { \"platform\": \"Cmd4\",\n     \"interval\": \"10\",\n     \"queueTypes: [ { \"queue\": \"A\" : \"queueType\": \"WoRm\" }\n                    { \"queue\": \"B\" : \"queueType\": \"Sequential\" }\n                    { \"queue\": \"C\" } // Defaults to \"WoRm\"\n                  ],\n     \"accessories\": [\n     {\n        \"name\": \"My_Thermostat\",\n        \"type\": \"Thermostatwitch\",\n        \"interval\": 15,\n        \"queue\": \"A\",\n        \"polling\": [ { \"characteristic\": \"currentTemperature\" },\n                     { \"characteristic\": \"targetTemperature\" },\n                     { \"characteristic\": \"currentHeatingCoolingState\", \"interval\": 25 }\n                   ],\n        ...\n     },\n     {\n        \"name\": \"My_Switch\",\n        \"type\": \"Switch\",\n        \"queue\": \"B\",\n        \"polling\": [ { \"characteristic\": \"On\" } ],\n        ...\n     },\n     {\n        \"name\": \"My_Door\",\n        \"type\": \"Door\",\n        \"queue\": \"C\",\n        \"polling\": true,\n        ...\n     },\n     {\n        \"name\": \"Switch2\",\n        \"type\": \"Switch\",\n        \"queue\": \"D\", // Defaults to WoRm\n        \"polling\": [ { \"characteristic\": \"on\" } ],\n        ...\n     }\n\n```\n<BR>\n\n\n## Priority Queue Polling Across Multiple accessories ( Same Device )\n&nbsp;&nbsp;&nbsp; In the case of a device like the My Air Smart Thermostat which has multiple accessories of Switches, Sensors and a Thermostat; Cmd4 Priority Queued Polling is essential. This device is actually why this feature was created. There was previously no possible configuration of Cmd4 staggered polling that would not result in the device locking up as it was hammered with requests at the same time. An example of configuring Cmd4 for this device is:\n```json\n    \"platforms\": [\n        {\n            \"platform\": \"Cmd4\",\n            \"debug\": false,\n            \"outputConstants\": false,\n            \"timeout\": 4000,\n            \"stateChangeResponseTime\": 3,\n            \"queueTypes:[ { \"queue\": \"A\", \"queueType\": \"WoRm\" } ],\n            \"accessories\": [\n                {\n                    \"type\": \"TemperatureSensor\",\n                    \"subType\": \"tempSensor1\",\n                    \"displayName\": \"LRoom\",\n                    \"name\": \"LRoom\",\n                    \"currentTemperature\": 25,\n                    \"statusFault\": \"NO_FAULT\",\n                    \"manufacturer\": \"Advantage Air Australia\",\n                    \"model\": \"e-zone\",\n                    \"serialNumber\": \"Fujitsu e-zone2\",\n                    \"queue\": \"A\",\n                    \"polling\": [\n                        { \"characteristic\": \"currentTemperature\" }\n                    ],\n                    \"props\": {\n                        \"currentTemperature\": {\n                            \"maxValue\": 100,\n                            \"minValue\": -100,\n                            \"minStep\": 0.1\n                        }\n                    },\n                    \"state_cmd\": \"bash /home/pi/zones.sh\",\n                    \"state_cmd_suffix\": \"z01\"\n                },\n                {\n                    \"type\": \"Switch\",\n                    \"displayName\": \"TSwitch\",\n                    \"name\": \"TSwitch\",\n                    \"on\": \"FALSE\",\n                    \"manufacturer\": \"Advantage Air Australia\",\n                    \"model\": \"e-zone\",\n                    \"serialNumber\": \"Fujitsu e-zone2\",\n                    \"queue\": \"A\",\n                    \"polling\": [\n                        { \"characteristic\": \"On\" }\n                    ],\n                    \"state_cmd\": \"bash /home/pi/zones.sh\",\n                    \"state_cmd_suffix\": \"z05\"\n                },\n                {\n                    \"type\": \"Fan\",\n                    \"on\": \"FALSE\",\n                    \"displayName\": \"Fan\",\n                    \"name\": \"Fan\",\n                    \"manufacturer\": \"Advantage Air Australia\",\n                    \"model\": \"e-zone\",\n                    \"serialNumber\": \"Fujitsu e-zone2\",\n                    \"queue\": \"A\",\n                    \"polling\": [\n                        { \"characteristic\": \"on\" }\n                    ],\n                    \"stateChangeResponseTime\": 1,\n                    \"state_cmd\": \"bash /home/pi/ezone.sh\"\n                },\n                {\n                    \"type\": \"Thermostat\",\n                    \"displayName\": \"Aircon\",\n                    \"name\": \"Aircon\",\n                    \"currentHeatingCoolingState\": \"OFF\",\n                    \"targetHeatingCoolingState\": \"OFF\",\n                    \"currentTemperature\": 25,\n                    \"targetTemperature\": 25,\n                    \"temperatureDisplayUnits\": \"CELSIUS\",\n                    \"manufacturer\": \"Advantage Air Australia\",\n                    \"model\": \"e-zone\",\n                    \"serialNumber\": \"Fujitsu e-zone2\",\n                    \"queue\": \"A\",  // All characteristics would go to queue \"A\"\n                    \"polling\": [\n                        { \"characteristic\": \"currentHeatingCoolingState\" },\n                        { \"characteristic\": \"targetHeatingCoolingState\" },\n                        { \"characteristic\": \"currentTemperature\" },\n                        { \"characteristic\": \"targetTemperature\" }\n                    ],\n                    \"state_cmd\": \"bash /home/pi/ezone.sh\"\n                }\n            ]\n        }\n    ]\n}\n```\n\n\n## Developer Notes\n### Step 1.  The provided jsmin differs from others\n&nbsp;&nbsp;&nbsp; The resulting file is still readable. Only C and C++ comments are removed. The included config.json is created via:\n\n```bash\n   *SHELL*> gcc jsmin.c -o jsmin\n   *SHELL*> jsmin < config.min.json > config.json\n```\n\n### Step 2.  The parameters to the state_cmd\n&nbsp;&nbsp;&nbsp; These are defined as:<BR>\n\n```\n   Get < Accessory Name > < Characteristic >\n   Set < Accessory Name > < Characteristic > < Value >\n```\n\n### Step 3.  Polling is supported\n&nbsp;&nbsp;&nbsp; Even if you do not use polling, care was taken that all Set Target states are immediately followed by a Get of the Current state. This is so that after closing a garage door for instance, Homekit gets updated that the door was closed.\n\n### Step 4.  Sending constants to your script.\n&nbsp;&nbsp;&nbsp; By placing in your config.json file the tag \"outputConstants\": true, instead of values, your script will receive constants instead of values (Where Applicable). Homebridge-Cmd4 will except constants or values as input.  See the config.min.json file for the defined constants.\n\n### Step 5. Changing characteristic properties.\n&nbsp;&nbsp;&nbsp; Cmd4 will allow you to change a characteristics property range, However the HomeKit GUI will most likely ignore it. The change is for those who create their own GUI's. For Example:\n```json\n    \"platforms\": [\n        {\n            \"platform\": \"Cmd4\",\n            \"debug\": false,\n            \"outputConstants\": false,\n            \"timeout\": 4000,\n            \"stateChangeResponseTime\": 3,\n            \"accessories\": [\n                {\n                    \"type\": \"Thermostat\",\n                    \"displayName\": \"MyThermostat\",\n                    \"name\": \"MyThermostat\",\n                    \"currentTemperature\": 25,\n                    \"targetTemperature\": 25,\n                    \"props\": {\n                        \"currentTemperature\": {\n                            \"maxValue\": 32,\n                            \"minValue\": 16,\n                            \"minStep\": 1\n                        },\n                        \"targetTemperature\": {\n                            \"maxValue\": 32,\n                            \"minValue\": 16,\n                            \"minStep\": 1\n                        }\n                    }\n                }\n            ]\n        }\n    ]\n}\n```\n\n\n***Important***\n&nbsp;&nbsp;&nbsp; Homebridge-cmd4 just outputs the value to be set.  For whatever reason the lower layers of homebridge set on/off to be \"true\" and \"false\" instead of 0 & 1, which is incorrect, but changing it would break others scripts.\n&nbsp;&nbsp;&nbsp;  Homebridge-cmd4 has always recognized either 0/1 or true/false when receiving the devices value.\nWhen in doubt, check the parameters yourself.\nThanks Florian for pointing out the original documented bash script was incorrect\n\n&nbsp;&nbsp;&nbsp; Your now ready to go and try Fans, Switches, Garage Doors, Locks, Sensors ... ✅\n\n<DIV id=\"fakegatotag\"></DIV>\n\n## Adding in Fakegato history\nSee [fakegato-history](https://github.com/simont77/fakegato-history)\n\n&nbsp;&nbsp;&nbsp; Not all accessories are supported by Eve or fakegato-history. As more and more are, they can easily be added to Homebridge-Cmd4 if they are not already by following these step.\n\n### Step 1.  Add fakegato config information\n&nbsp;&nbsp;&nbsp; Edit your homebridge/config.json file and add to the accessory config portion the following lines:\n\n```json\n\"fakegato\":{\"eve\":\"thermo\",\n            \"currentTemp\": \"currentTemperature\",\n            \"setTemp\": \"targetTemperature\",\n            \"valvePosition\": \"0\",\n            \"storage\": \"fs\",\n            \"storagePath\": \".homebridge/FakegatoStorage\",\n            \"folder\": \"folderName\",\n            \"keyPath\": \"/place/to/store/my/keys/\"\n           }\n```\n\n### Step 2.  Fakegato parameters\n&nbsp;&nbsp;&nbsp; If you notice, the parameters follow the fakegato-history spec.\n\nThe only difference is that the characteristics value will be substituted for the fakegato keys. In this example \"currentTemperature\" will be substituted with 50.0 if that is what was returned to Cmd4.\n\nThe value \"0\" should be used for any characteristics value which is not possible to retrieve.\n\n### Step 3.  History requires polling\n&nbsp;&nbsp;&nbsp; For history to be collected you will have to enable polling and interval for the accessory, and according to the fakegato-history documents it should be less than 10 minutes (600 seconds). The new polling config section allows for each characteristic to be polled at their individual times.\n\n```json\n\"polling\": [{\"characteristic\": \"currentHeatingCoolingState\",\n             \"interval\": 540,  \"timeout\": 4000},\n            {\"characteristic\": \"currentTemperature\",\n             \"interval\": 60,   \"timeout\": 4000}\n           ],\n```\n\n## Unit Testing\n&nbsp;&nbsp;&nbsp; Unit testing is done using the Mocha framework for Javascript and was introduced in homebridge-cmd4 version 2.1.2. There are 11708 test cases and they all run successfully.  They test the homebridge-Cmd4 module to make sure that all characteristics, services and names are correct. The provided config.json is also tested for proper definitions of all the homebridge-cmd4 config parameters.\n\n&nbsp;&nbsp;&nbsp; Unit testing is only possible in a development environment and can be achieved in the following manner.\n\n### Step 1.  Install homebridge-cmd4 in a local environment\n&nbsp;&nbsp;&nbsp; This is done separate from the global environment and does not impact the global environment.\n\n```bash\n   *SHELL*> npm install homebridge-cmd4\n```\n\n### Step 2.  Change to the homebridge-cmd4 directory\n\n```bash\n   *SHELL*> cd homebridge-cmd4\n```\n\n### Step 3.  Install homebridge-cmd4 development dependencies\n\n```bash\n   *SHELL*> npm install --dev\n```\n\n### Step 4.  Run the provided test cases\n\n```bash\n   *SHELL*> npm test\n```\n\nNote: There is one bug where the testcases do not run correctly every second attempt.  It has something to do with synchronous tests for Get/Set.  Please ignore it at this time.  Just run it again.\n\n## License\nSee [LICENSE](https://github.com/ztalbot2000/homebridge-cmd4/blob/master/LICENSE)\n\n\n\n<!---\nLink References (Not Local)\n-->\n\n[homebridge]:https://github.com/nfarina/homebridge\n[homebridge_api]:https://developers.homebridge.io/#/\n[ztalbot2000]:https://github.com/ztalbot2000\n"
  },
  {
    "path": "docs/autoGenerated/CMD4_AccessoryDescriptions.html",
    "content": "<!DOCTYPE HTML>\n<HTML LANG=\"en\">\n<HEAD>\n<META CHARSET=\"utf-8\">\n<META NAME=\"viewport\" CONTENT=\"width=device-width, initial-scale=1\">\n<!-- Needed for unicode fa-caret-down -->\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css\">\n<META NAME=\"robots\" CONTENT=\"index,follow\">\n<META NAME=\"Description\" CONTENT=\"CMD4 Characteristics.\">\n<META PROPERTY=\"og:url\" CONTENT=\"https://github.com/ztalbot2000/homebridge-cmd4/docs/autoGenerated/CMD4_AccessoryDescriptions.html\">\n\n<TITLE>CMD4 Devices</TITLE>\n<META NAME=\"viewport\" CONTENT=\"width=device-width, initial-scale=1\">\n<STYLE>\n\n/* Fallback styling */\nBODY {\n   font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;\n   font-size: 1rem;\n   font-weight: 400;\n   line-height: 1.5;\n   color: #252930;          /* blackish */\n   text-align: left;\n   background-color: white;\n}\n\n/* Common styling used inline */\n.fixed-bottom, .fixed-top {\n   POSITION: fixed;\n   LEFT: 0;\n   z-index: 1030;\n   background-color: white;\n}\n.fixed-top {\n   TOP: 0;\n}\n.position-relative {\n   position: relative;\n}\n.float-left {\n   float: left;\n}\n.flex {\n   display: flex;\n}\n.align-items-center {\n   align-items: center;\n}\n\n\n.header {\n   /* The header div goes all across the top */\n   WIDTH: 100%;\n   box-shadow: 0 1px 4px 0 rgba(0,0,0,.1);\n}\n\n/* This houses the Logo */\n.container-fluid {\n   width: 100%;\n   padding-right:15px;\n   padding-left:15px;\n   margin-right:auto;\n   margin-left:auto;\n}\n\n\n.site-logo {\n  box-shadow: 0 1px 4px 0 rgba(0,0,0,.1);\n  BACKGROUND: white;\n  display: inline-block;\n}\n.site-text {\n  BACKGROUND: white;\n  position: relative;\n  display: inline-block;\n  transform: translate( 0, 25% );\n}\n\n.nav-link:before {\n   background-color: #fbf5ff;\n   content: \" \";\n   display: inline-block;\n   height: inherit;\n   left: 0;\n   margin-top: -.5rem;\n   position: absolute;\n   width: 3px;\n   height: 100%;\n   border-radius: 1rem;\n}\n\n/* Fixed sidenav */\n.sidenav\n{\n  WIDTH: 130px;\n  POSITION: fixed;\n  Z-INDEX: 1;\n  MARGIN-LEFT: 10px;\n  /* Must be below Logo */\n  MARGIN-TOP: 50px;\n  BACKGROUND: #eee;\n  OVERFLOW-X: hidden;\n  OVERFLOW-Y: auto;\n  max-height: calc( 100vh - 9rem);\n}\n\n/* Style the sidenav links and the dropdown button */\n.sidenav a, .dropdown-btn, .accordion {\n  PADDING: 6px 8px 6px 16px;  /* Top, Right, Bottom,Left */\n  TEXT-DECORATION: none;\n  FONT: 10.5px Poppins;\n  COLOR: #4b5465;           /* Blueish Gray */\n  DISPLAY: block;\n  -webkit-text-stroke: #4b546;\n  TEXT-ALIGN: left;\n  CURSOR: pointer;\n  OUTLINE: none;\n  BACKGROUND: none;\n  /* Border around button */\n  BORDER: none;\n}\n\n/* On mouse-over */\n.sidenav a:hover, .dropdown-btn: hover, .accordion: hover\n{\n  COLOR: #064579;   /* darker blue */\n}\n\n.accordion\n{\n  transition: 0.4s;\n}\n\n/* accordion type divs */\n.panel {\n  padding: 0 0px;\n  display: none;\n  background-color: white;\n  overflow: hidden;\n}\n\n.main {\n  MARGIN-LEFT: 148px; /* Same width as the sidebar + left position in px */\n  PADDING: 55px 10px; /* Top, Right, Bottom, Left */\n}\n\n/* Div within main, holding page information */\n/* This is also used to hide all the sections at startup */\n.section {\n  display: none; /* initially hidden */\n}\n\n/* Common paragraph sytling */\nh1 {\n   FONT-SIZE: 2.5rem;\n   padding-top: 4rem;\n}\nh2 {\n   FONT-SIZE: 1.5rem;\n}\nh1, h2, h3, h4, h5 {\n  COLOR: #252930;\n  FONT-WEIGHT: 600;\n}\nh1, h2, h3, h4, h5, note, p {\n   FONT-FAMILY: Poppins,sans-serif;\n   MARGIN-TOP: 0;\n   MARGIN-BOTTOM: .5rem;\n   font-weight: 500;\n   line-height: 1.2;\n}\nnote {\n   FONT-STYLE: italic;\n   FONT-SIZE: 1rem;\n   COLOR: #5d6778;   /* blue-ish gray */\n   PADDING: 2rem;\n}\n\n\n/* Table styling */\ntable {\n   display: table;\n   border-collapse: collapse;\n   -webkit-border-horizontal-spacing: 2px;\n   -webkit-border-vertical-spacing: 2px;\n   width: 100%;\n   margin-bottom: 1rem;\n}\nth {\n   FONT-WEIGHT: bold;\n   border: 1px solid #e7e9ed;\n   text-align: center;\n}\ntd {\n   padding: .75rem;\n   vertical-align: top;\n   border-top: 1px solid #e7e9ed;\n   FONT-WEIGHT: normal;\n}\ntr:nth-child(even) { background-color: #f2f2f2 }  /* off white */\n\nblock-warning a {\n   color: #d09c13;     /* Orange-ish */\n}\n\n/* Add an active class to the active dropdown button */\n.active, .accordion: hover {\n\n  /* The background color of the active buttons */\n  background-color: #ccc;   /* light gray */\n\n  /* The width of item is the width of the div */\n  /* Otherwise buttons appear half blocked */\n  width: 100%;\n}\n\n/* Optional: Style the caret down icon */\n.fa-caret-down {\n  float: right;\n}\n\n/* Apply box-sizing to everything */\n* {\n   box-sizing: border-box;\n}\n\n/* Some media queries for responsiveness */\n@media screen and (max-height: 450px) {\n  .sidenav {PADDING-TOP: 15px;}\n  .sidenav a {FONT-SIZE: 12px;}  /* height of items in accordion dropdown */\n}\n</STYLE>\n</HEAD>\n<BODY>\n<HEADER class=\"header fixed-top\">\n   <div class=\"container-fluid position-relative\">\n      <div class=\"site-logo\">\n         <img class=\"float-left\" src=\"assets/images/Cmd4_icon.svg\" width=\"40px\" alt=\"logo\">\n         <div class=\"site-text\">\n            Cmd4\n         </DIV>   <!-- site-text -->\n      </DIV>   <!-- site-logo -->\n   </DIV>   <!-- container-fluid -->\n</HEADER>\n<div class=\"content\">\n   <div class=\"sidenav\">\n      <button class=\"accordion\">Devices\n         <i class=\"fa fa-caret-down\"></i>\n      </button>\n      <div class=\"panel\">\n         <a href=\"#AccessCode\" onclick=\"toggleVisibility( 'AccessCode');\">AccessCode</a>\n         <a href=\"#AccessControl\" onclick=\"toggleVisibility( 'AccessControl');\">AccessControl</a>\n         <a href=\"#AccessoryInformation\" onclick=\"toggleVisibility( 'AccessoryInformation');\">AccessoryInformation</a>\n         <a href=\"#AccessoryMetrics\" onclick=\"toggleVisibility( 'AccessoryMetrics');\">AccessoryMetrics</a>\n         <a href=\"#AccessoryRuntimeInformation\" onclick=\"toggleVisibility( 'AccessoryRuntimeInformation');\">AccessoryRuntimeInformation</a>\n         <a href=\"#AirPurifier\" onclick=\"toggleVisibility( 'AirPurifier');\">AirPurifier</a>\n         <a href=\"#AirQualitySensor\" onclick=\"toggleVisibility( 'AirQualitySensor');\">AirQualitySensor</a>\n         <a href=\"#AssetUpdate\" onclick=\"toggleVisibility( 'AssetUpdate');\">AssetUpdate</a>\n         <a href=\"#Assistant\" onclick=\"toggleVisibility( 'Assistant');\">Assistant</a>\n         <a href=\"#AudioStreamManagement\" onclick=\"toggleVisibility( 'AudioStreamManagement');\">AudioStreamManagement</a>\n         <a href=\"#Battery\" onclick=\"toggleVisibility( 'Battery');\">Battery</a>\n         <a href=\"#BatteryService\" onclick=\"toggleVisibility( 'BatteryService');\">BatteryService</a>\n         <a href=\"#CameraEventRecordingManagement\" onclick=\"toggleVisibility( 'CameraEventRecordingManagement');\">CameraEventRecordingManagement</a>\n         <a href=\"#CameraOperatingMode\" onclick=\"toggleVisibility( 'CameraOperatingMode');\">CameraOperatingMode</a>\n         <a href=\"#CameraRTPStreamManagement\" onclick=\"toggleVisibility( 'CameraRTPStreamManagement');\">CameraRTPStreamManagement</a>\n         <a href=\"#CameraRecordingManagement\" onclick=\"toggleVisibility( 'CameraRecordingManagement');\">CameraRecordingManagement</a>\n         <a href=\"#CarbonDioxideSensor\" onclick=\"toggleVisibility( 'CarbonDioxideSensor');\">CarbonDioxideSensor</a>\n         <a href=\"#CarbonMonoxideSensor\" onclick=\"toggleVisibility( 'CarbonMonoxideSensor');\">CarbonMonoxideSensor</a>\n         <a href=\"#CloudRelay\" onclick=\"toggleVisibility( 'CloudRelay');\">CloudRelay</a>\n         <a href=\"#ContactSensor\" onclick=\"toggleVisibility( 'ContactSensor');\">ContactSensor</a>\n         <a href=\"#DataStreamTransportManagement\" onclick=\"toggleVisibility( 'DataStreamTransportManagement');\">DataStreamTransportManagement</a>\n         <a href=\"#Diagnostics\" onclick=\"toggleVisibility( 'Diagnostics');\">Diagnostics</a>\n         <a href=\"#Door\" onclick=\"toggleVisibility( 'Door');\">Door</a>\n         <a href=\"#DoorBell\" onclick=\"toggleVisibility( 'DoorBell');\">DoorBell</a>\n         <a href=\"#Fan\" onclick=\"toggleVisibility( 'Fan');\">Fan</a>\n         <a href=\"#Fanv1\" onclick=\"toggleVisibility( 'Fanv1');\">Fanv1</a>\n         <a href=\"#Fanv2\" onclick=\"toggleVisibility( 'Fanv2');\">Fanv2</a>\n         <a href=\"#Faucet\" onclick=\"toggleVisibility( 'Faucet');\">Faucet</a>\n         <a href=\"#FilterMaintenance\" onclick=\"toggleVisibility( 'FilterMaintenance');\">FilterMaintenance</a>\n         <a href=\"#FirmwareUpdate\" onclick=\"toggleVisibility( 'FirmwareUpdate');\">FirmwareUpdate</a>\n         <a href=\"#GarageDoorOpener\" onclick=\"toggleVisibility( 'GarageDoorOpener');\">GarageDoorOpener</a>\n         <a href=\"#HeaterCooler\" onclick=\"toggleVisibility( 'HeaterCooler');\">HeaterCooler</a>\n         <a href=\"#HumidifierDehumidifier\" onclick=\"toggleVisibility( 'HumidifierDehumidifier');\">HumidifierDehumidifier</a>\n         <a href=\"#HumiditySensor\" onclick=\"toggleVisibility( 'HumiditySensor');\">HumiditySensor</a>\n         <a href=\"#InputSource\" onclick=\"toggleVisibility( 'InputSource');\">InputSource</a>\n         <a href=\"#IrrigationSystem\" onclick=\"toggleVisibility( 'IrrigationSystem');\">IrrigationSystem</a>\n         <a href=\"#LeakSensor\" onclick=\"toggleVisibility( 'LeakSensor');\">LeakSensor</a>\n         <a href=\"#LightSensor\" onclick=\"toggleVisibility( 'LightSensor');\">LightSensor</a>\n         <a href=\"#Lightbulb\" onclick=\"toggleVisibility( 'Lightbulb');\">Lightbulb</a>\n         <a href=\"#LockManagement\" onclick=\"toggleVisibility( 'LockManagement');\">LockManagement</a>\n         <a href=\"#LockMechanism\" onclick=\"toggleVisibility( 'LockMechanism');\">LockMechanism</a>\n         <a href=\"#Microphone\" onclick=\"toggleVisibility( 'Microphone');\">Microphone</a>\n         <a href=\"#MotionSensor\" onclick=\"toggleVisibility( 'MotionSensor');\">MotionSensor</a>\n         <a href=\"#NFCAccess\" onclick=\"toggleVisibility( 'NFCAccess');\">NFCAccess</a>\n         <a href=\"#OccupancySensor\" onclick=\"toggleVisibility( 'OccupancySensor');\">OccupancySensor</a>\n         <a href=\"#Outlet\" onclick=\"toggleVisibility( 'Outlet');\">Outlet</a>\n         <a href=\"#Pairing\" onclick=\"toggleVisibility( 'Pairing');\">Pairing</a>\n         <a href=\"#PowerManagement\" onclick=\"toggleVisibility( 'PowerManagement');\">PowerManagement</a>\n         <a href=\"#ProtocolInformation\" onclick=\"toggleVisibility( 'ProtocolInformation');\">ProtocolInformation</a>\n         <a href=\"#Relay\" onclick=\"toggleVisibility( 'Relay');\">Relay</a>\n         <a href=\"#SecuritySystem\" onclick=\"toggleVisibility( 'SecuritySystem');\">SecuritySystem</a>\n         <a href=\"#ServiceLabel\" onclick=\"toggleVisibility( 'ServiceLabel');\">ServiceLabel</a>\n         <a href=\"#Siri\" onclick=\"toggleVisibility( 'Siri');\">Siri</a>\n         <a href=\"#SiriEndpoint\" onclick=\"toggleVisibility( 'SiriEndpoint');\">SiriEndpoint</a>\n         <a href=\"#Slats\" onclick=\"toggleVisibility( 'Slats');\">Slats</a>\n         <a href=\"#SmartSpeaker\" onclick=\"toggleVisibility( 'SmartSpeaker');\">SmartSpeaker</a>\n         <a href=\"#SmokeSensor\" onclick=\"toggleVisibility( 'SmokeSensor');\">SmokeSensor</a>\n         <a href=\"#Speaker\" onclick=\"toggleVisibility( 'Speaker');\">Speaker</a>\n         <a href=\"#StatefulProgrammableSwitch\" onclick=\"toggleVisibility( 'StatefulProgrammableSwitch');\">StatefulProgrammableSwitch</a>\n         <a href=\"#StatelessProgrammableSwitch\" onclick=\"toggleVisibility( 'StatelessProgrammableSwitch');\">StatelessProgrammableSwitch</a>\n         <a href=\"#Switch\" onclick=\"toggleVisibility( 'Switch');\">Switch</a>\n         <a href=\"#TapManagement\" onclick=\"toggleVisibility( 'TapManagement');\">TapManagement</a>\n         <a href=\"#TargetControl\" onclick=\"toggleVisibility( 'TargetControl');\">TargetControl</a>\n         <a href=\"#TargetControlManagement\" onclick=\"toggleVisibility( 'TargetControlManagement');\">TargetControlManagement</a>\n         <a href=\"#Television\" onclick=\"toggleVisibility( 'Television');\">Television</a>\n         <a href=\"#TelevisionSpeaker\" onclick=\"toggleVisibility( 'TelevisionSpeaker');\">TelevisionSpeaker</a>\n         <a href=\"#TemperatureSensor\" onclick=\"toggleVisibility( 'TemperatureSensor');\">TemperatureSensor</a>\n         <a href=\"#Thermostat\" onclick=\"toggleVisibility( 'Thermostat');\">Thermostat</a>\n         <a href=\"#ThreadTransport\" onclick=\"toggleVisibility( 'ThreadTransport');\">ThreadTransport</a>\n         <a href=\"#TransferTransportManagement\" onclick=\"toggleVisibility( 'TransferTransportManagement');\">TransferTransportManagement</a>\n         <a href=\"#TunneledBTLEAccessoryService\" onclick=\"toggleVisibility( 'TunneledBTLEAccessoryService');\">TunneledBTLEAccessoryService</a>\n         <a href=\"#Valve\" onclick=\"toggleVisibility( 'Valve');\">Valve</a>\n         <a href=\"#WiFiRouter\" onclick=\"toggleVisibility( 'WiFiRouter');\">WiFiRouter</a>\n         <a href=\"#WiFiSatellite\" onclick=\"toggleVisibility( 'WiFiSatellite');\">WiFiSatellite</a>\n         <a href=\"#WiFiTransport\" onclick=\"toggleVisibility( 'WiFiTransport');\">WiFiTransport</a>\n         <a href=\"#Window\" onclick=\"toggleVisibility( 'Window');\">Window</a>\n         <a href=\"#WindowCovering\" onclick=\"toggleVisibility( 'WindowCovering');\">WindowCovering</a>\n      </DIV>   <!-- panel -->\n      <button class=\"accordion\">Characteristics\n         <i class=\"fa fa-caret-down\"></i>\n      </button>\n      <div class=\"panel\">\n         <a href=\"#accessCodeControlPoint\" onclick=\"toggleVisibility( 'accessCodeControlPoint');\">accessCodeControlPoint</a>\n         <a href=\"#accessCodeSupportedConfiguration\" onclick=\"toggleVisibility( 'accessCodeSupportedConfiguration');\">accessCodeSupportedConfiguration</a>\n         <a href=\"#accessControlLevel\" onclick=\"toggleVisibility( 'accessControlLevel');\">accessControlLevel</a>\n         <a href=\"#accessoryFlags\" onclick=\"toggleVisibility( 'accessoryFlags');\">accessoryFlags</a>\n         <a href=\"#accessoryIdentifier\" onclick=\"toggleVisibility( 'accessoryIdentifier');\">accessoryIdentifier</a>\n         <a href=\"#active\" onclick=\"toggleVisibility( 'active');\">active</a>\n         <a href=\"#activeIdentifier\" onclick=\"toggleVisibility( 'activeIdentifier');\">activeIdentifier</a>\n         <a href=\"#activityInterval\" onclick=\"toggleVisibility( 'activityInterval');\">activityInterval</a>\n         <a href=\"#administratorOnlyAccess\" onclick=\"toggleVisibility( 'administratorOnlyAccess');\">administratorOnlyAccess</a>\n         <a href=\"#airParticulateDensity\" onclick=\"toggleVisibility( 'airParticulateDensity');\">airParticulateDensity</a>\n         <a href=\"#airParticulateSize\" onclick=\"toggleVisibility( 'airParticulateSize');\">airParticulateSize</a>\n         <a href=\"#airPlayEnable\" onclick=\"toggleVisibility( 'airPlayEnable');\">airPlayEnable</a>\n         <a href=\"#airQuality\" onclick=\"toggleVisibility( 'airQuality');\">airQuality</a>\n         <a href=\"#appMatchingIdentifier\" onclick=\"toggleVisibility( 'appMatchingIdentifier');\">appMatchingIdentifier</a>\n         <a href=\"#assetUpdateReadiness\" onclick=\"toggleVisibility( 'assetUpdateReadiness');\">assetUpdateReadiness</a>\n         <a href=\"#audioFeedback\" onclick=\"toggleVisibility( 'audioFeedback');\">audioFeedback</a>\n         <a href=\"#batteryLevel\" onclick=\"toggleVisibility( 'batteryLevel');\">batteryLevel</a>\n         <a href=\"#brightness\" onclick=\"toggleVisibility( 'brightness');\">brightness</a>\n         <a href=\"#buttonEvent\" onclick=\"toggleVisibility( 'buttonEvent');\">buttonEvent</a>\n         <a href=\"#ccaEnergyDetectThreshold\" onclick=\"toggleVisibility( 'ccaEnergyDetectThreshold');\">ccaEnergyDetectThreshold</a>\n         <a href=\"#ccaSignalDetectThreshold\" onclick=\"toggleVisibility( 'ccaSignalDetectThreshold');\">ccaSignalDetectThreshold</a>\n         <a href=\"#cameraOperatingModeIndicator\" onclick=\"toggleVisibility( 'cameraOperatingModeIndicator');\">cameraOperatingModeIndicator</a>\n         <a href=\"#carbonDioxideDetected\" onclick=\"toggleVisibility( 'carbonDioxideDetected');\">carbonDioxideDetected</a>\n         <a href=\"#carbonDioxideLevel\" onclick=\"toggleVisibility( 'carbonDioxideLevel');\">carbonDioxideLevel</a>\n         <a href=\"#carbonDioxidePeakLevel\" onclick=\"toggleVisibility( 'carbonDioxidePeakLevel');\">carbonDioxidePeakLevel</a>\n         <a href=\"#carbonMonoxideDetected\" onclick=\"toggleVisibility( 'carbonMonoxideDetected');\">carbonMonoxideDetected</a>\n         <a href=\"#carbonMonoxideLevel\" onclick=\"toggleVisibility( 'carbonMonoxideLevel');\">carbonMonoxideLevel</a>\n         <a href=\"#carbonMonoxidePeakLevel\" onclick=\"toggleVisibility( 'carbonMonoxidePeakLevel');\">carbonMonoxidePeakLevel</a>\n         <a href=\"#characteristicValueActiveTransitionCount\" onclick=\"toggleVisibility( 'characteristicValueActiveTransitionCount');\">characteristicValueActiveTransitionCount</a>\n         <a href=\"#characteristicValueTransitionControl\" onclick=\"toggleVisibility( 'characteristicValueTransitionControl');\">characteristicValueTransitionControl</a>\n         <a href=\"#chargingState\" onclick=\"toggleVisibility( 'chargingState');\">chargingState</a>\n         <a href=\"#closedCaptions\" onclick=\"toggleVisibility( 'closedCaptions');\">closedCaptions</a>\n         <a href=\"#colorTemperature\" onclick=\"toggleVisibility( 'colorTemperature');\">colorTemperature</a>\n         <a href=\"#configurationState\" onclick=\"toggleVisibility( 'configurationState');\">configurationState</a>\n         <a href=\"#configuredName\" onclick=\"toggleVisibility( 'configuredName');\">configuredName</a>\n         <a href=\"#contactSensorState\" onclick=\"toggleVisibility( 'contactSensorState');\">contactSensorState</a>\n         <a href=\"#coolingThresholdTemperature\" onclick=\"toggleVisibility( 'coolingThresholdTemperature');\">coolingThresholdTemperature</a>\n         <a href=\"#cryptoHash\" onclick=\"toggleVisibility( 'cryptoHash');\">cryptoHash</a>\n         <a href=\"#currentAirPurifierState\" onclick=\"toggleVisibility( 'currentAirPurifierState');\">currentAirPurifierState</a>\n         <a href=\"#currentAmbientLightLevel\" onclick=\"toggleVisibility( 'currentAmbientLightLevel');\">currentAmbientLightLevel</a>\n         <a href=\"#currentDoorState\" onclick=\"toggleVisibility( 'currentDoorState');\">currentDoorState</a>\n         <a href=\"#currentFanState\" onclick=\"toggleVisibility( 'currentFanState');\">currentFanState</a>\n         <a href=\"#currentHeaterCoolerState\" onclick=\"toggleVisibility( 'currentHeaterCoolerState');\">currentHeaterCoolerState</a>\n         <a href=\"#currentHeatingCoolingState\" onclick=\"toggleVisibility( 'currentHeatingCoolingState');\">currentHeatingCoolingState</a>\n         <a href=\"#currentHorizontalTiltAngle\" onclick=\"toggleVisibility( 'currentHorizontalTiltAngle');\">currentHorizontalTiltAngle</a>\n         <a href=\"#currentHumidifierDehumidifierState\" onclick=\"toggleVisibility( 'currentHumidifierDehumidifierState');\">currentHumidifierDehumidifierState</a>\n         <a href=\"#currentMediaState\" onclick=\"toggleVisibility( 'currentMediaState');\">currentMediaState</a>\n         <a href=\"#currentPosition\" onclick=\"toggleVisibility( 'currentPosition');\">currentPosition</a>\n         <a href=\"#currentRelativeHumidity\" onclick=\"toggleVisibility( 'currentRelativeHumidity');\">currentRelativeHumidity</a>\n         <a href=\"#currentSlatState\" onclick=\"toggleVisibility( 'currentSlatState');\">currentSlatState</a>\n         <a href=\"#currentTemperature\" onclick=\"toggleVisibility( 'currentTemperature');\">currentTemperature</a>\n         <a href=\"#currentTiltAngle\" onclick=\"toggleVisibility( 'currentTiltAngle');\">currentTiltAngle</a>\n         <a href=\"#currentTransport\" onclick=\"toggleVisibility( 'currentTransport');\">currentTransport</a>\n         <a href=\"#currentVerticalTiltAngle\" onclick=\"toggleVisibility( 'currentVerticalTiltAngle');\">currentVerticalTiltAngle</a>\n         <a href=\"#currentVisibilityState\" onclick=\"toggleVisibility( 'currentVisibilityState');\">currentVisibilityState</a>\n         <a href=\"#dataStreamHAPTransport\" onclick=\"toggleVisibility( 'dataStreamHAPTransport');\">dataStreamHAPTransport</a>\n         <a href=\"#dataStreamHAPTransportInterrupt\" onclick=\"toggleVisibility( 'dataStreamHAPTransportInterrupt');\">dataStreamHAPTransportInterrupt</a>\n         <a href=\"#diagonalFieldOfView\" onclick=\"toggleVisibility( 'diagonalFieldOfView');\">diagonalFieldOfView</a>\n         <a href=\"#digitalZoom\" onclick=\"toggleVisibility( 'digitalZoom');\">digitalZoom</a>\n         <a href=\"#displayOrder\" onclick=\"toggleVisibility( 'displayOrder');\">displayOrder</a>\n         <a href=\"#eventRetransmissionMaximum\" onclick=\"toggleVisibility( 'eventRetransmissionMaximum');\">eventRetransmissionMaximum</a>\n         <a href=\"#eventSnapshotsActive\" onclick=\"toggleVisibility( 'eventSnapshotsActive');\">eventSnapshotsActive</a>\n         <a href=\"#eventTransmissionCounters\" onclick=\"toggleVisibility( 'eventTransmissionCounters');\">eventTransmissionCounters</a>\n         <a href=\"#filterChangeIndication\" onclick=\"toggleVisibility( 'filterChangeIndication');\">filterChangeIndication</a>\n         <a href=\"#filterLifeLevel\" onclick=\"toggleVisibility( 'filterLifeLevel');\">filterLifeLevel</a>\n         <a href=\"#firmwareRevision\" onclick=\"toggleVisibility( 'firmwareRevision');\">firmwareRevision</a>\n         <a href=\"#firmwareUpdateReadiness\" onclick=\"toggleVisibility( 'firmwareUpdateReadiness');\">firmwareUpdateReadiness</a>\n         <a href=\"#firmwareUpdateStatus\" onclick=\"toggleVisibility( 'firmwareUpdateStatus');\">firmwareUpdateStatus</a>\n         <a href=\"#hardwareFinish\" onclick=\"toggleVisibility( 'hardwareFinish');\">hardwareFinish</a>\n         <a href=\"#hardwareRevision\" onclick=\"toggleVisibility( 'hardwareRevision');\">hardwareRevision</a>\n         <a href=\"#heartBeat\" onclick=\"toggleVisibility( 'heartBeat');\">heartBeat</a>\n         <a href=\"#heatingThresholdTemperature\" onclick=\"toggleVisibility( 'heatingThresholdTemperature');\">heatingThresholdTemperature</a>\n         <a href=\"#holdPosition\" onclick=\"toggleVisibility( 'holdPosition');\">holdPosition</a>\n         <a href=\"#homeKitCameraActive\" onclick=\"toggleVisibility( 'homeKitCameraActive');\">homeKitCameraActive</a>\n         <a href=\"#hue\" onclick=\"toggleVisibility( 'hue');\">hue</a>\n         <a href=\"#identifier\" onclick=\"toggleVisibility( 'identifier');\">identifier</a>\n         <a href=\"#identify\" onclick=\"toggleVisibility( 'identify');\">identify</a>\n         <a href=\"#imageMirroring\" onclick=\"toggleVisibility( 'imageMirroring');\">imageMirroring</a>\n         <a href=\"#imageRotation\" onclick=\"toggleVisibility( 'imageRotation');\">imageRotation</a>\n         <a href=\"#inUse\" onclick=\"toggleVisibility( 'inUse');\">inUse</a>\n         <a href=\"#inputDeviceType\" onclick=\"toggleVisibility( 'inputDeviceType');\">inputDeviceType</a>\n         <a href=\"#inputSourceType\" onclick=\"toggleVisibility( 'inputSourceType');\">inputSourceType</a>\n         <a href=\"#isConfigured\" onclick=\"toggleVisibility( 'isConfigured');\">isConfigured</a>\n         <a href=\"#leakDetected\" onclick=\"toggleVisibility( 'leakDetected');\">leakDetected</a>\n         <a href=\"#listPairings\" onclick=\"toggleVisibility( 'listPairings');\">listPairings</a>\n         <a href=\"#lockControlPoint\" onclick=\"toggleVisibility( 'lockControlPoint');\">lockControlPoint</a>\n         <a href=\"#lockCurrentState\" onclick=\"toggleVisibility( 'lockCurrentState');\">lockCurrentState</a>\n         <a href=\"#lockLastKnownAction\" onclick=\"toggleVisibility( 'lockLastKnownAction');\">lockLastKnownAction</a>\n         <a href=\"#lockManagementAutoSecurityTimeout\" onclick=\"toggleVisibility( 'lockManagementAutoSecurityTimeout');\">lockManagementAutoSecurityTimeout</a>\n         <a href=\"#lockPhysicalControls\" onclick=\"toggleVisibility( 'lockPhysicalControls');\">lockPhysicalControls</a>\n         <a href=\"#lockTargetState\" onclick=\"toggleVisibility( 'lockTargetState');\">lockTargetState</a>\n         <a href=\"#logs\" onclick=\"toggleVisibility( 'logs');\">logs</a>\n         <a href=\"#macRetransmissionMaximum\" onclick=\"toggleVisibility( 'macRetransmissionMaximum');\">macRetransmissionMaximum</a>\n         <a href=\"#macTransmissionCounters\" onclick=\"toggleVisibility( 'macTransmissionCounters');\">macTransmissionCounters</a>\n         <a href=\"#managedNetworkEnable\" onclick=\"toggleVisibility( 'managedNetworkEnable');\">managedNetworkEnable</a>\n         <a href=\"#manuallyDisabled\" onclick=\"toggleVisibility( 'manuallyDisabled');\">manuallyDisabled</a>\n         <a href=\"#manufacturer\" onclick=\"toggleVisibility( 'manufacturer');\">manufacturer</a>\n         <a href=\"#MaximumTransmitPower\" onclick=\"toggleVisibility( 'MaximumTransmitPower');\">MaximumTransmitPower</a>\n         <a href=\"#MetricsBufferFullState\" onclick=\"toggleVisibility( 'MetricsBufferFullState');\">MetricsBufferFullState</a>\n         <a href=\"#model\" onclick=\"toggleVisibility( 'model');\">model</a>\n         <a href=\"#motionDetected\" onclick=\"toggleVisibility( 'motionDetected');\">motionDetected</a>\n         <a href=\"#multiFunctionButton\" onclick=\"toggleVisibility( 'multiFunctionButton');\">multiFunctionButton</a>\n         <a href=\"#mute\" onclick=\"toggleVisibility( 'mute');\">mute</a>\n         <a href=\"#NFCAccessControlPoint\" onclick=\"toggleVisibility( 'NFCAccessControlPoint');\">NFCAccessControlPoint</a>\n         <a href=\"#NFCAccessSupportedConfiguration\" onclick=\"toggleVisibility( 'NFCAccessSupportedConfiguration');\">NFCAccessSupportedConfiguration</a>\n         <a href=\"#name\" onclick=\"toggleVisibility( 'name');\">name</a>\n         <a href=\"#networkAccessViolationControl\" onclick=\"toggleVisibility( 'networkAccessViolationControl');\">networkAccessViolationControl</a>\n         <a href=\"#networkClientProfileControl\" onclick=\"toggleVisibility( 'networkClientProfileControl');\">networkClientProfileControl</a>\n         <a href=\"#networkClientStatusControl\" onclick=\"toggleVisibility( 'networkClientStatusControl');\">networkClientStatusControl</a>\n         <a href=\"#nightVision\" onclick=\"toggleVisibility( 'nightVision');\">nightVision</a>\n         <a href=\"#nitrogenDioxideDensity\" onclick=\"toggleVisibility( 'nitrogenDioxideDensity');\">nitrogenDioxideDensity</a>\n         <a href=\"#obstructionDetected\" onclick=\"toggleVisibility( 'obstructionDetected');\">obstructionDetected</a>\n         <a href=\"#occupancyDetected\" onclick=\"toggleVisibility( 'occupancyDetected');\">occupancyDetected</a>\n         <a href=\"#on\" onclick=\"toggleVisibility( 'on');\">on</a>\n         <a href=\"#operatingStateResponse\" onclick=\"toggleVisibility( 'operatingStateResponse');\">operatingStateResponse</a>\n         <a href=\"#opticalZoom\" onclick=\"toggleVisibility( 'opticalZoom');\">opticalZoom</a>\n         <a href=\"#outletInUse\" onclick=\"toggleVisibility( 'outletInUse');\">outletInUse</a>\n         <a href=\"#ozoneDensity\" onclick=\"toggleVisibility( 'ozoneDensity');\">ozoneDensity</a>\n         <a href=\"#pm10Density\" onclick=\"toggleVisibility( 'pm10Density');\">pm10Density</a>\n         <a href=\"#pm2_5Density\" onclick=\"toggleVisibility( 'pm2_5Density');\">pm2_5Density</a>\n         <a href=\"#pairSetup\" onclick=\"toggleVisibility( 'pairSetup');\">pairSetup</a>\n         <a href=\"#pairVerify\" onclick=\"toggleVisibility( 'pairVerify');\">pairVerify</a>\n         <a href=\"#pairingFeatures\" onclick=\"toggleVisibility( 'pairingFeatures');\">pairingFeatures</a>\n         <a href=\"#pairingPairings\" onclick=\"toggleVisibility( 'pairingPairings');\">pairingPairings</a>\n         <a href=\"#passwordSetting\" onclick=\"toggleVisibility( 'passwordSetting');\">passwordSetting</a>\n         <a href=\"#periodicSnapshotsActive\" onclick=\"toggleVisibility( 'periodicSnapshotsActive');\">periodicSnapshotsActive</a>\n         <a href=\"#pictureMode\" onclick=\"toggleVisibility( 'pictureMode');\">pictureMode</a>\n         <a href=\"#ping\" onclick=\"toggleVisibility( 'ping');\">ping</a>\n         <a href=\"#positionState\" onclick=\"toggleVisibility( 'positionState');\">positionState</a>\n         <a href=\"#powerModeSelection\" onclick=\"toggleVisibility( 'powerModeSelection');\">powerModeSelection</a>\n         <a href=\"#productData\" onclick=\"toggleVisibility( 'productData');\">productData</a>\n         <a href=\"#programMode\" onclick=\"toggleVisibility( 'programMode');\">programMode</a>\n         <a href=\"#programmableSwitchEvent\" onclick=\"toggleVisibility( 'programmableSwitchEvent');\">programmableSwitchEvent</a>\n         <a href=\"#programmableSwitchOutputState\" onclick=\"toggleVisibility( 'programmableSwitchOutputState');\">programmableSwitchOutputState</a>\n         <a href=\"#receivedSignalStrengthIndication\" onclick=\"toggleVisibility( 'receivedSignalStrengthIndication');\">receivedSignalStrengthIndication</a>\n         <a href=\"#receiverSensitivity\" onclick=\"toggleVisibility( 'receiverSensitivity');\">receiverSensitivity</a>\n         <a href=\"#recordingAudioActive\" onclick=\"toggleVisibility( 'recordingAudioActive');\">recordingAudioActive</a>\n         <a href=\"#relativeHumidityDehumidifierThreshold\" onclick=\"toggleVisibility( 'relativeHumidityDehumidifierThreshold');\">relativeHumidityDehumidifierThreshold</a>\n         <a href=\"#relativeHumidityHumidifierThreshold\" onclick=\"toggleVisibility( 'relativeHumidityHumidifierThreshold');\">relativeHumidityHumidifierThreshold</a>\n         <a href=\"#relayControlPoint\" onclick=\"toggleVisibility( 'relayControlPoint');\">relayControlPoint</a>\n         <a href=\"#relayEnabled\" onclick=\"toggleVisibility( 'relayEnabled');\">relayEnabled</a>\n         <a href=\"#relayState\" onclick=\"toggleVisibility( 'relayState');\">relayState</a>\n         <a href=\"#remainingDuration\" onclick=\"toggleVisibility( 'remainingDuration');\">remainingDuration</a>\n         <a href=\"#remoteKey\" onclick=\"toggleVisibility( 'remoteKey');\">remoteKey</a>\n         <a href=\"#resetFilterIndication\" onclick=\"toggleVisibility( 'resetFilterIndication');\">resetFilterIndication</a>\n         <a href=\"#rotationDirection\" onclick=\"toggleVisibility( 'rotationDirection');\">rotationDirection</a>\n         <a href=\"#rotationSpeed\" onclick=\"toggleVisibility( 'rotationSpeed');\">rotationSpeed</a>\n         <a href=\"#routerStatus\" onclick=\"toggleVisibility( 'routerStatus');\">routerStatus</a>\n         <a href=\"#saturation\" onclick=\"toggleVisibility( 'saturation');\">saturation</a>\n         <a href=\"#securitySystemAlarmType\" onclick=\"toggleVisibility( 'securitySystemAlarmType');\">securitySystemAlarmType</a>\n         <a href=\"#securitySystemCurrentState\" onclick=\"toggleVisibility( 'securitySystemCurrentState');\">securitySystemCurrentState</a>\n         <a href=\"#securitySystemTargetState\" onclick=\"toggleVisibility( 'securitySystemTargetState');\">securitySystemTargetState</a>\n         <a href=\"#selectedAudioStreamConfiguration\" onclick=\"toggleVisibility( 'selectedAudioStreamConfiguration');\">selectedAudioStreamConfiguration</a>\n         <a href=\"#selectedCameraRecordingConfiguration\" onclick=\"toggleVisibility( 'selectedCameraRecordingConfiguration');\">selectedCameraRecordingConfiguration</a>\n         <a href=\"#selectedDiagnosticsModes\" onclick=\"toggleVisibility( 'selectedDiagnosticsModes');\">selectedDiagnosticsModes</a>\n         <a href=\"#selectedRTPStreamConfiguration\" onclick=\"toggleVisibility( 'selectedRTPStreamConfiguration');\">selectedRTPStreamConfiguration</a>\n         <a href=\"#selectedSleepConfiguration\" onclick=\"toggleVisibility( 'selectedSleepConfiguration');\">selectedSleepConfiguration</a>\n         <a href=\"#serialNumber\" onclick=\"toggleVisibility( 'serialNumber');\">serialNumber</a>\n         <a href=\"#serviceLabelIndex\" onclick=\"toggleVisibility( 'serviceLabelIndex');\">serviceLabelIndex</a>\n         <a href=\"#serviceLabelNamespace\" onclick=\"toggleVisibility( 'serviceLabelNamespace');\">serviceLabelNamespace</a>\n         <a href=\"#setDuration\" onclick=\"toggleVisibility( 'setDuration');\">setDuration</a>\n         <a href=\"#setupDataStreamTransport\" onclick=\"toggleVisibility( 'setupDataStreamTransport');\">setupDataStreamTransport</a>\n         <a href=\"#setupEndpoints\" onclick=\"toggleVisibility( 'setupEndpoints');\">setupEndpoints</a>\n         <a href=\"#setupTransferTransport\" onclick=\"toggleVisibility( 'setupTransferTransport');\">setupTransferTransport</a>\n         <a href=\"#signalToNoiseRatio\" onclick=\"toggleVisibility( 'signalToNoiseRatio');\">signalToNoiseRatio</a>\n         <a href=\"#siriEnable\" onclick=\"toggleVisibility( 'siriEnable');\">siriEnable</a>\n         <a href=\"#SiriEndpointSessionStatus\" onclick=\"toggleVisibility( 'SiriEndpointSessionStatus');\">SiriEndpointSessionStatus</a>\n         <a href=\"#siriEngineVersion\" onclick=\"toggleVisibility( 'siriEngineVersion');\">siriEngineVersion</a>\n         <a href=\"#siriInputType\" onclick=\"toggleVisibility( 'siriInputType');\">siriInputType</a>\n         <a href=\"#siriLightOnUse\" onclick=\"toggleVisibility( 'siriLightOnUse');\">siriLightOnUse</a>\n         <a href=\"#siriListening\" onclick=\"toggleVisibility( 'siriListening');\">siriListening</a>\n         <a href=\"#siriTouchToUse\" onclick=\"toggleVisibility( 'siriTouchToUse');\">siriTouchToUse</a>\n         <a href=\"#slatType\" onclick=\"toggleVisibility( 'slatType');\">slatType</a>\n         <a href=\"#sleepDiscoveryMode\" onclick=\"toggleVisibility( 'sleepDiscoveryMode');\">sleepDiscoveryMode</a>\n         <a href=\"#sleepInterval\" onclick=\"toggleVisibility( 'sleepInterval');\">sleepInterval</a>\n         <a href=\"#smokeDetected\" onclick=\"toggleVisibility( 'smokeDetected');\">smokeDetected</a>\n         <a href=\"#softwareRevision\" onclick=\"toggleVisibility( 'softwareRevision');\">softwareRevision</a>\n         <a href=\"#StagedFirmwareVersion\" onclick=\"toggleVisibility( 'StagedFirmwareVersion');\">StagedFirmwareVersion</a>\n         <a href=\"#statusActive\" onclick=\"toggleVisibility( 'statusActive');\">statusActive</a>\n         <a href=\"#statusFault\" onclick=\"toggleVisibility( 'statusFault');\">statusFault</a>\n         <a href=\"#statusJammed\" onclick=\"toggleVisibility( 'statusJammed');\">statusJammed</a>\n         <a href=\"#statusLowBattery\" onclick=\"toggleVisibility( 'statusLowBattery');\">statusLowBattery</a>\n         <a href=\"#statusTampered\" onclick=\"toggleVisibility( 'statusTampered');\">statusTampered</a>\n         <a href=\"#streamingStatus\" onclick=\"toggleVisibility( 'streamingStatus');\">streamingStatus</a>\n         <a href=\"#sulphurDioxideDensity\" onclick=\"toggleVisibility( 'sulphurDioxideDensity');\">sulphurDioxideDensity</a>\n         <a href=\"#supportedAssetTypes\" onclick=\"toggleVisibility( 'supportedAssetTypes');\">supportedAssetTypes</a>\n         <a href=\"#supportedAudioRecordingConfiguration\" onclick=\"toggleVisibility( 'supportedAudioRecordingConfiguration');\">supportedAudioRecordingConfiguration</a>\n         <a href=\"#supportedAudioStreamConfiguration\" onclick=\"toggleVisibility( 'supportedAudioStreamConfiguration');\">supportedAudioStreamConfiguration</a>\n         <a href=\"#supportedCameraRecordingConfiguration\" onclick=\"toggleVisibility( 'supportedCameraRecordingConfiguration');\">supportedCameraRecordingConfiguration</a>\n         <a href=\"#supportedCharacteristicValueTransitionConfiguration\" onclick=\"toggleVisibility( 'supportedCharacteristicValueTransitionConfiguration');\">supportedCharacteristicValueTransitionConfiguration</a>\n         <a href=\"#supportedDataStreamTransportConfiguration\" onclick=\"toggleVisibility( 'supportedDataStreamTransportConfiguration');\">supportedDataStreamTransportConfiguration</a>\n         <a href=\"#supportedDiagnosticsSnapshot\" onclick=\"toggleVisibility( 'supportedDiagnosticsSnapshot');\">supportedDiagnosticsSnapshot</a>\n         <a href=\"#supportedFirmwareUpdateConfiguration\" onclick=\"toggleVisibility( 'supportedFirmwareUpdateConfiguration');\">supportedFirmwareUpdateConfiguration</a>\n         <a href=\"#supportedMetrics\" onclick=\"toggleVisibility( 'supportedMetrics');\">supportedMetrics</a>\n         <a href=\"#supportedRTPConfiguration\" onclick=\"toggleVisibility( 'supportedRTPConfiguration');\">supportedRTPConfiguration</a>\n         <a href=\"#supportedRouterConfiguration\" onclick=\"toggleVisibility( 'supportedRouterConfiguration');\">supportedRouterConfiguration</a>\n         <a href=\"#supportedTransferTransportConfiguration\" onclick=\"toggleVisibility( 'supportedTransferTransportConfiguration');\">supportedTransferTransportConfiguration</a>\n         <a href=\"#supportedVideoRecordingConfiguration\" onclick=\"toggleVisibility( 'supportedVideoRecordingConfiguration');\">supportedVideoRecordingConfiguration</a>\n         <a href=\"#supportedVideoStreamConfiguration\" onclick=\"toggleVisibility( 'supportedVideoStreamConfiguration');\">supportedVideoStreamConfiguration</a>\n         <a href=\"#swingMode\" onclick=\"toggleVisibility( 'swingMode');\">swingMode</a>\n         <a href=\"#tapType\" onclick=\"toggleVisibility( 'tapType');\">tapType</a>\n         <a href=\"#targetAirPurifierState\" onclick=\"toggleVisibility( 'targetAirPurifierState');\">targetAirPurifierState</a>\n         <a href=\"#targetControlList\" onclick=\"toggleVisibility( 'targetControlList');\">targetControlList</a>\n         <a href=\"#targetControlSupportedConfiguration\" onclick=\"toggleVisibility( 'targetControlSupportedConfiguration');\">targetControlSupportedConfiguration</a>\n         <a href=\"#targetDoorState\" onclick=\"toggleVisibility( 'targetDoorState');\">targetDoorState</a>\n         <a href=\"#targetFanState\" onclick=\"toggleVisibility( 'targetFanState');\">targetFanState</a>\n         <a href=\"#targetHeaterCoolerState\" onclick=\"toggleVisibility( 'targetHeaterCoolerState');\">targetHeaterCoolerState</a>\n         <a href=\"#targetHeatingCoolingState\" onclick=\"toggleVisibility( 'targetHeatingCoolingState');\">targetHeatingCoolingState</a>\n         <a href=\"#targetHorizontalTiltAngle\" onclick=\"toggleVisibility( 'targetHorizontalTiltAngle');\">targetHorizontalTiltAngle</a>\n         <a href=\"#targetHumidifierDehumidifierState\" onclick=\"toggleVisibility( 'targetHumidifierDehumidifierState');\">targetHumidifierDehumidifierState</a>\n         <a href=\"#targetMediaState\" onclick=\"toggleVisibility( 'targetMediaState');\">targetMediaState</a>\n         <a href=\"#targetPosition\" onclick=\"toggleVisibility( 'targetPosition');\">targetPosition</a>\n         <a href=\"#targetRelativeHumidity\" onclick=\"toggleVisibility( 'targetRelativeHumidity');\">targetRelativeHumidity</a>\n         <a href=\"#targetTemperature\" onclick=\"toggleVisibility( 'targetTemperature');\">targetTemperature</a>\n         <a href=\"#targetTiltAngle\" onclick=\"toggleVisibility( 'targetTiltAngle');\">targetTiltAngle</a>\n         <a href=\"#targetVerticalTiltAngle\" onclick=\"toggleVisibility( 'targetVerticalTiltAngle');\">targetVerticalTiltAngle</a>\n         <a href=\"#targetVisibilityState\" onclick=\"toggleVisibility( 'targetVisibilityState');\">targetVisibilityState</a>\n         <a href=\"#temperatureDisplayUnits\" onclick=\"toggleVisibility( 'temperatureDisplayUnits');\">temperatureDisplayUnits</a>\n         <a href=\"#thirdPartyCameraActive\" onclick=\"toggleVisibility( 'thirdPartyCameraActive');\">thirdPartyCameraActive</a>\n         <a href=\"#threadControlPoint\" onclick=\"toggleVisibility( 'threadControlPoint');\">threadControlPoint</a>\n         <a href=\"#threadNodeCapabilities\" onclick=\"toggleVisibility( 'threadNodeCapabilities');\">threadNodeCapabilities</a>\n         <a href=\"#threadOpenThreadVersion\" onclick=\"toggleVisibility( 'threadOpenThreadVersion');\">threadOpenThreadVersion</a>\n         <a href=\"#threadStatus\" onclick=\"toggleVisibility( 'threadStatus');\">threadStatus</a>\n         <a href=\"#token\" onclick=\"toggleVisibility( 'token');\">token</a>\n         <a href=\"#transmitPower\" onclick=\"toggleVisibility( 'transmitPower');\">transmitPower</a>\n         <a href=\"#tunnelConnectionTimeout\" onclick=\"toggleVisibility( 'tunnelConnectionTimeout');\">tunnelConnectionTimeout</a>\n         <a href=\"#tunneledAccessoryAdvertising\" onclick=\"toggleVisibility( 'tunneledAccessoryAdvertising');\">tunneledAccessoryAdvertising</a>\n         <a href=\"#tunneledAccessoryConnected\" onclick=\"toggleVisibility( 'tunneledAccessoryConnected');\">tunneledAccessoryConnected</a>\n         <a href=\"#tunneledAccessoryStateNumber\" onclick=\"toggleVisibility( 'tunneledAccessoryStateNumber');\">tunneledAccessoryStateNumber</a>\n         <a href=\"#vocDensity\" onclick=\"toggleVisibility( 'vocDensity');\">vocDensity</a>\n         <a href=\"#valveType\" onclick=\"toggleVisibility( 'valveType');\">valveType</a>\n         <a href=\"#version\" onclick=\"toggleVisibility( 'version');\">version</a>\n         <a href=\"#videoAnalysisActive\" onclick=\"toggleVisibility( 'videoAnalysisActive');\">videoAnalysisActive</a>\n         <a href=\"#volume\" onclick=\"toggleVisibility( 'volume');\">volume</a>\n         <a href=\"#volumeControlType\" onclick=\"toggleVisibility( 'volumeControlType');\">volumeControlType</a>\n         <a href=\"#volumeSelector\" onclick=\"toggleVisibility( 'volumeSelector');\">volumeSelector</a>\n         <a href=\"#wanConfigurationList\" onclick=\"toggleVisibility( 'wanConfigurationList');\">wanConfigurationList</a>\n         <a href=\"#wanStatusList\" onclick=\"toggleVisibility( 'wanStatusList');\">wanStatusList</a>\n         <a href=\"#wakeConfiguration\" onclick=\"toggleVisibility( 'wakeConfiguration');\">wakeConfiguration</a>\n         <a href=\"#waterLevel\" onclick=\"toggleVisibility( 'waterLevel');\">waterLevel</a>\n         <a href=\"#wifiCapabilities\" onclick=\"toggleVisibility( 'wifiCapabilities');\">wifiCapabilities</a>\n         <a href=\"#wifiConfigurationControl\" onclick=\"toggleVisibility( 'wifiConfigurationControl');\">wifiConfigurationControl</a>\n         <a href=\"#wifiSatelliteStatus\" onclick=\"toggleVisibility( 'wifiSatelliteStatus');\">wifiSatelliteStatus</a>\n      </DIV>   <!-- panel -->\n      <button class=\"accordion\">Directives\n         <i class=\"fa fa-caret-down\"></i>\n      </button>\n      <div class=\"panel\">\n         <a href=\"#debug_D\" onclick=\"toggleVisibility( 'Directives');\">debug</a>\n         <a href=\"#outputConstants_D\" onclick=\"toggleVisibility( 'Directives');\">outputConstants</a>\n         <a href=\"#statusMsg_D\" onclick=\"toggleVisibility( 'Directives');\">statusMsg</a>\n         <a href=\"#interval_D\" onclick=\"toggleVisibility( 'Directives');\">interval</a>\n         <a href=\"#timeout_D\" onclick=\"toggleVisibility( 'Directives');\">timeout</a>\n         <a href=\"#queueTypes_D\" onclick=\"toggleVisibility( 'Directives');\">queueTypes</a>\n         <a href=\"#definitions_D\" onclick=\"toggleVisibility( 'Directives');\">definitions</a>\n      </DIV>   <!-- panel -->\n      <button class=\"accordion\">Accessory Directives\n         <i class=\"fa fa-caret-down\"></i>\n      </button>\n      <div class=\"panel\">\n         <a href=\"#subType\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">subType</a>\n         <a href=\"#fakegato\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">fakegato</a>\n         <a href=\"#publishExternally\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">publishExternally</a>\n         <a href=\"#state_cmd_prefix\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">state_cmd_prefix</a>\n         <a href=\"#state_cmd_suffix\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">state_cmd_suffix</a>\n         <a href=\"#state_cmd\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">state_cmd</a>\n         <a href=\"#polling\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">polling</a>\n         <a href=\"#interval\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">interval</a>\n         <a href=\"#timeout\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">timeout</a>\n         <a href=\"#queue\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">queue</a>\n         <a href=\"#stateChangeResponseTime\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">stateChangeResponseTime</a>\n         <a href=\"#linkedTypes\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">linkedTypes</a>\n         <a href=\"#outputConstants\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">outputConstants</a>\n         <a href=\"#statusMsg\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">statusMsg</a>\n      </DIV>   <!-- panel -->\n      <button class=\"accordion\">Custom Characteristics\n         <i class=\"fa fa-caret-down\"></i>\n      </button>\n      <div class=\"panel\">\n         <a href=\"#CUSTOM_CHARACTERISTICS\" onclick=\"toggleVisibility( 'CustomCharacteristics');\">Custom Characteristics</a>\n      </DIV>   <!-- panel -->\n      <button class=\"accordion\">Script Templates\n         <i class=\"fa fa-caret-down\"></i>\n      </button>\n      <div class=\"panel\">\n         <a href=\"#JS Template\" onclick=\"toggleVisibility( 'JS Template');\">JS Template</a>\n         <a href=\"#Bash Template\" onclick=\"toggleVisibility( 'Bash Template');\">Bash Template</a>\n      </DIV>   <!-- panel -->\n      <a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/Developers.md>Developers Guide</a>\n      <a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/AdvancedTroubleShooting.md>Advanced TroubleShooting</a>\n   </DIV>   <!-- sidenav -->\n   <div class=\"main\">\n      <h2>CMD4 Portal</h2>\n      <p>This auto generated document replaces much of the hard coded definitions and is the portal to everything that is Cmd4.</p>\n      <p>Enjoy</p>\n      <p>&nbsp;&nbsp;&nbsp;John Talbot</p>\n   </DIV>   <!-- main -->\n   <div class=\"main\">\n      <div id=\"AccessControl\" class=\"section\">\n         <a name=\"AccessControl\"></a>\n         <header><h1>AccessControl</h1></header>\n         <p>UUID:000000DA-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#accessControlLevel\">accessControlLevel</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#passwordSetting\">passwordSetting</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AccessControl,\n            name: \"MY_AccessControl\",\n            displayName: \"MY_AccessControl\",\n            accessControlLevel: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AccessControl -->\n      <div id=\"AccessoryRuntimeInformation\" class=\"section\">\n         <a name=\"AccessoryRuntimeInformation\"></a>\n         <header><h1>AccessoryRuntimeInformation</h1></header>\n         <p>UUID:00000239-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#ping\">ping</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#activityInterval\">activityInterval</a>\n            <LI><a href=\"#heartBeat\">heartBeat</a>\n            <LI><a href=\"#sleepInterval\">sleepInterval</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AccessoryRuntimeInformation,\n            name: \"MY_AccessoryRuntimeInformation\",\n            displayName: \"MY_AccessoryRuntimeInformation\",\n            ping: \"0\",\n            activityInterval: < UINT32 >,\n            heartBeat: < UINT32 >,\n            sleepInterval: < UINT32 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AccessoryRuntimeInformation -->\n      <div id=\"AccessoryInformation\" class=\"section\">\n         <a name=\"AccessoryInformation\"></a>\n         <header><h1>AccessoryInformation</h1></header>\n         <p>UUID:0000003E-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#identify\">identify</a></UL></TD><TD> 1 </TD><TD> TRUE </TD>\n            <tr><TD><UL><LI><a href=\"#manufacturer\">manufacturer</a></UL></TD><TD> Cmd4 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#model\">model</a></UL></TD><TD> Model </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#name\">name</a></UL></TD><TD> My_AccessoryInformation </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#serialNumber\">serialNumber</a></UL></TD><TD> ABC001 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#firmwareRevision\">firmwareRevision</a></UL></TD><TD> 100.1.1 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#hardwareRevision\">hardwareRevision</a>\n            <LI><a href=\"#accessoryFlags\">accessoryFlags</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#identify\">identify</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AccessoryInformation,\n            name: \"MY_AccessoryInformation\",\n            displayName: \"MY_AccessoryInformation\",\n            identify: \"1\",\n            manufacturer: \"Cmd4\",\n            model: \"Model\",\n            name: \"My_AccessoryInformation\",\n            serialNumber: \"ABC001\",\n            firmwareRevision: \"100.1.1\",\n            hardwareRevision: \"< STRING> \",\n            accessoryFlags: < UINT32 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AccessoryInformation -->\n      <div id=\"AirPurifier\" class=\"section\">\n         <a name=\"AirPurifier\"></a>\n         <header><h1>AirPurifier</h1></header>\n         <p>UUID:000000BB-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#currentAirPurifierState\">currentAirPurifierState</a></UL></TD><TD> 2 </TD><TD> PURIFYING_AIR </TD>\n            <tr><TD><UL><LI><a href=\"#targetAirPurifierState\">targetAirPurifierState</a></UL></TD><TD> 1 </TD><TD> AUTO </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#lockPhysicalControls\">lockPhysicalControls</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#swingMode\">swingMode</a>\n            <LI><a href=\"#rotationSpeed\">rotationSpeed</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AirPurifier,\n            name: \"MY_AirPurifier\",\n            displayName: \"MY_AirPurifier\",\n            active: \"1\",\n            currentAirPurifierState: \"2\",\n            targetAirPurifierState: \"1\",\n            lockPhysicalControls: < UINT8 >,\n            name: \"< STRING> \",\n            swingMode: < UINT8 >,\n            Unknown format float,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AirPurifier -->\n      <div id=\"AirQualitySensor\" class=\"section\">\n         <a name=\"AirQualitySensor\"></a>\n         <header><h1>AirQualitySensor</h1></header>\n         <p>UUID:0000008D-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#airQuality\">airQuality</a></UL></TD><TD> 2 </TD><TD> GOOD </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#ozoneDensity\">ozoneDensity</a>\n            <LI><a href=\"#nitrogenDioxideDensity\">nitrogenDioxideDensity</a>\n            <LI><a href=\"#sulphurDioxideDensity\">sulphurDioxideDensity</a>\n            <LI><a href=\"#pm2_5Density\">pm2_5Density</a>\n            <LI><a href=\"#pm10Density\">pm10Density</a>\n            <LI><a href=\"#vocDensity\">vocDensity</a>\n            <LI><a href=\"#carbonMonoxideLevel\">carbonMonoxideLevel</a>\n            <LI><a href=\"#carbonDioxideLevel\">carbonDioxideLevel</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#airQuality\">airQuality</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AirQualitySensor,\n            name: \"MY_AirQualitySensor\",\n            displayName: \"MY_AirQualitySensor\",\n            airQuality: \"2\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            name: \"< STRING> \",\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AirQualitySensor -->\n      <div id=\"BatteryService\" class=\"section\">\n         <a name=\"BatteryService\"></a>\n         <header><h1>BatteryService</h1></header>\n         <p>UUID:00000096-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#batteryLevel\">batteryLevel</a></UL></TD><TD> 50 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#chargingState\">chargingState</a></UL></TD><TD> 0 </TD><TD> NOT_CHARGING </TD>\n            <tr><TD><UL><LI><a href=\"#statusLowBattery\">statusLowBattery</a></UL></TD><TD> 0 </TD><TD> BATTERY_LEVEL_NORMAL </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: BatteryService,\n            name: \"MY_BatteryService\",\n            displayName: \"MY_BatteryService\",\n            batteryLevel: \"50\",\n            chargingState: \"0\",\n            statusLowBattery: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- BatteryService -->\n      <div id=\"CameraEventRecordingManagement\" class=\"section\">\n         <a name=\"CameraEventRecordingManagement\"></a>\n         <header><h1>CameraEventRecordingManagement</h1></header>\n         <p>UUID:00000204-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#supportedCameraRecordingConfiguration\">supportedCameraRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedVideoRecordingConfiguration\">supportedVideoRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedAudioRecordingConfiguration\">supportedAudioRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#selectedCameraRecordingConfiguration\">selectedCameraRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#recordingAudioActive\">recordingAudioActive</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CameraEventRecordingManagement,\n            name: \"MY_CameraEventRecordingManagement\",\n            displayName: \"MY_CameraEventRecordingManagement\",\n            active: \"1\",\n            supportedCameraRecordingConfiguration: \"0\",\n            supportedVideoRecordingConfiguration: \"0\",\n            supportedAudioRecordingConfiguration: \"0\",\n            selectedCameraRecordingConfiguration: \"0\",\n            recordingAudioActive: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CameraEventRecordingManagement -->\n      <div id=\"CameraRTPStreamManagement\" class=\"section\">\n         <a name=\"CameraRTPStreamManagement\"></a>\n         <header><h1>CameraRTPStreamManagement</h1></header>\n         <p>UUID:00000110-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#supportedVideoStreamConfiguration\">supportedVideoStreamConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedAudioStreamConfiguration\">supportedAudioStreamConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedRTPConfiguration\">supportedRTPConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#selectedRTPStreamConfiguration\">selectedRTPStreamConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#streamingStatus\">streamingStatus</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#setupEndpoints\">setupEndpoints</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CameraRTPStreamManagement,\n            name: \"MY_CameraRTPStreamManagement\",\n            displayName: \"MY_CameraRTPStreamManagement\",\n            supportedVideoStreamConfiguration: \"0\",\n            supportedAudioStreamConfiguration: \"0\",\n            supportedRTPConfiguration: \"0\",\n            selectedRTPStreamConfiguration: \"0\",\n            streamingStatus: \"0\",\n            setupEndpoints: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CameraRTPStreamManagement -->\n      <div id=\"CameraOperatingMode\" class=\"section\">\n         <a name=\"CameraOperatingMode\"></a>\n         <header><h1>CameraOperatingMode</h1></header>\n         <p>UUID:0000021A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#eventSnapshotsActive\">eventSnapshotsActive</a></UL></TD><TD> 0 </TD><TD> DISABLE </TD>\n            <tr><TD><UL><LI><a href=\"#homeKitCameraActive\">homeKitCameraActive</a></UL></TD><TD> 0 </TD><TD> OFF </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#cameraOperatingModeIndicator\">cameraOperatingModeIndicator</a>\n            <LI><a href=\"#manuallyDisabled\">manuallyDisabled</a>\n            <LI><a href=\"#nightVision\">nightVision</a>\n            <LI><a href=\"#periodicSnapshotsActive\">periodicSnapshotsActive</a>\n            <LI><a href=\"#thirdPartyCameraActive\">thirdPartyCameraActive</a>\n            <LI><a href=\"#diagonalFieldOfView\">diagonalFieldOfView</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CameraOperatingMode,\n            name: \"MY_CameraOperatingMode\",\n            displayName: \"MY_CameraOperatingMode\",\n            eventSnapshotsActive: \"0\",\n            homeKitCameraActive: \"0\",\n            cameraOperatingModeIndicator: < BOOLEAN >,\n            manuallyDisabled: < BOOLEAN >,\n            nightVision: < BOOLEAN >,\n            periodicSnapshotsActive: < UINT8 >,\n            thirdPartyCameraActive: < UINT8 >,\n            Unknown format float,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CameraOperatingMode -->\n      <div id=\"CarbonDioxideSensor\" class=\"section\">\n         <a name=\"CarbonDioxideSensor\"></a>\n         <header><h1>CarbonDioxideSensor</h1></header>\n         <p>UUID:00000097-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#carbonDioxideDetected\">carbonDioxideDetected</a></UL></TD><TD> 0 </TD><TD> CO2_LEVELS_NORMAL </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#carbonDioxideLevel\">carbonDioxideLevel</a>\n            <LI><a href=\"#carbonDioxidePeakLevel\">carbonDioxidePeakLevel</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#carbonDioxideDetected\">carbonDioxideDetected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CarbonDioxideSensor,\n            name: \"MY_CarbonDioxideSensor\",\n            displayName: \"MY_CarbonDioxideSensor\",\n            carbonDioxideDetected: \"0\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            statusTampered: < UINT8 >,\n            Unknown format float,\n            Unknown format float,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CarbonDioxideSensor -->\n      <div id=\"CarbonMonoxideSensor\" class=\"section\">\n         <a name=\"CarbonMonoxideSensor\"></a>\n         <header><h1>CarbonMonoxideSensor</h1></header>\n         <p>UUID:0000007F-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#carbonMonoxideDetected\">carbonMonoxideDetected</a></UL></TD><TD> 0 </TD><TD> CO_LEVELS_NORMAL </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#carbonMonoxideLevel\">carbonMonoxideLevel</a>\n            <LI><a href=\"#carbonMonoxidePeakLevel\">carbonMonoxidePeakLevel</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#carbonMonoxideDetected\">carbonMonoxideDetected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CarbonMonoxideSensor,\n            name: \"MY_CarbonMonoxideSensor\",\n            displayName: \"MY_CarbonMonoxideSensor\",\n            carbonMonoxideDetected: \"0\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            statusTampered: < UINT8 >,\n            Unknown format float,\n            Unknown format float,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CarbonMonoxideSensor -->\n      <div id=\"ContactSensor\" class=\"section\">\n         <a name=\"ContactSensor\"></a>\n         <header><h1>ContactSensor</h1></header>\n         <p>UUID:00000080-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#contactSensorState\">contactSensorState</a></UL></TD><TD> 1 </TD><TD> CONTACT_NOT_DETECTED </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#contactSensorState\">contactSensorState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: ContactSensor,\n            name: \"MY_ContactSensor\",\n            displayName: \"MY_ContactSensor\",\n            contactSensorState: \"1\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- ContactSensor -->\n      <div id=\"Diagnostics\" class=\"section\">\n         <a name=\"Diagnostics\"></a>\n         <header><h1>Diagnostics</h1></header>\n         <p>UUID:00000237-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#supportedDiagnosticsSnapshot\">supportedDiagnosticsSnapshot</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Diagnostics,\n            name: \"MY_Diagnostics\",\n            displayName: \"MY_Diagnostics\",\n            supportedDiagnosticsSnapshot: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Diagnostics -->\n      <div id=\"Door\" class=\"section\">\n         <a name=\"Door\"></a>\n         <header><h1>Door</h1></header>\n         <p>UUID:00000081-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentPosition\">currentPosition</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#positionState\">positionState</a></UL></TD><TD> 2 </TD><TD> STOPPED </TD>\n            <tr><TD><UL><LI><a href=\"#targetPosition\">targetPosition</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#holdPosition\">holdPosition</a>\n            <LI><a href=\"#obstructionDetected\">obstructionDetected</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentPosition\">currentPosition</a>\n            <LI><a href=\"#targetPosition\">targetPosition</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Door,\n            name: \"MY_Door\",\n            displayName: \"MY_Door\",\n            currentPosition: \"0\",\n            positionState: \"2\",\n            targetPosition: \"0\",\n            holdPosition: < BOOLEAN >,\n            obstructionDetected: < BOOLEAN >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Door -->\n      <div id=\"DoorBell\" class=\"section\">\n         <a name=\"DoorBell\"></a>\n         <header><h1>DoorBell</h1></header>\n         <p>UUID:00000121-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#programmableSwitchEvent\">programmableSwitchEvent</a></UL></TD><TD> 0 </TD><TD> SINGLE_PRESS </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#brightness\">brightness</a>\n            <LI><a href=\"#mute\">mute</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#volume\">volume</a>\n            <LI><a href=\"#operatingStateResponse\">operatingStateResponse</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#programmableSwitchEvent\">programmableSwitchEvent</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: DoorBell,\n            name: \"MY_DoorBell\",\n            displayName: \"MY_DoorBell\",\n            programmableSwitchEvent: \"0\",\n            brightness: < INT >,\n            mute: < BOOLEAN >,\n            name: \"< STRING> \",\n            volume: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- DoorBell -->\n      <div id=\"Fan\" class=\"section\">\n         <a name=\"Fan\"></a>\n         <header><h1>Fan</h1></header>\n         <p>UUID:00000040-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#on\">on</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#rotationDirection\">rotationDirection</a>\n            <LI><a href=\"#rotationSpeed\">rotationSpeed</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#on\">on</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Fan,\n            name: \"MY_Fan\",\n            displayName: \"MY_Fan\",\n            on: \"0\",\n            rotationDirection: < INT >,\n            Unknown format float,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Fan -->\n      <div id=\"Fanv1\" class=\"section\">\n         <a name=\"Fanv1\"></a>\n         <header><h1>Fanv1</h1></header>\n         <p>UUID:00000040-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#on\">on</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#rotationDirection\">rotationDirection</a>\n            <LI><a href=\"#rotationSpeed\">rotationSpeed</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#on\">on</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Fanv1,\n            name: \"MY_Fanv1\",\n            displayName: \"MY_Fanv1\",\n            on: \"0\",\n            rotationDirection: < INT >,\n            Unknown format float,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Fanv1 -->\n      <div id=\"Fanv2\" class=\"section\">\n         <a name=\"Fanv2\"></a>\n         <header><h1>Fanv2</h1></header>\n         <p>UUID:000000B7-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#currentFanState\">currentFanState</a>\n            <LI><a href=\"#targetFanState\">targetFanState</a>\n            <LI><a href=\"#lockPhysicalControls\">lockPhysicalControls</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#rotationDirection\">rotationDirection</a>\n            <LI><a href=\"#rotationSpeed\">rotationSpeed</a>\n            <LI><a href=\"#swingMode\">swingMode</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Fanv2,\n            name: \"MY_Fanv2\",\n            displayName: \"MY_Fanv2\",\n            active: \"1\",\n            currentFanState: < UINT8 >,\n            targetFanState: < UINT8 >,\n            lockPhysicalControls: < UINT8 >,\n            name: \"< STRING> \",\n            rotationDirection: < INT >,\n            Unknown format float,\n            swingMode: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Fanv2 -->\n      <div id=\"Faucet\" class=\"section\">\n         <a name=\"Faucet\"></a>\n         <header><h1>Faucet</h1></header>\n         <p>UUID:000000D7-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Faucet,\n            name: \"MY_Faucet\",\n            displayName: \"MY_Faucet\",\n            active: \"1\",\n            name: \"< STRING> \",\n            statusFault: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Faucet -->\n      <div id=\"FilterMaintenance\" class=\"section\">\n         <a name=\"FilterMaintenance\"></a>\n         <header><h1>FilterMaintenance</h1></header>\n         <p>UUID:000000BA-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#filterChangeIndication\">filterChangeIndication</a></UL></TD><TD> 0 </TD><TD> FILTER_OK </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#filterLifeLevel\">filterLifeLevel</a>\n            <LI><a href=\"#resetFilterIndication\">resetFilterIndication</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#filterChangeIndication\">filterChangeIndication</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: FilterMaintenance,\n            name: \"MY_FilterMaintenance\",\n            displayName: \"MY_FilterMaintenance\",\n            filterChangeIndication: \"0\",\n            Unknown format float,\n            resetFilterIndication: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- FilterMaintenance -->\n      <div id=\"GarageDoorOpener\" class=\"section\">\n         <a name=\"GarageDoorOpener\"></a>\n         <header><h1>GarageDoorOpener</h1></header>\n         <p>UUID:00000041-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentDoorState\">currentDoorState</a></UL></TD><TD> 0 </TD><TD> OPEN </TD>\n            <tr><TD><UL><LI><a href=\"#targetDoorState\">targetDoorState</a></UL></TD><TD> 0 </TD><TD> OPEN </TD>\n            <tr><TD><UL><LI><a href=\"#obstructionDetected\">obstructionDetected</a></UL></TD><TD> 1 </TD><TD> TRUE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#lockCurrentState\">lockCurrentState</a>\n            <LI><a href=\"#lockTargetState\">lockTargetState</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentDoorState\">currentDoorState</a>\n            <LI><a href=\"#targetDoorState\">targetDoorState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: GarageDoorOpener,\n            name: \"MY_GarageDoorOpener\",\n            displayName: \"MY_GarageDoorOpener\",\n            currentDoorState: \"0\",\n            targetDoorState: \"0\",\n            obstructionDetected: \"1\",\n            lockCurrentState: < UINT8 >,\n            lockTargetState: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- GarageDoorOpener -->\n      <div id=\"HeaterCooler\" class=\"section\">\n         <a name=\"HeaterCooler\"></a>\n         <header><h1>HeaterCooler</h1></header>\n         <p>UUID:000000BC-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#currentHeaterCoolerState\">currentHeaterCoolerState</a></UL></TD><TD> 0 </TD><TD> INACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#targetHeaterCoolerState\">targetHeaterCoolerState</a></UL></TD><TD> 1 </TD><TD> HEAT </TD>\n            <tr><TD><UL><LI><a href=\"#currentTemperature\">currentTemperature</a></UL></TD><TD> 22.2 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#lockPhysicalControls\">lockPhysicalControls</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#rotationSpeed\">rotationSpeed</a>\n            <LI><a href=\"#swingMode\">swingMode</a>\n            <LI><a href=\"#coolingThresholdTemperature\">coolingThresholdTemperature</a>\n            <LI><a href=\"#heatingThresholdTemperature\">heatingThresholdTemperature</a>\n            <LI><a href=\"#temperatureDisplayUnits\">temperatureDisplayUnits</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: HeaterCooler,\n            name: \"MY_HeaterCooler\",\n            displayName: \"MY_HeaterCooler\",\n            active: \"1\",\n            currentHeaterCoolerState: \"0\",\n            targetHeaterCoolerState: \"1\",\n            currentTemperature: \"22.2\",\n            lockPhysicalControls: < UINT8 >,\n            name: \"< STRING> \",\n            Unknown format float,\n            swingMode: < UINT8 >,\n            Unknown format float,\n            Unknown format float,\n            temperatureDisplayUnits: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- HeaterCooler -->\n      <div id=\"HumidifierDehumidifier\" class=\"section\">\n         <a name=\"HumidifierDehumidifier\"></a>\n         <header><h1>HumidifierDehumidifier</h1></header>\n         <p>UUID:000000BD-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentRelativeHumidity\">currentRelativeHumidity</a></UL></TD><TD> 60 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#currentHumidifierDehumidifierState\">currentHumidifierDehumidifierState</a></UL></TD><TD> 1 </TD><TD> IDLE </TD>\n            <tr><TD><UL><LI><a href=\"#targetHumidifierDehumidifierState\">targetHumidifierDehumidifierState</a></UL></TD><TD> 2 </TD><TD> DEHUMIDIFIER </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#lockPhysicalControls\">lockPhysicalControls</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#relativeHumidityDehumidifierThreshold\">relativeHumidityDehumidifierThreshold</a>\n            <LI><a href=\"#relativeHumidityHumidifierThreshold\">relativeHumidityHumidifierThreshold</a>\n            <LI><a href=\"#rotationSpeed\">rotationSpeed</a>\n            <LI><a href=\"#swingMode\">swingMode</a>\n            <LI><a href=\"#waterLevel\">waterLevel</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: HumidifierDehumidifier,\n            name: \"MY_HumidifierDehumidifier\",\n            displayName: \"MY_HumidifierDehumidifier\",\n            currentRelativeHumidity: \"60\",\n            currentHumidifierDehumidifierState: \"1\",\n            targetHumidifierDehumidifierState: \"2\",\n            active: \"1\",\n            lockPhysicalControls: < UINT8 >,\n            name: \"< STRING> \",\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            swingMode: < UINT8 >,\n            Unknown format float,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- HumidifierDehumidifier -->\n      <div id=\"HumiditySensor\" class=\"section\">\n         <a name=\"HumiditySensor\"></a>\n         <header><h1>HumiditySensor</h1></header>\n         <p>UUID:00000082-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentRelativeHumidity\">currentRelativeHumidity</a></UL></TD><TD> 60 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentRelativeHumidity\">currentRelativeHumidity</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: HumiditySensor,\n            name: \"MY_HumiditySensor\",\n            displayName: \"MY_HumiditySensor\",\n            currentRelativeHumidity: \"60\",\n            name: \"< STRING> \",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- HumiditySensor -->\n      <div id=\"InputSource\" class=\"section\">\n         <a name=\"InputSource\"></a>\n         <header><h1>InputSource</h1></header>\n         <p>UUID:000000D9-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#configuredName\">configuredName</a></UL></TD><TD> My_InputSource </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#inputSourceType\">inputSourceType</a></UL></TD><TD> 1 </TD><TD> HOME_SCREEN </TD>\n            <tr><TD><UL><LI><a href=\"#isConfigured\">isConfigured</a></UL></TD><TD> 1 </TD><TD> CONFIGURED </TD>\n            <tr><TD><UL><LI><a href=\"#currentVisibilityState\">currentVisibilityState</a></UL></TD><TD> 0 </TD><TD> SHOWN </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#identifier\">identifier</a>\n            <LI><a href=\"#inputDeviceType\">inputDeviceType</a>\n            <LI><a href=\"#targetVisibilityState\">targetVisibilityState</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentVisibilityState\">currentVisibilityState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: InputSource,\n            name: \"MY_InputSource\",\n            displayName: \"MY_InputSource\",\n            configuredName: \"My_InputSource\",\n            inputSourceType: \"1\",\n            isConfigured: \"1\",\n            currentVisibilityState: \"0\",\n            identifier: < UINT32 >,\n            inputDeviceType: < UINT8 >,\n            targetVisibilityState: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- InputSource -->\n      <div id=\"IrrigationSystem\" class=\"section\">\n         <a name=\"IrrigationSystem\"></a>\n         <header><h1>IrrigationSystem</h1></header>\n         <p>UUID:000000CF-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#programMode\">programMode</a></UL></TD><TD> 0 </TD><TD> NO_PROGRAM_SCHEDULED </TD>\n            <tr><TD><UL><LI><a href=\"#inUse\">inUse</a></UL></TD><TD> 1 </TD><TD> IN_USE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#remainingDuration\">remainingDuration</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: IrrigationSystem,\n            name: \"MY_IrrigationSystem\",\n            displayName: \"MY_IrrigationSystem\",\n            active: \"1\",\n            programMode: \"0\",\n            inUse: \"1\",\n            name: \"< STRING> \",\n            remainingDuration: < UINT32 >,\n            statusFault: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- IrrigationSystem -->\n      <div id=\"LeakSensor\" class=\"section\">\n         <a name=\"LeakSensor\"></a>\n         <header><h1>LeakSensor</h1></header>\n         <p>UUID:00000083-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#leakDetected\">leakDetected</a></UL></TD><TD> 0 </TD><TD> LEAK_NOT_DETECTED </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#leakDetected\">leakDetected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: LeakSensor,\n            name: \"MY_LeakSensor\",\n            displayName: \"MY_LeakSensor\",\n            leakDetected: \"0\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- LeakSensor -->\n      <div id=\"LightSensor\" class=\"section\">\n         <a name=\"LightSensor\"></a>\n         <header><h1>LightSensor</h1></header>\n         <p>UUID:00000084-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentAmbientLightLevel\">currentAmbientLightLevel</a></UL></TD><TD> 1 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentAmbientLightLevel\">currentAmbientLightLevel</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: LightSensor,\n            name: \"MY_LightSensor\",\n            displayName: \"MY_LightSensor\",\n            currentAmbientLightLevel: \"1\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- LightSensor -->\n      <div id=\"Lightbulb\" class=\"section\">\n         <a name=\"Lightbulb\"></a>\n         <header><h1>Lightbulb</h1></header>\n         <p>UUID:00000043-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#on\">on</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#brightness\">brightness</a>\n            <LI><a href=\"#hue\">hue</a>\n            <LI><a href=\"#saturation\">saturation</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#colorTemperature\">colorTemperature</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#on\">on</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Lightbulb,\n            name: \"MY_Lightbulb\",\n            displayName: \"MY_Lightbulb\",\n            on: \"0\",\n            brightness: < INT >,\n            Unknown format float,\n            Unknown format float,\n            name: \"< STRING> \",\n            colorTemperature: < INT >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Lightbulb -->\n      <div id=\"LockManagement\" class=\"section\">\n         <a name=\"LockManagement\"></a>\n         <header><h1>LockManagement</h1></header>\n         <p>UUID:00000044-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#lockControlPoint\">lockControlPoint</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#version\">version</a></UL></TD><TD> 0.0.0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#administratorOnlyAccess\">administratorOnlyAccess</a>\n            <LI><a href=\"#audioFeedback\">audioFeedback</a>\n            <LI><a href=\"#currentDoorState\">currentDoorState</a>\n            <LI><a href=\"#lockManagementAutoSecurityTimeout\">lockManagementAutoSecurityTimeout</a>\n            <LI><a href=\"#lockLastKnownAction\">lockLastKnownAction</a>\n            <LI><a href=\"#logs\">logs</a>\n            <LI><a href=\"#motionDetected\">motionDetected</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: LockManagement,\n            name: \"MY_LockManagement\",\n            displayName: \"MY_LockManagement\",\n            lockControlPoint: \"0\",\n            version: \"0.0.0\",\n            administratorOnlyAccess: < BOOLEAN >,\n            audioFeedback: < BOOLEAN >,\n            currentDoorState: < UINT8 >,\n            lockManagementAutoSecurityTimeout: < UINT32 >,\n            lockLastKnownAction: < UINT8 >,\n            motionDetected: < BOOLEAN >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- LockManagement -->\n      <div id=\"LockMechanism\" class=\"section\">\n         <a name=\"LockMechanism\"></a>\n         <header><h1>LockMechanism</h1></header>\n         <p>UUID:00000045-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#lockCurrentState\">lockCurrentState</a></UL></TD><TD> 0 </TD><TD> UNSECURED </TD>\n            <tr><TD><UL><LI><a href=\"#lockTargetState\">lockTargetState</a></UL></TD><TD> 0 </TD><TD> UNSECURED </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#lockCurrentState\">lockCurrentState</a>\n            <LI><a href=\"#lockTargetState\">lockTargetState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: LockMechanism,\n            name: \"MY_LockMechanism\",\n            displayName: \"MY_LockMechanism\",\n            lockCurrentState: \"0\",\n            lockTargetState: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- LockMechanism -->\n      <div id=\"Microphone\" class=\"section\">\n         <a name=\"Microphone\"></a>\n         <header><h1>Microphone</h1></header>\n         <p>UUID:00000112-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#mute\">mute</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#volume\">volume</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#mute\">mute</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Microphone,\n            name: \"MY_Microphone\",\n            displayName: \"MY_Microphone\",\n            mute: \"0\",\n            volume: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Microphone -->\n      <div id=\"MotionSensor\" class=\"section\">\n         <a name=\"MotionSensor\"></a>\n         <header><h1>MotionSensor</h1></header>\n         <p>UUID:00000085-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#motionDetected\">motionDetected</a></UL></TD><TD> 1 </TD><TD> TRUE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#motionDetected\">motionDetected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: MotionSensor,\n            name: \"MY_MotionSensor\",\n            displayName: \"MY_MotionSensor\",\n            motionDetected: \"1\",\n            name: \"< STRING> \",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            statusTampered: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- MotionSensor -->\n      <div id=\"OccupancySensor\" class=\"section\">\n         <a name=\"OccupancySensor\"></a>\n         <header><h1>OccupancySensor</h1></header>\n         <p>UUID:00000086-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#occupancyDetected\">occupancyDetected</a></UL></TD><TD> 0 </TD><TD> OCCUPANCY_NOT_DETECTED </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#occupancyDetected\">occupancyDetected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: OccupancySensor,\n            name: \"MY_OccupancySensor\",\n            displayName: \"MY_OccupancySensor\",\n            occupancyDetected: \"0\",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- OccupancySensor -->\n      <div id=\"Outlet\" class=\"section\">\n         <a name=\"Outlet\"></a>\n         <header><h1>Outlet</h1></header>\n         <p>UUID:00000047-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#on\">on</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n            <tr><TD><UL><LI><a href=\"#outletInUse\">outletInUse</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#on\">on</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Outlet,\n            name: \"MY_Outlet\",\n            displayName: \"MY_Outlet\",\n            on: \"0\",\n            outletInUse: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Outlet -->\n      <div id=\"Pairing\" class=\"section\">\n         <a name=\"Pairing\"></a>\n         <header><h1>Pairing</h1></header>\n         <p>UUID:00000055-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#listPairings\">listPairings</a></UL></TD><TD> 1 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#pairSetup\">pairSetup</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#pairVerify\">pairVerify</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#pairingFeatures\">pairingFeatures</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#pairingFeatures\">pairingFeatures</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Pairing,\n            name: \"MY_Pairing\",\n            displayName: \"MY_Pairing\",\n            listPairings: \"1\",\n            pairSetup: \"0\",\n            pairVerify: \"0\",\n            pairingFeatures: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Pairing -->\n      <div id=\"PowerManagement\" class=\"section\">\n         <a name=\"PowerManagement\"></a>\n         <header><h1>PowerManagement</h1></header>\n         <p>UUID:00000221-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#wakeConfiguration\">wakeConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: PowerManagement,\n            name: \"MY_PowerManagement\",\n            displayName: \"MY_PowerManagement\",\n            wakeConfiguration: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- PowerManagement -->\n      <div id=\"ProtocolInformation\" class=\"section\">\n         <a name=\"ProtocolInformation\"></a>\n         <header><h1>ProtocolInformation</h1></header>\n         <p>UUID:000000A2-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#version\">version</a></UL></TD><TD> 1.2.3 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#version\">version</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: ProtocolInformation,\n            name: \"MY_ProtocolInformation\",\n            displayName: \"MY_ProtocolInformation\",\n            version: \"1.2.3\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- ProtocolInformation -->\n      <div id=\"Relay\" class=\"section\">\n         <a name=\"Relay\"></a>\n         <header><h1>Relay</h1></header>\n         <p>UUID:0000005A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#relayEnabled\">relayEnabled</a></UL></TD><TD> 1 </TD><TD> TRUE </TD>\n            <tr><TD><UL><LI><a href=\"#relayState\">relayState</a></UL></TD><TD> 1 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#relayControlPoint\">relayControlPoint</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#relayEnabled\">relayEnabled</a>\n            <LI><a href=\"#relayState\">relayState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Relay,\n            name: \"MY_Relay\",\n            displayName: \"MY_Relay\",\n            relayEnabled: \"1\",\n            relayState: \"1\",\n            relayControlPoint: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Relay -->\n      <div id=\"SecuritySystem\" class=\"section\">\n         <a name=\"SecuritySystem\"></a>\n         <header><h1>SecuritySystem</h1></header>\n         <p>UUID:0000007E-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#securitySystemCurrentState\">securitySystemCurrentState</a></UL></TD><TD> 3 </TD><TD> DISARMED </TD>\n            <tr><TD><UL><LI><a href=\"#securitySystemTargetState\">securitySystemTargetState</a></UL></TD><TD> 3 </TD><TD> DISARM </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#securitySystemAlarmType\">securitySystemAlarmType</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#securitySystemCurrentState\">securitySystemCurrentState</a>\n            <LI><a href=\"#securitySystemTargetState\">securitySystemTargetState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: SecuritySystem,\n            name: \"MY_SecuritySystem\",\n            displayName: \"MY_SecuritySystem\",\n            securitySystemCurrentState: \"3\",\n            securitySystemTargetState: \"3\",\n            name: \"< STRING> \",\n            securitySystemAlarmType: < UINT8 >,\n            statusFault: < UINT8 >,\n            statusTampered: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- SecuritySystem -->\n      <div id=\"ServiceLabel\" class=\"section\">\n         <a name=\"ServiceLabel\"></a>\n         <header><h1>ServiceLabel</h1></header>\n         <p>UUID:000000CC-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#serviceLabelNamespace\">serviceLabelNamespace</a></UL></TD><TD> 0 </TD><TD> DOTS </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#serviceLabelNamespace\">serviceLabelNamespace</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: ServiceLabel,\n            name: \"MY_ServiceLabel\",\n            displayName: \"MY_ServiceLabel\",\n            serviceLabelNamespace: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- ServiceLabel -->\n      <div id=\"Siri\" class=\"section\">\n         <a name=\"Siri\"></a>\n         <header><h1>Siri</h1></header>\n         <p>UUID:00000133-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#siriInputType\">siriInputType</a></UL></TD><TD> 0 </TD><TD> PUSH_BUTTON_TRIGGERED_APPLE_TV </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#multiFunctionButton\">multiFunctionButton</a>\n            <LI><a href=\"#siriEnable\">siriEnable</a>\n            <LI><a href=\"#siriEngineVersion\">siriEngineVersion</a>\n            <LI><a href=\"#siriLightOnUse\">siriLightOnUse</a>\n            <LI><a href=\"#siriListening\">siriListening</a>\n            <LI><a href=\"#siriTouchToUse\">siriTouchToUse</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Siri,\n            name: \"MY_Siri\",\n            displayName: \"MY_Siri\",\n            siriInputType: \"0\",\n            multiFunctionButton: < UINT8 >,\n            siriEnable: < UINT8 >,\n            siriEngineVersion: \"< STRING> \",\n            siriLightOnUse: < UINT8 >,\n            siriListening: < UINT8 >,\n            siriTouchToUse: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Siri -->\n      <div id=\"Slats\" class=\"section\">\n         <a name=\"Slats\"></a>\n         <header><h1>Slats</h1></header>\n         <p>UUID:000000B9-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentSlatState\">currentSlatState</a></UL></TD><TD> 0 </TD><TD> FIXED </TD>\n            <tr><TD><UL><LI><a href=\"#slatType\">slatType</a></UL></TD><TD> 0 </TD><TD> HORIZONTAL </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#swingMode\">swingMode</a>\n            <LI><a href=\"#currentTiltAngle\">currentTiltAngle</a>\n            <LI><a href=\"#targetTiltAngle\">targetTiltAngle</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentSlatState\">currentSlatState</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Slats,\n            name: \"MY_Slats\",\n            displayName: \"MY_Slats\",\n            currentSlatState: \"0\",\n            slatType: \"0\",\n            name: \"< STRING> \",\n            swingMode: < UINT8 >,\n            currentTiltAngle: < INT >,\n            targetTiltAngle: < INT >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Slats -->\n      <div id=\"SmartSpeaker\" class=\"section\">\n         <a name=\"SmartSpeaker\"></a>\n         <header><h1>SmartSpeaker</h1></header>\n         <p>UUID:00000228-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentMediaState\">currentMediaState</a></UL></TD><TD> 2 </TD><TD> STOP </TD>\n            <tr><TD><UL><LI><a href=\"#targetMediaState\">targetMediaState</a></UL></TD><TD> 2 </TD><TD> STOP </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#airPlayEnable\">airPlayEnable</a>\n            <LI><a href=\"#configuredName\">configuredName</a>\n            <LI><a href=\"#mute\">mute</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#volume\">volume</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: SmartSpeaker,\n            name: \"MY_SmartSpeaker\",\n            displayName: \"MY_SmartSpeaker\",\n            currentMediaState: \"2\",\n            targetMediaState: \"2\",\n            airPlayEnable: < UINT8 >,\n            configuredName: \"< STRING> \",\n            mute: < BOOLEAN >,\n            name: \"< STRING> \",\n            volume: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- SmartSpeaker -->\n      <div id=\"SmokeSensor\" class=\"section\">\n         <a name=\"SmokeSensor\"></a>\n         <header><h1>SmokeSensor</h1></header>\n         <p>UUID:00000087-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#smokeDetected\">smokeDetected</a></UL></TD><TD> 0 </TD><TD> SMOKE_NOT_DETECTED </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#smokeDetected\">smokeDetected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: SmokeSensor,\n            name: \"MY_SmokeSensor\",\n            displayName: \"MY_SmokeSensor\",\n            smokeDetected: \"0\",\n            name: \"< STRING> \",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            statusTampered: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- SmokeSensor -->\n      <div id=\"Speaker\" class=\"section\">\n         <a name=\"Speaker\"></a>\n         <header><h1>Speaker</h1></header>\n         <p>UUID:00000113-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#mute\">mute</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#active\">active</a>\n            <LI><a href=\"#volume\">volume</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#mute\">mute</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Speaker,\n            name: \"MY_Speaker\",\n            displayName: \"MY_Speaker\",\n            mute: \"0\",\n            active: < UINT8 >,\n            volume: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Speaker -->\n      <div id=\"StatefulProgrammableSwitch\" class=\"section\">\n         <a name=\"StatefulProgrammableSwitch\"></a>\n         <header><h1>StatefulProgrammableSwitch</h1></header>\n         <p>UUID:00000088-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#programmableSwitchEvent\">programmableSwitchEvent</a></UL></TD><TD> 0 </TD><TD> SINGLE_PRESS </TD>\n            <tr><TD><UL><LI><a href=\"#programmableSwitchOutputState\">programmableSwitchOutputState</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#programmableSwitchEvent\">programmableSwitchEvent</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: StatefulProgrammableSwitch,\n            name: \"MY_StatefulProgrammableSwitch\",\n            displayName: \"MY_StatefulProgrammableSwitch\",\n            programmableSwitchEvent: \"0\",\n            programmableSwitchOutputState: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- StatefulProgrammableSwitch -->\n      <div id=\"StatelessProgrammableSwitch\" class=\"section\">\n         <a name=\"StatelessProgrammableSwitch\"></a>\n         <header><h1>StatelessProgrammableSwitch</h1></header>\n         <p>UUID:00000089-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#programmableSwitchEvent\">programmableSwitchEvent</a></UL></TD><TD> 0 </TD><TD> SINGLE_PRESS </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#serviceLabelIndex\">serviceLabelIndex</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#programmableSwitchEvent\">programmableSwitchEvent</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: StatelessProgrammableSwitch,\n            name: \"MY_StatelessProgrammableSwitch\",\n            displayName: \"MY_StatelessProgrammableSwitch\",\n            programmableSwitchEvent: \"0\",\n            name: \"< STRING> \",\n            serviceLabelIndex: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- StatelessProgrammableSwitch -->\n      <div id=\"Switch\" class=\"section\">\n         <a name=\"Switch\"></a>\n         <header><h1>Switch</h1></header>\n         <p>UUID:00000049-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#on\">on</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#on\">on</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Switch,\n            name: \"MY_Switch\",\n            displayName: \"MY_Switch\",\n            on: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Switch -->\n      <div id=\"TargetControl\" class=\"section\">\n         <a name=\"TargetControl\"></a>\n         <header><h1>TargetControl</h1></header>\n         <p>UUID:00000125-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#activeIdentifier\">activeIdentifier</a></UL></TD><TD> 7 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#buttonEvent\">buttonEvent</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TargetControl,\n            name: \"MY_TargetControl\",\n            displayName: \"MY_TargetControl\",\n            active: \"1\",\n            activeIdentifier: \"7\",\n            buttonEvent: \"0\",\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TargetControl -->\n      <div id=\"TargetControlManagement\" class=\"section\">\n         <a name=\"TargetControlManagement\"></a>\n         <header><h1>TargetControlManagement</h1></header>\n         <p>UUID:00000122-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#targetControlSupportedConfiguration\">targetControlSupportedConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#targetControlList\">targetControlList</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TargetControlManagement,\n            name: \"MY_TargetControlManagement\",\n            displayName: \"MY_TargetControlManagement\",\n            targetControlSupportedConfiguration: \"0\",\n            targetControlList: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TargetControlManagement -->\n      <div id=\"Television\" class=\"section\">\n         <a name=\"Television\"></a>\n         <header><h1>Television</h1></header>\n         <p>UUID:000000D8-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#activeIdentifier\">activeIdentifier</a></UL></TD><TD> 123 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#configuredName\">configuredName</a></UL></TD><TD> My_Tv </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#remoteKey\">remoteKey</a></UL></TD><TD> 8 </TD><TD> SELECT </TD>\n            <tr><TD><UL><LI><a href=\"#sleepDiscoveryMode\">sleepDiscoveryMode</a></UL></TD><TD> 1 </TD><TD> ALWAYS_DISCOVERABLE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#brightness\">brightness</a>\n            <LI><a href=\"#closedCaptions\">closedCaptions</a>\n            <LI><a href=\"#displayOrder\">displayOrder</a>\n            <LI><a href=\"#currentMediaState\">currentMediaState</a>\n            <LI><a href=\"#targetMediaState\">targetMediaState</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#pictureMode\">pictureMode</a>\n            <LI><a href=\"#powerModeSelection\">powerModeSelection</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Television,\n            name: \"MY_Television\",\n            displayName: \"MY_Television\",\n            active: \"1\",\n            activeIdentifier: \"123\",\n            configuredName: \"My_Tv\",\n            remoteKey: \"8\",\n            sleepDiscoveryMode: \"1\",\n            brightness: < INT >,\n            closedCaptions: < UINT8 >,\n            currentMediaState: < UINT8 >,\n            targetMediaState: < UINT8 >,\n            name: \"< STRING> \",\n            pictureMode: < UINT8 >,\n            powerModeSelection: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Television -->\n      <div id=\"TelevisionSpeaker\" class=\"section\">\n         <a name=\"TelevisionSpeaker\"></a>\n         <header><h1>TelevisionSpeaker</h1></header>\n         <p>UUID:00000113-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#mute\">mute</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#active\">active</a>\n            <LI><a href=\"#volume\">volume</a>\n            <LI><a href=\"#volumeControlType\">volumeControlType</a>\n            <LI><a href=\"#volumeSelector\">volumeSelector</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#mute\">mute</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TelevisionSpeaker,\n            name: \"MY_TelevisionSpeaker\",\n            displayName: \"MY_TelevisionSpeaker\",\n            mute: \"0\",\n            active: < UINT8 >,\n            volume: < UINT8 >,\n            volumeControlType: < UINT8 >,\n            volumeSelector: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TelevisionSpeaker -->\n      <div id=\"TemperatureSensor\" class=\"section\">\n         <a name=\"TemperatureSensor\"></a>\n         <header><h1>TemperatureSensor</h1></header>\n         <p>UUID:0000008A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentTemperature\">currentTemperature</a></UL></TD><TD> 50 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#statusActive\">statusActive</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n            <LI><a href=\"#statusLowBattery\">statusLowBattery</a>\n            <LI><a href=\"#statusTampered\">statusTampered</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentTemperature\">currentTemperature</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TemperatureSensor,\n            name: \"MY_TemperatureSensor\",\n            displayName: \"MY_TemperatureSensor\",\n            currentTemperature: \"50\",\n            name: \"< STRING> \",\n            statusActive: < BOOLEAN >,\n            statusFault: < UINT8 >,\n            statusLowBattery: < UINT8 >,\n            statusTampered: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TemperatureSensor -->\n      <div id=\"Thermostat\" class=\"section\">\n         <a name=\"Thermostat\"></a>\n         <header><h1>Thermostat</h1></header>\n         <p>UUID:0000004A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentHeatingCoolingState\">currentHeatingCoolingState</a></UL></TD><TD> 0 </TD><TD> OFF </TD>\n            <tr><TD><UL><LI><a href=\"#targetHeatingCoolingState\">targetHeatingCoolingState</a></UL></TD><TD> 0 </TD><TD> OFF </TD>\n            <tr><TD><UL><LI><a href=\"#currentTemperature\">currentTemperature</a></UL></TD><TD> 50 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#targetTemperature\">targetTemperature</a></UL></TD><TD> 50 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#temperatureDisplayUnits\">temperatureDisplayUnits</a></UL></TD><TD> 0 </TD><TD> CELSIUS </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#currentRelativeHumidity\">currentRelativeHumidity</a>\n            <LI><a href=\"#targetRelativeHumidity\">targetRelativeHumidity</a>\n            <LI><a href=\"#coolingThresholdTemperature\">coolingThresholdTemperature</a>\n            <LI><a href=\"#heatingThresholdTemperature\">heatingThresholdTemperature</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentTemperature\">currentTemperature</a>\n            <LI><a href=\"#targetTemperature\">targetTemperature</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Thermostat,\n            name: \"MY_Thermostat\",\n            displayName: \"MY_Thermostat\",\n            currentHeatingCoolingState: \"0\",\n            targetHeatingCoolingState: \"0\",\n            currentTemperature: \"50\",\n            targetTemperature: \"50\",\n            temperatureDisplayUnits: \"0\",\n            name: \"< STRING> \",\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            Unknown format float,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Thermostat -->\n      <div id=\"TransferTransportManagement\" class=\"section\">\n         <a name=\"TransferTransportManagement\"></a>\n         <header><h1>TransferTransportManagement</h1></header>\n         <p>UUID:00000203-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#supportedTransferTransportConfiguration\">supportedTransferTransportConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#setupTransferTransport\">setupTransferTransport</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TransferTransportManagement,\n            name: \"MY_TransferTransportManagement\",\n            displayName: \"MY_TransferTransportManagement\",\n            supportedTransferTransportConfiguration: \"0\",\n            setupTransferTransport: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TransferTransportManagement -->\n      <div id=\"TunneledBTLEAccessoryService\" class=\"section\">\n         <a name=\"TunneledBTLEAccessoryService\"></a>\n         <header><h1>TunneledBTLEAccessoryService</h1></header>\n         <p>UUID:00000056-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#name\">name</a></UL></TD><TD> My_TunnelB </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#accessoryIdentifier\">accessoryIdentifier</a></UL></TD><TD> TLB </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#tunneledAccessoryStateNumber\">tunneledAccessoryStateNumber</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#tunneledAccessoryConnected\">tunneledAccessoryConnected</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n            <tr><TD><UL><LI><a href=\"#tunneledAccessoryAdvertising\">tunneledAccessoryAdvertising</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n            <tr><TD><UL><LI><a href=\"#tunnelConnectionTimeout\">tunnelConnectionTimeout</a></UL></TD><TD> 5000 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#tunneledAccessoryConnected\">tunneledAccessoryConnected</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TunneledBTLEAccessoryService,\n            name: \"MY_TunneledBTLEAccessoryService\",\n            displayName: \"MY_TunneledBTLEAccessoryService\",\n            name: \"My_TunnelB\",\n            accessoryIdentifier: \"TLB\",\n            tunneledAccessoryStateNumber: \"0\",\n            tunneledAccessoryConnected: \"0\",\n            tunneledAccessoryAdvertising: \"0\",\n            tunnelConnectionTimeout: \"5000\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TunneledBTLEAccessoryService -->\n      <div id=\"Valve\" class=\"section\">\n         <a name=\"Valve\"></a>\n         <header><h1>Valve</h1></header>\n         <p>UUID:000000D0-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#inUse\">inUse</a></UL></TD><TD> 1 </TD><TD> IN_USE </TD>\n            <tr><TD><UL><LI><a href=\"#valveType\">valveType</a></UL></TD><TD> 0 </TD><TD> GENERIC_VALVE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#isConfigured\">isConfigured</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#remainingDuration\">remainingDuration</a>\n            <LI><a href=\"#serviceLabelIndex\">serviceLabelIndex</a>\n            <LI><a href=\"#setDuration\">setDuration</a>\n            <LI><a href=\"#statusFault\">statusFault</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Valve,\n            name: \"MY_Valve\",\n            displayName: \"MY_Valve\",\n            active: \"1\",\n            inUse: \"1\",\n            valveType: \"0\",\n            isConfigured: < UINT8 >,\n            name: \"< STRING> \",\n            remainingDuration: < UINT32 >,\n            serviceLabelIndex: < UINT8 >,\n            setDuration: < UINT32 >,\n            statusFault: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Valve -->\n      <div id=\"WiFiRouter\" class=\"section\">\n         <a name=\"WiFiRouter\"></a>\n         <header><h1>WiFiRouter</h1></header>\n         <p>UUID:0000020A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#configuredName\">configuredName</a></UL></TD><TD> My_WiFiRouter </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#managedNetworkEnable\">managedNetworkEnable</a></UL></TD><TD> 0 </TD><TD> DISABLED </TD>\n            <tr><TD><UL><LI><a href=\"#networkAccessViolationControl\">networkAccessViolationControl</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#networkClientProfileControl\">networkClientProfileControl</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#networkClientStatusControl\">networkClientStatusControl</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#routerStatus\">routerStatus</a></UL></TD><TD> 0 </TD><TD> READY </TD>\n            <tr><TD><UL><LI><a href=\"#supportedRouterConfiguration\">supportedRouterConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#wanConfigurationList\">wanConfigurationList</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#wanStatusList\">wanStatusList</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: WiFiRouter,\n            name: \"MY_WiFiRouter\",\n            displayName: \"MY_WiFiRouter\",\n            configuredName: \"My_WiFiRouter\",\n            managedNetworkEnable: \"0\",\n            networkAccessViolationControl: \"0\",\n            networkClientProfileControl: \"0\",\n            networkClientStatusControl: \"0\",\n            routerStatus: \"0\",\n            supportedRouterConfiguration: \"0\",\n            wanConfigurationList: \"0\",\n            wanStatusList: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- WiFiRouter -->\n      <div id=\"WiFiSatellite\" class=\"section\">\n         <a name=\"WiFiSatellite\"></a>\n         <header><h1>WiFiSatellite</h1></header>\n         <p>UUID:0000020F-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#wifiSatelliteStatus\">wifiSatelliteStatus</a></UL></TD><TD> 2 </TD><TD> NOT_CONNECTED </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: WiFiSatellite,\n            name: \"MY_WiFiSatellite\",\n            displayName: \"MY_WiFiSatellite\",\n            wifiSatelliteStatus: \"2\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- WiFiSatellite -->\n      <div id=\"Window\" class=\"section\">\n         <a name=\"Window\"></a>\n         <header><h1>Window</h1></header>\n         <p>UUID:0000008B-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentPosition\">currentPosition</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#positionState\">positionState</a></UL></TD><TD> 2 </TD><TD> STOPPED </TD>\n            <tr><TD><UL><LI><a href=\"#targetPosition\">targetPosition</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#obstructionDetected\">obstructionDetected</a>\n            <LI><a href=\"#holdPosition\">holdPosition</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentPosition\">currentPosition</a>\n            <LI><a href=\"#targetPosition\">targetPosition</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Window,\n            name: \"MY_Window\",\n            displayName: \"MY_Window\",\n            currentPosition: \"0\",\n            positionState: \"2\",\n            targetPosition: \"0\",\n            name: \"< STRING> \",\n            obstructionDetected: < BOOLEAN >,\n            holdPosition: < BOOLEAN >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Window -->\n      <div id=\"WindowCovering\" class=\"section\">\n         <a name=\"WindowCovering\"></a>\n         <header><h1>WindowCovering</h1></header>\n         <p>UUID:0000008C-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentPosition\">currentPosition</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#positionState\">positionState</a></UL></TD><TD> 2 </TD><TD> STOPPED </TD>\n            <tr><TD><UL><LI><a href=\"#targetPosition\">targetPosition</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#currentHorizontalTiltAngle\">currentHorizontalTiltAngle</a>\n            <LI><a href=\"#targetHorizontalTiltAngle\">targetHorizontalTiltAngle</a>\n            <LI><a href=\"#name\">name</a>\n            <LI><a href=\"#obstructionDetected\">obstructionDetected</a>\n            <LI><a href=\"#holdPosition\">holdPosition</a>\n            <LI><a href=\"#currentVerticalTiltAngle\">currentVerticalTiltAngle</a>\n            <LI><a href=\"#targetVerticalTiltAngle\">targetVerticalTiltAngle</a>\n         </UL>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#currentPosition\">currentPosition</a>\n            <LI><a href=\"#targetPosition\">targetPosition</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: WindowCovering,\n            name: \"MY_WindowCovering\",\n            displayName: \"MY_WindowCovering\",\n            currentPosition: \"0\",\n            positionState: \"2\",\n            targetPosition: \"0\",\n            currentHorizontalTiltAngle: < INT >,\n            targetHorizontalTiltAngle: < INT >,\n            name: \"< STRING> \",\n            obstructionDetected: < BOOLEAN >,\n            holdPosition: < BOOLEAN >,\n            currentVerticalTiltAngle: < INT >,\n            targetVerticalTiltAngle: < INT >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- WindowCovering -->\n      <div id=\"AccessoryMetrics\" class=\"section\">\n         <a name=\"AccessoryMetrics\"></a>\n         <header><h1>AccessoryMetrics</h1></header>\n         <p>UUID:00000270-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#MetricsBufferFullState\">MetricsBufferFullState</a></UL></TD><TD> 1 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedMetrics\">supportedMetrics</a></UL></TD><TD>  </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Default Polling Characteristics</H3>\n         <note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\n         <UL>\n            <LI><a href=\"#active\">active</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AccessoryMetrics,\n            name: \"MY_AccessoryMetrics\",\n            displayName: \"MY_AccessoryMetrics\",\n            active: \"1\",\n            MetricsBufferFullState: \"1\",\n            supportedMetrics: \"\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AccessoryMetrics -->\n      <div id=\"AssetUpdate\" class=\"section\">\n         <a name=\"AssetUpdate\"></a>\n         <header><h1>AssetUpdate</h1></header>\n         <p>UUID:00000267-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#assetUpdateReadiness\">assetUpdateReadiness</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedAssetTypes\">supportedAssetTypes</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AssetUpdate,\n            name: \"MY_AssetUpdate\",\n            displayName: \"MY_AssetUpdate\",\n            assetUpdateReadiness: \"0\",\n            supportedAssetTypes: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AssetUpdate -->\n      <div id=\"Assistant\" class=\"section\">\n         <a name=\"Assistant\"></a>\n         <header><h1>Assistant</h1></header>\n         <p>UUID:0000026A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#identifier\">identifier</a></UL></TD><TD> Some Identifier </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#name\">name</a></UL></TD><TD> Unnamed Assistant </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Assistant,\n            name: \"MY_Assistant\",\n            displayName: \"MY_Assistant\",\n            active: \"1\",\n            identifier: \"Some Identifier\",\n            name: \"Unnamed Assistant\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Assistant -->\n      <div id=\"AudioStreamManagement\" class=\"section\">\n         <a name=\"AudioStreamManagement\"></a>\n         <header><h1>AudioStreamManagement</h1></header>\n         <p>UUID:00000127-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#supportedAudioStreamConfiguration\">supportedAudioStreamConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#selectedAudioStreamConfiguration\">selectedAudioStreamConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AudioStreamManagement,\n            name: \"MY_AudioStreamManagement\",\n            displayName: \"MY_AudioStreamManagement\",\n            supportedAudioStreamConfiguration: \"0\",\n            selectedAudioStreamConfiguration: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AudioStreamManagement -->\n      <div id=\"Battery\" class=\"section\">\n         <a name=\"Battery\"></a>\n         <header><h1>Battery</h1></header>\n         <p>UUID:00000096-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#statusLowBattery\">statusLowBattery</a></UL></TD><TD> 0 </TD><TD> BATTERY_LEVEL_NORMAL </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#batteryLevel\">batteryLevel</a>\n            <LI><a href=\"#chargingState\">chargingState</a>\n            <LI><a href=\"#name\">name</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: Battery,\n            name: \"MY_Battery\",\n            displayName: \"MY_Battery\",\n            statusLowBattery: \"0\",\n            batteryLevel: < UINT8 >,\n            chargingState: < UINT8 >,\n            name: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- Battery -->\n      <div id=\"CameraRecordingManagement\" class=\"section\">\n         <a name=\"CameraRecordingManagement\"></a>\n         <header><h1>CameraRecordingManagement</h1></header>\n         <p>UUID:00000204-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#supportedCameraRecordingConfiguration\">supportedCameraRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedVideoRecordingConfiguration\">supportedVideoRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedAudioRecordingConfiguration\">supportedAudioRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#selectedCameraRecordingConfiguration\">selectedCameraRecordingConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#recordingAudioActive\">recordingAudioActive</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CameraRecordingManagement,\n            name: \"MY_CameraRecordingManagement\",\n            displayName: \"MY_CameraRecordingManagement\",\n            active: \"1\",\n            supportedCameraRecordingConfiguration: \"0\",\n            supportedVideoRecordingConfiguration: \"0\",\n            supportedAudioRecordingConfiguration: \"0\",\n            selectedCameraRecordingConfiguration: \"0\",\n            recordingAudioActive: < UINT8 >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CameraRecordingManagement -->\n      <div id=\"CloudRelay\" class=\"section\">\n         <a name=\"CloudRelay\"></a>\n         <header><h1>CloudRelay</h1></header>\n         <p>UUID:0000005A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#relayControlPoint\">relayControlPoint</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#relayState\">relayState</a></UL></TD><TD> 1 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#relayEnabled\">relayEnabled</a></UL></TD><TD> false </TD><TD> FALSE </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: CloudRelay,\n            name: \"MY_CloudRelay\",\n            displayName: \"MY_CloudRelay\",\n            relayControlPoint: \"0\",\n            relayState: \"1\",\n            relayEnabled: \"false\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- CloudRelay -->\n      <div id=\"DataStreamTransportManagement\" class=\"section\">\n         <a name=\"DataStreamTransportManagement\"></a>\n         <header><h1>DataStreamTransportManagement</h1></header>\n         <p>UUID:00000129-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#setupDataStreamTransport\">setupDataStreamTransport</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#supportedCharacteristicValueTransitionConfiguration\">supportedCharacteristicValueTransitionConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#version\">version</a></UL></TD><TD> Unknown version </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: DataStreamTransportManagement,\n            name: \"MY_DataStreamTransportManagement\",\n            displayName: \"MY_DataStreamTransportManagement\",\n            setupDataStreamTransport: \"0\",\n            supportedCharacteristicValueTransitionConfiguration: \"0\",\n            version: \"Unknown version\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- DataStreamTransportManagement -->\n      <div id=\"NFCAccess\" class=\"section\">\n         <a name=\"NFCAccess\"></a>\n         <header><h1>NFCAccess</h1></header>\n         <p>UUID:00000266-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#configurationState\">configurationState</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#NFCAccessControlPoint\">NFCAccessControlPoint</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#NFCAccessSupportedConfiguration\">NFCAccessSupportedConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: NFCAccess,\n            name: \"MY_NFCAccess\",\n            displayName: \"MY_NFCAccess\",\n            configurationState: \"0\",\n            NFCAccessControlPoint: \"0\",\n            NFCAccessSupportedConfiguration: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- NFCAccess -->\n      <div id=\"SiriEndpoint\" class=\"section\">\n         <a name=\"SiriEndpoint\"></a>\n         <header><h1>SiriEndpoint</h1></header>\n         <p>UUID:00000253-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#SiriEndpointSessionStatus\">SiriEndpointSessionStatus</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#version\">version</a></UL></TD><TD> Unknown version </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#activeIdentifier\">activeIdentifier</a>\n            <LI><a href=\"#manuallyDisabled\">manuallyDisabled</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: SiriEndpoint,\n            name: \"MY_SiriEndpoint\",\n            displayName: \"MY_SiriEndpoint\",\n            SiriEndpointSessionStatus: \"0\",\n            version: \"Unknown version\",\n            activeIdentifier: < UINT32 >,\n            manuallyDisabled: < BOOLEAN >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- SiriEndpoint -->\n      <div id=\"ThreadTransport\" class=\"section\">\n         <a name=\"ThreadTransport\"></a>\n         <header><h1>ThreadTransport</h1></header>\n         <p>UUID:00000701-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentTransport\">currentTransport</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n            <tr><TD><UL><LI><a href=\"#threadControlPoint\">threadControlPoint</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#threadNodeCapabilities\">threadNodeCapabilities</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#threadStatus\">threadStatus</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#ccaEnergyDetectThreshold\">ccaEnergyDetectThreshold</a>\n            <LI><a href=\"#ccaSignalDetectThreshold\">ccaSignalDetectThreshold</a>\n            <LI><a href=\"#eventRetransmissionMaximum\">eventRetransmissionMaximum</a>\n            <LI><a href=\"#eventTransmissionCounters\">eventTransmissionCounters</a>\n            <LI><a href=\"#macRetransmissionMaximum\">macRetransmissionMaximum</a>\n            <LI><a href=\"#macTransmissionCounters\">macTransmissionCounters</a>\n            <LI><a href=\"#receiverSensitivity\">receiverSensitivity</a>\n            <LI><a href=\"#receivedSignalStrengthIndication\">receivedSignalStrengthIndication</a>\n            <LI><a href=\"#signalToNoiseRatio\">signalToNoiseRatio</a>\n            <LI><a href=\"#threadOpenThreadVersion\">threadOpenThreadVersion</a>\n            <LI><a href=\"#transmitPower\">transmitPower</a>\n            <LI><a href=\"#MaximumTransmitPower\">MaximumTransmitPower</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: ThreadTransport,\n            name: \"MY_ThreadTransport\",\n            displayName: \"MY_ThreadTransport\",\n            currentTransport: \"0\",\n            threadControlPoint: \"0\",\n            threadNodeCapabilities: \"0\",\n            threadStatus: \"0\",\n            ccaEnergyDetectThreshold: < INT >,\n            ccaSignalDetectThreshold: < INT >,\n            eventRetransmissionMaximum: < UINT8 >,\n            eventTransmissionCounters: < UINT32 >,\n            macRetransmissionMaximum: < UINT8 >,\n            macTransmissionCounters: < DATA >,\n            receiverSensitivity: < INT >,\n            receivedSignalStrengthIndication: < INT >,\n            signalToNoiseRatio: < INT >,\n            threadOpenThreadVersion: \"< STRING> \",\n            transmitPower: < INT >,\n            MaximumTransmitPower: < INT >,\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- ThreadTransport -->\n      <div id=\"AccessCode\" class=\"section\">\n         <a name=\"AccessCode\"></a>\n         <header><h1>AccessCode</h1></header>\n         <p>UUID:00000260-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#accessCodeControlPoint\">accessCodeControlPoint</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#accessCodeSupportedConfiguration\">accessCodeSupportedConfiguration</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#configurationState\">configurationState</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: AccessCode,\n            name: \"MY_AccessCode\",\n            displayName: \"MY_AccessCode\",\n            accessCodeControlPoint: \"0\",\n            accessCodeSupportedConfiguration: \"0\",\n            configurationState: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- AccessCode -->\n      <div id=\"FirmwareUpdate\" class=\"section\">\n         <a name=\"FirmwareUpdate\"></a>\n         <header><h1>FirmwareUpdate</h1></header>\n         <p>UUID:00000236-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#firmwareUpdateReadiness\">firmwareUpdateReadiness</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#firmwareUpdateStatus\">firmwareUpdateStatus</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#StagedFirmwareVersion\">StagedFirmwareVersion</a>\n            <LI><a href=\"#supportedFirmwareUpdateConfiguration\">supportedFirmwareUpdateConfiguration</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: FirmwareUpdate,\n            name: \"MY_FirmwareUpdate\",\n            displayName: \"MY_FirmwareUpdate\",\n            firmwareUpdateReadiness: \"0\",\n            firmwareUpdateStatus: \"0\",\n            StagedFirmwareVersion: \"< STRING> \",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- FirmwareUpdate -->\n      <div id=\"TapManagement\" class=\"section\">\n         <a name=\"TapManagement\"></a>\n         <header><h1>TapManagement</h1></header>\n         <p>UUID:0000022E-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#active\">active</a></UL></TD><TD> 1 </TD><TD> ACTIVE </TD>\n            <tr><TD><UL><LI><a href=\"#cryptoHash\">cryptoHash</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#tapType\">tapType</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n            <tr><TD><UL><LI><a href=\"#token\">token</a></UL></TD><TD>  </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: TapManagement,\n            name: \"MY_TapManagement\",\n            displayName: \"MY_TapManagement\",\n            active: \"1\",\n            cryptoHash: \"0\",\n            tapType: \"0\",\n            token: \"\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- TapManagement -->\n      <div id=\"WiFiTransport\" class=\"section\">\n         <a name=\"WiFiTransport\"></a>\n         <header><h1>WiFiTransport</h1></header>\n         <p>UUID:0000022A-0000-1000-8000-0026BB765291</p>\n         <H3>Required Characteristics</H3>\n         <table>\n            <TD> </TD><TD> Default Value </TD><TD> Constant </TD>\n            <tr><TD><UL><LI><a href=\"#currentTransport\">currentTransport</a></UL></TD><TD> 0 </TD><TD> FALSE </TD>\n            <tr><TD><UL><LI><a href=\"#wifiCapabilities\">wifiCapabilities</a></UL></TD><TD> 0 </TD><TD> n/a </TD>\n         </Table>\n         <H3>Optional Characteristics</H3>\n         <UL>\n            <LI><a href=\"#wifiConfigurationControl\">wifiConfigurationControl</a>\n         </UL>\n         <H3>Example config.json entry</H3>\n         <pre>\n         {\n            type: WiFiTransport,\n            name: \"MY_WiFiTransport\",\n            displayName: \"MY_WiFiTransport\",\n            currentTransport: \"0\",\n            wifiCapabilities: \"0\",\n            <a href=\"#state_cmd\">state_cmd</a>: < \"STRING\" >,\n            <a href=\"#polling\">polling</a>: < POLLING>\n\n         }\n         </pre>\n         See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\n      </DIV>   <!-- WiFiTransport -->\n      <div id=\"accessControlLevel\" class=\"section\" >\n         <a name=\"accessControlLevel\"></a>\n         <header><h1>accessControlLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> accessControlLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E5-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint16</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- accessControlLevel -->\n      <div id=\"accessoryFlags\" class=\"section\" >\n         <a name=\"accessoryFlags\"></a>\n         <header><h1>accessoryFlags</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> accessoryFlags</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000A6-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- accessoryFlags -->\n      <div id=\"accessoryIdentifier\" class=\"section\" >\n         <a name=\"accessoryIdentifier\"></a>\n         <header><h1>accessoryIdentifier</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> accessoryIdentifier</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000057-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- accessoryIdentifier -->\n      <div id=\"active\" class=\"section\" >\n         <a name=\"active\"></a>\n         <header><h1>active</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> active</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B0-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"INACTIVE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ACTIVE\" </TD></tr>\n         </table>\n      </DIV>   <!-- active -->\n      <div id=\"activeIdentifier\" class=\"section\" >\n         <a name=\"activeIdentifier\"></a>\n         <header><h1>activeIdentifier</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> activeIdentifier</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E7-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- activeIdentifier -->\n      <div id=\"activityInterval\" class=\"section\" >\n         <a name=\"activityInterval\"></a>\n         <header><h1>activityInterval</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> activityInterval</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000023B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- activityInterval -->\n      <div id=\"administratorOnlyAccess\" class=\"section\" >\n         <a name=\"administratorOnlyAccess\"></a>\n         <header><h1>administratorOnlyAccess</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> administratorOnlyAccess</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000001-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- administratorOnlyAccess -->\n      <div id=\"airParticulateDensity\" class=\"section\" >\n         <a name=\"airParticulateDensity\"></a>\n         <header><h1>airParticulateDensity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> airParticulateDensity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000064-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- airParticulateDensity -->\n      <div id=\"airParticulateSize\" class=\"section\" >\n         <a name=\"airParticulateSize\"></a>\n         <header><h1>airParticulateSize</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> airParticulateSize</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000065-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"_2_5_M\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"_10_M\" </TD></tr>\n         </table>\n      </DIV>   <!-- airParticulateSize -->\n      <div id=\"airQuality\" class=\"section\" >\n         <a name=\"airQuality\"></a>\n         <header><h1>airQuality</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> airQuality</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000095-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  5</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"UNKNOWN\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"EXCELLENT\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"GOOD\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"FAIR\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"INFERIOR\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"POOR\" </TD></tr>\n         </table>\n      </DIV>   <!-- airQuality -->\n      <div id=\"appMatchingIdentifier\" class=\"section\" >\n         <a name=\"appMatchingIdentifier\"></a>\n         <header><h1>appMatchingIdentifier</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> appMatchingIdentifier</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000A4-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- appMatchingIdentifier -->\n      <div id=\"audioFeedback\" class=\"section\" >\n         <a name=\"audioFeedback\"></a>\n         <header><h1>audioFeedback</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> audioFeedback</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000005-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- audioFeedback -->\n      <div id=\"batteryLevel\" class=\"section\" >\n         <a name=\"batteryLevel\"></a>\n         <header><h1>batteryLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> batteryLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000068-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- batteryLevel -->\n      <div id=\"brightness\" class=\"section\" >\n         <a name=\"brightness\"></a>\n         <header><h1>brightness</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> brightness</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000008-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- brightness -->\n      <div id=\"buttonEvent\" class=\"section\" >\n         <a name=\"buttonEvent\"></a>\n         <header><h1>buttonEvent</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> buttonEvent</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000126-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- buttonEvent -->\n      <div id=\"ccaEnergyDetectThreshold\" class=\"section\" >\n         <a name=\"ccaEnergyDetectThreshold\"></a>\n         <header><h1>ccaEnergyDetectThreshold</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> ccaEnergyDetectThreshold</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000246-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- ccaEnergyDetectThreshold -->\n      <div id=\"ccaSignalDetectThreshold\" class=\"section\" >\n         <a name=\"ccaSignalDetectThreshold\"></a>\n         <header><h1>ccaSignalDetectThreshold</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> ccaSignalDetectThreshold</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000245-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- ccaSignalDetectThreshold -->\n      <div id=\"cameraOperatingModeIndicator\" class=\"section\" >\n         <a name=\"cameraOperatingModeIndicator\"></a>\n         <header><h1>cameraOperatingModeIndicator</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> cameraOperatingModeIndicator</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000021D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DISABLE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ENABLE\" </TD></tr>\n         </table>\n      </DIV>   <!-- cameraOperatingModeIndicator -->\n      <div id=\"carbonDioxideDetected\" class=\"section\" >\n         <a name=\"carbonDioxideDetected\"></a>\n         <header><h1>carbonDioxideDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> carbonDioxideDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000092-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"CO2_LEVELS_NORMAL\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CO2_LEVELS_ABNORMAL\" </TD></tr>\n         </table>\n      </DIV>   <!-- carbonDioxideDetected -->\n      <div id=\"carbonDioxideLevel\" class=\"section\" >\n         <a name=\"carbonDioxideLevel\"></a>\n         <header><h1>carbonDioxideLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> carbonDioxideLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000093-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- carbonDioxideLevel -->\n      <div id=\"carbonDioxidePeakLevel\" class=\"section\" >\n         <a name=\"carbonDioxidePeakLevel\"></a>\n         <header><h1>carbonDioxidePeakLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> carbonDioxidePeakLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000094-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- carbonDioxidePeakLevel -->\n      <div id=\"carbonMonoxideDetected\" class=\"section\" >\n         <a name=\"carbonMonoxideDetected\"></a>\n         <header><h1>carbonMonoxideDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> carbonMonoxideDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000069-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"CO_LEVELS_NORMAL\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CO_LEVELS_ABNORMAL\" </TD></tr>\n         </table>\n      </DIV>   <!-- carbonMonoxideDetected -->\n      <div id=\"carbonMonoxideLevel\" class=\"section\" >\n         <a name=\"carbonMonoxideLevel\"></a>\n         <header><h1>carbonMonoxideLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> carbonMonoxideLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000090-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- carbonMonoxideLevel -->\n      <div id=\"carbonMonoxidePeakLevel\" class=\"section\" >\n         <a name=\"carbonMonoxidePeakLevel\"></a>\n         <header><h1>carbonMonoxidePeakLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> carbonMonoxidePeakLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000091-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- carbonMonoxidePeakLevel -->\n      <div id=\"characteristicValueTransitionControl\" class=\"section\" >\n         <a name=\"characteristicValueTransitionControl\"></a>\n         <header><h1>characteristicValueTransitionControl</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> characteristicValueTransitionControl</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000143-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- characteristicValueTransitionControl -->\n      <div id=\"chargingState\" class=\"section\" >\n         <a name=\"chargingState\"></a>\n         <header><h1>chargingState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> chargingState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000008F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NOT_CHARGING\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CHARGING\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"NOT_CHARGEABLE\" </TD></tr>\n         </table>\n      </DIV>   <!-- chargingState -->\n      <div id=\"closedCaptions\" class=\"section\" >\n         <a name=\"closedCaptions\"></a>\n         <header><h1>closedCaptions</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> closedCaptions</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000DD-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DISABLED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ENABLED\" </TD></tr>\n         </table>\n      </DIV>   <!-- closedCaptions -->\n      <div id=\"colorTemperature\" class=\"section\" >\n         <a name=\"colorTemperature\"></a>\n         <header><h1>colorTemperature</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> colorTemperature</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000CE-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  140</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  500</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- colorTemperature -->\n      <div id=\"configuredName\" class=\"section\" >\n         <a name=\"configuredName\"></a>\n         <header><h1>configuredName</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> configuredName</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E3-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- configuredName -->\n      <div id=\"contactSensorState\" class=\"section\" >\n         <a name=\"contactSensorState\"></a>\n         <header><h1>contactSensorState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> contactSensorState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000006A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"CONTACT_DETECTED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CONTACT_NOT_DETECTED\" </TD></tr>\n         </table>\n      </DIV>   <!-- contactSensorState -->\n      <div id=\"coolingThresholdTemperature\" class=\"section\" >\n         <a name=\"coolingThresholdTemperature\"></a>\n         <header><h1>coolingThresholdTemperature</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> coolingThresholdTemperature</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000000D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  celsius</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  10</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  35</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  0.1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- coolingThresholdTemperature -->\n      <div id=\"currentAirPurifierState\" class=\"section\" >\n         <a name=\"currentAirPurifierState\"></a>\n         <header><h1>currentAirPurifierState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentAirPurifierState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000A9-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"INACTIVE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"IDLE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"PURIFYING_AIR\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentAirPurifierState -->\n      <div id=\"currentAmbientLightLevel\" class=\"section\" >\n         <a name=\"currentAmbientLightLevel\"></a>\n         <header><h1>currentAmbientLightLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentAmbientLightLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000006B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  lux</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  0.0001</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100000</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentAmbientLightLevel -->\n      <div id=\"currentDoorState\" class=\"section\" >\n         <a name=\"currentDoorState\"></a>\n         <header><h1>currentDoorState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentDoorState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000000E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  4</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OPEN\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CLOSED\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"OPENING\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"CLOSING\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"STOPPED\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentDoorState -->\n      <div id=\"currentFanState\" class=\"section\" >\n         <a name=\"currentFanState\"></a>\n         <header><h1>currentFanState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentFanState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000AF-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"INACTIVE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"IDLE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"BLOWING_AIR\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentFanState -->\n      <div id=\"currentHeaterCoolerState\" class=\"section\" >\n         <a name=\"currentHeaterCoolerState\"></a>\n         <header><h1>currentHeaterCoolerState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentHeaterCoolerState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B1-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"INACTIVE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"IDLE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"HEATING\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"COOLING\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentHeaterCoolerState -->\n      <div id=\"currentHeatingCoolingState\" class=\"section\" >\n         <a name=\"currentHeatingCoolingState\"></a>\n         <header><h1>currentHeatingCoolingState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentHeatingCoolingState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000000F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OFF\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HEAT\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"COOL\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"AUTO\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentHeatingCoolingState -->\n      <div id=\"currentHorizontalTiltAngle\" class=\"section\" >\n         <a name=\"currentHorizontalTiltAngle\"></a>\n         <header><h1>currentHorizontalTiltAngle</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentHorizontalTiltAngle</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000006C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -90</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  90</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentHorizontalTiltAngle -->\n      <div id=\"currentHumidifierDehumidifierState\" class=\"section\" >\n         <a name=\"currentHumidifierDehumidifierState\"></a>\n         <header><h1>currentHumidifierDehumidifierState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentHumidifierDehumidifierState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B3-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"INACTIVE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"IDLE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"HUMIDIFYING\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"DEHUMIDIFYING\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentHumidifierDehumidifierState -->\n      <div id=\"currentMediaState\" class=\"section\" >\n         <a name=\"currentMediaState\"></a>\n         <header><h1>currentMediaState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentMediaState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E0-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  5</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"PLAY\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"PAUSE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"STOP\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"LOADING\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"INTERRUPTED\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentMediaState -->\n      <div id=\"currentPosition\" class=\"section\" >\n         <a name=\"currentPosition\"></a>\n         <header><h1>currentPosition</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentPosition</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000006D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentPosition -->\n      <div id=\"currentRelativeHumidity\" class=\"section\" >\n         <a name=\"currentRelativeHumidity\"></a>\n         <header><h1>currentRelativeHumidity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentRelativeHumidity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000010-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentRelativeHumidity -->\n      <div id=\"currentSlatState\" class=\"section\" >\n         <a name=\"currentSlatState\"></a>\n         <header><h1>currentSlatState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentSlatState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000AA-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FIXED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"JAMMED\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"SWINGING\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentSlatState -->\n      <div id=\"currentTemperature\" class=\"section\" >\n         <a name=\"currentTemperature\"></a>\n         <header><h1>currentTemperature</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentTemperature</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000011-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  celsius</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -270</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  0.1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentTemperature -->\n      <div id=\"currentTiltAngle\" class=\"section\" >\n         <a name=\"currentTiltAngle\"></a>\n         <header><h1>currentTiltAngle</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentTiltAngle</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C1-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -90</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  90</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentTiltAngle -->\n      <div id=\"currentTransport\" class=\"section\" >\n         <a name=\"currentTransport\"></a>\n         <header><h1>currentTransport</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentTransport</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000022B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentTransport -->\n      <div id=\"currentVerticalTiltAngle\" class=\"section\" >\n         <a name=\"currentVerticalTiltAngle\"></a>\n         <header><h1>currentVerticalTiltAngle</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentVerticalTiltAngle</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000006E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -90</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  90</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- currentVerticalTiltAngle -->\n      <div id=\"currentVisibilityState\" class=\"section\" >\n         <a name=\"currentVisibilityState\"></a>\n         <header><h1>currentVisibilityState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> currentVisibilityState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000135-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SHOWN\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HIDDEN\" </TD></tr>\n         </table>\n      </DIV>   <!-- currentVisibilityState -->\n      <div id=\"dataStreamHAPTransport\" class=\"section\" >\n         <a name=\"dataStreamHAPTransport\"></a>\n         <header><h1>dataStreamHAPTransport</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> dataStreamHAPTransport</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000138-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- dataStreamHAPTransport -->\n      <div id=\"dataStreamHAPTransportInterrupt\" class=\"section\" >\n         <a name=\"dataStreamHAPTransportInterrupt\"></a>\n         <header><h1>dataStreamHAPTransportInterrupt</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> dataStreamHAPTransportInterrupt</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000139-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- dataStreamHAPTransportInterrupt -->\n      <div id=\"diagonalFieldOfView\" class=\"section\" >\n         <a name=\"diagonalFieldOfView\"></a>\n         <header><h1>diagonalFieldOfView</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> diagonalFieldOfView</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000224-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  360</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- diagonalFieldOfView -->\n      <div id=\"digitalZoom\" class=\"section\" >\n         <a name=\"digitalZoom\"></a>\n         <header><h1>digitalZoom</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> digitalZoom</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000011D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  0.1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- digitalZoom -->\n      <div id=\"displayOrder\" class=\"section\" >\n         <a name=\"displayOrder\"></a>\n         <header><h1>displayOrder</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> displayOrder</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000136-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- displayOrder -->\n      <div id=\"eventRetransmissionMaximum\" class=\"section\" >\n         <a name=\"eventRetransmissionMaximum\"></a>\n         <header><h1>eventRetransmissionMaximum</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> eventRetransmissionMaximum</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000023D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- eventRetransmissionMaximum -->\n      <div id=\"eventSnapshotsActive\" class=\"section\" >\n         <a name=\"eventSnapshotsActive\"></a>\n         <header><h1>eventSnapshotsActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> eventSnapshotsActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000223-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DISABLE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ENABLE\" </TD></tr>\n         </table>\n      </DIV>   <!-- eventSnapshotsActive -->\n      <div id=\"eventTransmissionCounters\" class=\"section\" >\n         <a name=\"eventTransmissionCounters\"></a>\n         <header><h1>eventTransmissionCounters</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> eventTransmissionCounters</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000023E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- eventTransmissionCounters -->\n      <div id=\"filterChangeIndication\" class=\"section\" >\n         <a name=\"filterChangeIndication\"></a>\n         <header><h1>filterChangeIndication</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> filterChangeIndication</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000AC-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FILTER_OK\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CHANGE_FILTER\" </TD></tr>\n         </table>\n      </DIV>   <!-- filterChangeIndication -->\n      <div id=\"filterLifeLevel\" class=\"section\" >\n         <a name=\"filterLifeLevel\"></a>\n         <header><h1>filterLifeLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> filterLifeLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000AB-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- filterLifeLevel -->\n      <div id=\"firmwareRevision\" class=\"section\" >\n         <a name=\"firmwareRevision\"></a>\n         <header><h1>firmwareRevision</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> firmwareRevision</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000052-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- firmwareRevision -->\n      <div id=\"hardwareRevision\" class=\"section\" >\n         <a name=\"hardwareRevision\"></a>\n         <header><h1>hardwareRevision</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> hardwareRevision</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000053-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- hardwareRevision -->\n      <div id=\"heartBeat\" class=\"section\" >\n         <a name=\"heartBeat\"></a>\n         <header><h1>heartBeat</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> heartBeat</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000024A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- heartBeat -->\n      <div id=\"heatingThresholdTemperature\" class=\"section\" >\n         <a name=\"heatingThresholdTemperature\"></a>\n         <header><h1>heatingThresholdTemperature</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> heatingThresholdTemperature</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000012-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  celsius</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  25</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  0.1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- heatingThresholdTemperature -->\n      <div id=\"holdPosition\" class=\"section\" >\n         <a name=\"holdPosition\"></a>\n         <header><h1>holdPosition</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> holdPosition</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000006F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- holdPosition -->\n      <div id=\"homeKitCameraActive\" class=\"section\" >\n         <a name=\"homeKitCameraActive\"></a>\n         <header><h1>homeKitCameraActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> homeKitCameraActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000021B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OFF\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ON\" </TD></tr>\n         </table>\n      </DIV>   <!-- homeKitCameraActive -->\n      <div id=\"hue\" class=\"section\" >\n         <a name=\"hue\"></a>\n         <header><h1>hue</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> hue</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000013-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  360</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- hue -->\n      <div id=\"identifier\" class=\"section\" >\n         <a name=\"identifier\"></a>\n         <header><h1>identifier</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> identifier</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E6-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- identifier -->\n      <div id=\"identify\" class=\"section\" >\n         <a name=\"identify\"></a>\n         <header><h1>identify</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> identify</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000014-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- identify -->\n      <div id=\"imageMirroring\" class=\"section\" >\n         <a name=\"imageMirroring\"></a>\n         <header><h1>imageMirroring</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> imageMirroring</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000011F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- imageMirroring -->\n      <div id=\"imageRotation\" class=\"section\" >\n         <a name=\"imageRotation\"></a>\n         <header><h1>imageRotation</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> imageRotation</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000011E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  360</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- imageRotation -->\n      <div id=\"inUse\" class=\"section\" >\n         <a name=\"inUse\"></a>\n         <header><h1>inUse</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> inUse</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000D2-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NOT_IN_USE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"IN_USE\" </TD></tr>\n         </table>\n      </DIV>   <!-- inUse -->\n      <div id=\"inputDeviceType\" class=\"section\" >\n         <a name=\"inputDeviceType\"></a>\n         <header><h1>inputDeviceType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> inputDeviceType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000DC-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  6</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OTHER\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TV\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"RECORDING\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"TUNER\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"PLAYBACK\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"AUDIO_SYSTEM\" </TD></tr>\n            <tr><TD> undefined </TD><TD> \"UNKNOWN_6\" </TD></tr>\n         </table>\n      </DIV>   <!-- inputDeviceType -->\n      <div id=\"inputSourceType\" class=\"section\" >\n         <a name=\"inputSourceType\"></a>\n         <header><h1>inputSourceType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> inputSourceType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000DB-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  10</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OTHER\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HOME_SCREEN\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"TUNER\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"HDMI\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"COMPOSITE_VIDEO\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"S_VIDEO\" </TD></tr>\n            <tr><TD> 6 </TD><TD> \"COMPONENT_VIDEO\" </TD></tr>\n            <tr><TD> 7 </TD><TD> \"DVI\" </TD></tr>\n            <tr><TD> 8 </TD><TD> \"AIRPLAY\" </TD></tr>\n            <tr><TD> 9 </TD><TD> \"USB\" </TD></tr>\n            <tr><TD> 10 </TD><TD> \"APPLICATION\" </TD></tr>\n         </table>\n      </DIV>   <!-- inputSourceType -->\n      <div id=\"isConfigured\" class=\"section\" >\n         <a name=\"isConfigured\"></a>\n         <header><h1>isConfigured</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> isConfigured</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000D6-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NOT_CONFIGURED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CONFIGURED\" </TD></tr>\n         </table>\n      </DIV>   <!-- isConfigured -->\n      <div id=\"leakDetected\" class=\"section\" >\n         <a name=\"leakDetected\"></a>\n         <header><h1>leakDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> leakDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000070-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"LEAK_NOT_DETECTED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"LEAK_DETECTED\" </TD></tr>\n         </table>\n      </DIV>   <!-- leakDetected -->\n      <div id=\"listPairings\" class=\"section\" >\n         <a name=\"listPairings\"></a>\n         <header><h1>listPairings</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> listPairings</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000050-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- listPairings -->\n      <div id=\"lockControlPoint\" class=\"section\" >\n         <a name=\"lockControlPoint\"></a>\n         <header><h1>lockControlPoint</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> lockControlPoint</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000019-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- lockControlPoint -->\n      <div id=\"lockCurrentState\" class=\"section\" >\n         <a name=\"lockCurrentState\"></a>\n         <header><h1>lockCurrentState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> lockCurrentState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000001D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"UNSECURED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"SECURED\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"JAMMED\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"UNKNOWN\" </TD></tr>\n         </table>\n      </DIV>   <!-- lockCurrentState -->\n      <div id=\"lockLastKnownAction\" class=\"section\" >\n         <a name=\"lockLastKnownAction\"></a>\n         <header><h1>lockLastKnownAction</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> lockLastKnownAction</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000001C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  10</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SECURED_PHYSICALLY_INTERIOR\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"UNSECURED_PHYSICALLY_INTERIOR\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"SECURED_PHYSICALLY_EXTERIOR\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"UNSECURED_PHYSICALLY_EXTERIOR\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"SECURED_BY_KEYPAD\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"UNSECURED_BY_KEYPAD\" </TD></tr>\n            <tr><TD> 6 </TD><TD> \"SECURED_REMOTELY\" </TD></tr>\n            <tr><TD> 7 </TD><TD> \"UNSECURED_REMOTELY\" </TD></tr>\n            <tr><TD> 8 </TD><TD> \"SECURED_BY_AUTO_SECURE_TIMEOUT\" </TD></tr>\n            <tr><TD> 9 </TD><TD> \"SECURED_PHYSICALLY\" </TD></tr>\n            <tr><TD> 10 </TD><TD> \"UNSECURED_PHYSICALLY\" </TD></tr>\n         </table>\n      </DIV>   <!-- lockLastKnownAction -->\n      <div id=\"lockManagementAutoSecurityTimeout\" class=\"section\" >\n         <a name=\"lockManagementAutoSecurityTimeout\"></a>\n         <header><h1>lockManagementAutoSecurityTimeout</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> lockManagementAutoSecurityTimeout</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000001A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Unit: </TD><TD>  seconds</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- lockManagementAutoSecurityTimeout -->\n      <div id=\"lockPhysicalControls\" class=\"section\" >\n         <a name=\"lockPhysicalControls\"></a>\n         <header><h1>lockPhysicalControls</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> lockPhysicalControls</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000A7-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"CONTROL_LOCK_DISABLED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CONTROL_LOCK_ENABLED\" </TD></tr>\n         </table>\n      </DIV>   <!-- lockPhysicalControls -->\n      <div id=\"lockTargetState\" class=\"section\" >\n         <a name=\"lockTargetState\"></a>\n         <header><h1>lockTargetState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> lockTargetState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000001E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"UNSECURED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"SECURED\" </TD></tr>\n         </table>\n      </DIV>   <!-- lockTargetState -->\n      <div id=\"logs\" class=\"section\" >\n         <a name=\"logs\"></a>\n         <header><h1>logs</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> logs</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000001F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- logs -->\n      <div id=\"macRetransmissionMaximum\" class=\"section\" >\n         <a name=\"macRetransmissionMaximum\"></a>\n         <header><h1>macRetransmissionMaximum</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> macRetransmissionMaximum</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000247-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- macRetransmissionMaximum -->\n      <div id=\"macTransmissionCounters\" class=\"section\" >\n         <a name=\"macTransmissionCounters\"></a>\n         <header><h1>macTransmissionCounters</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> macTransmissionCounters</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000248-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> data</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- macTransmissionCounters -->\n      <div id=\"managedNetworkEnable\" class=\"section\" >\n         <a name=\"managedNetworkEnable\"></a>\n         <header><h1>managedNetworkEnable</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> managedNetworkEnable</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000215-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DISABLED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ENABLED\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"UNKNOWN\" </TD></tr>\n         </table>\n      </DIV>   <!-- managedNetworkEnable -->\n      <div id=\"manuallyDisabled\" class=\"section\" >\n         <a name=\"manuallyDisabled\"></a>\n         <header><h1>manuallyDisabled</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> manuallyDisabled</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000227-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"ENABLED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"DISABLED\" </TD></tr>\n         </table>\n      </DIV>   <!-- manuallyDisabled -->\n      <div id=\"manufacturer\" class=\"section\" >\n         <a name=\"manufacturer\"></a>\n         <header><h1>manufacturer</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> manufacturer</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000020-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- manufacturer -->\n      <div id=\"model\" class=\"section\" >\n         <a name=\"model\"></a>\n         <header><h1>model</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> model</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000021-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- model -->\n      <div id=\"motionDetected\" class=\"section\" >\n         <a name=\"motionDetected\"></a>\n         <header><h1>motionDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> motionDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000022-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- motionDetected -->\n      <div id=\"mute\" class=\"section\" >\n         <a name=\"mute\"></a>\n         <header><h1>mute</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> mute</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000011A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- mute -->\n      <div id=\"name\" class=\"section\" >\n         <a name=\"name\"></a>\n         <header><h1>name</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> name</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000023-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- name -->\n      <div id=\"networkAccessViolationControl\" class=\"section\" >\n         <a name=\"networkAccessViolationControl\"></a>\n         <header><h1>networkAccessViolationControl</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> networkAccessViolationControl</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000021F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- networkAccessViolationControl -->\n      <div id=\"networkClientProfileControl\" class=\"section\" >\n         <a name=\"networkClientProfileControl\"></a>\n         <header><h1>networkClientProfileControl</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> networkClientProfileControl</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000020C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- networkClientProfileControl -->\n      <div id=\"networkClientStatusControl\" class=\"section\" >\n         <a name=\"networkClientStatusControl\"></a>\n         <header><h1>networkClientStatusControl</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> networkClientStatusControl</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000020D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- networkClientStatusControl -->\n      <div id=\"nightVision\" class=\"section\" >\n         <a name=\"nightVision\"></a>\n         <header><h1>nightVision</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> nightVision</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000011B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- nightVision -->\n      <div id=\"nitrogenDioxideDensity\" class=\"section\" >\n         <a name=\"nitrogenDioxideDensity\"></a>\n         <header><h1>nitrogenDioxideDensity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> nitrogenDioxideDensity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C4-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- nitrogenDioxideDensity -->\n      <div id=\"obstructionDetected\" class=\"section\" >\n         <a name=\"obstructionDetected\"></a>\n         <header><h1>obstructionDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> obstructionDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000024-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- obstructionDetected -->\n      <div id=\"occupancyDetected\" class=\"section\" >\n         <a name=\"occupancyDetected\"></a>\n         <header><h1>occupancyDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> occupancyDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000071-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OCCUPANCY_NOT_DETECTED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"OCCUPANCY_DETECTED\" </TD></tr>\n         </table>\n      </DIV>   <!-- occupancyDetected -->\n      <div id=\"on\" class=\"section\" >\n         <a name=\"on\"></a>\n         <header><h1>on</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> on</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000025-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- on -->\n      <div id=\"operatingStateResponse\" class=\"section\" >\n         <a name=\"operatingStateResponse\"></a>\n         <header><h1>operatingStateResponse</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> operatingStateResponse</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000232-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- operatingStateResponse -->\n      <div id=\"opticalZoom\" class=\"section\" >\n         <a name=\"opticalZoom\"></a>\n         <header><h1>opticalZoom</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> opticalZoom</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000011C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  0.1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- opticalZoom -->\n      <div id=\"outletInUse\" class=\"section\" >\n         <a name=\"outletInUse\"></a>\n         <header><h1>outletInUse</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> outletInUse</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000026-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- outletInUse -->\n      <div id=\"ozoneDensity\" class=\"section\" >\n         <a name=\"ozoneDensity\"></a>\n         <header><h1>ozoneDensity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> ozoneDensity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C3-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- ozoneDensity -->\n      <div id=\"pm10Density\" class=\"section\" >\n         <a name=\"pm10Density\"></a>\n         <header><h1>pm10Density</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pm10Density</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C7-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- pm10Density -->\n      <div id=\"pm2_5Density\" class=\"section\" >\n         <a name=\"pm2_5Density\"></a>\n         <header><h1>pm2_5Density</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pm2_5Density</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C6-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- pm2_5Density -->\n      <div id=\"pairSetup\" class=\"section\" >\n         <a name=\"pairSetup\"></a>\n         <header><h1>pairSetup</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pairSetup</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000004C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- pairSetup -->\n      <div id=\"pairVerify\" class=\"section\" >\n         <a name=\"pairVerify\"></a>\n         <header><h1>pairVerify</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pairVerify</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000004E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- pairVerify -->\n      <div id=\"pairingFeatures\" class=\"section\" >\n         <a name=\"pairingFeatures\"></a>\n         <header><h1>pairingFeatures</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pairingFeatures</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000004F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- pairingFeatures -->\n      <div id=\"pairingPairings\" class=\"section\" >\n         <a name=\"pairingPairings\"></a>\n         <header><h1>pairingPairings</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pairingPairings</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000050-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- pairingPairings -->\n      <div id=\"passwordSetting\" class=\"section\" >\n         <a name=\"passwordSetting\"></a>\n         <header><h1>passwordSetting</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> passwordSetting</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E4-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- passwordSetting -->\n      <div id=\"periodicSnapshotsActive\" class=\"section\" >\n         <a name=\"periodicSnapshotsActive\"></a>\n         <header><h1>periodicSnapshotsActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> periodicSnapshotsActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000225-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DISABLE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ENABLE\" </TD></tr>\n         </table>\n      </DIV>   <!-- periodicSnapshotsActive -->\n      <div id=\"pictureMode\" class=\"section\" >\n         <a name=\"pictureMode\"></a>\n         <header><h1>pictureMode</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> pictureMode</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E2-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  13</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OTHER\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"STANDARD\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"CALIBRATED\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"CALIBRATED_DARK\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"VIVID\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"GAME\" </TD></tr>\n            <tr><TD> 6 </TD><TD> \"COMPUTER\" </TD></tr>\n            <tr><TD> 7 </TD><TD> \"CUSTOM\" </TD></tr>\n            <tr><TD> 8 </TD><TD> \"UNKNOWN8\" </TD></tr>\n            <tr><TD> 9 </TD><TD> \"UNKNOWN9\" </TD></tr>\n            <tr><TD> 10 </TD><TD> \"UNKNOWN10\" </TD></tr>\n            <tr><TD> 11 </TD><TD> \"UNKNOWN11\" </TD></tr>\n            <tr><TD> 12 </TD><TD> \"UNKNOWN12\" </TD></tr>\n            <tr><TD> 13 </TD><TD> \"UNKNOWN13\" </TD></tr>\n         </table>\n      </DIV>   <!-- pictureMode -->\n      <div id=\"ping\" class=\"section\" >\n         <a name=\"ping\"></a>\n         <header><h1>ping</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> ping</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000023C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> data</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- ping -->\n      <div id=\"positionState\" class=\"section\" >\n         <a name=\"positionState\"></a>\n         <header><h1>positionState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> positionState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000072-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DECREASING\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"INCREASING\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"STOPPED\" </TD></tr>\n         </table>\n      </DIV>   <!-- positionState -->\n      <div id=\"powerModeSelection\" class=\"section\" >\n         <a name=\"powerModeSelection\"></a>\n         <header><h1>powerModeSelection</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> powerModeSelection</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000DF-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SHOW\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HIDE\" </TD></tr>\n         </table>\n      </DIV>   <!-- powerModeSelection -->\n      <div id=\"productData\" class=\"section\" >\n         <a name=\"productData\"></a>\n         <header><h1>productData</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> productData</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000220-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> data</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- productData -->\n      <div id=\"programMode\" class=\"section\" >\n         <a name=\"programMode\"></a>\n         <header><h1>programMode</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> programMode</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000D1-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NO_PROGRAM_SCHEDULED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"PROGRAM_SCHEDULED\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"PROGRAM_SCHEDULED_MANUAL_MODE\" </TD></tr>\n         </table>\n      </DIV>   <!-- programMode -->\n      <div id=\"programmableSwitchEvent\" class=\"section\" >\n         <a name=\"programmableSwitchEvent\"></a>\n         <header><h1>programmableSwitchEvent</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> programmableSwitchEvent</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000073-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SINGLE_PRESS\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"DOUBLE_PRESS\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"LONG_PRESS\" </TD></tr>\n         </table>\n      </DIV>   <!-- programmableSwitchEvent -->\n      <div id=\"programmableSwitchOutputState\" class=\"section\" >\n         <a name=\"programmableSwitchOutputState\"></a>\n         <header><h1>programmableSwitchOutputState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> programmableSwitchOutputState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000074-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- programmableSwitchOutputState -->\n      <div id=\"receivedSignalStrengthIndication\" class=\"section\" >\n         <a name=\"receivedSignalStrengthIndication\"></a>\n         <header><h1>receivedSignalStrengthIndication</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> receivedSignalStrengthIndication</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000023F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- receivedSignalStrengthIndication -->\n      <div id=\"receiverSensitivity\" class=\"section\" >\n         <a name=\"receiverSensitivity\"></a>\n         <header><h1>receiverSensitivity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> receiverSensitivity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000244-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- receiverSensitivity -->\n      <div id=\"recordingAudioActive\" class=\"section\" >\n         <a name=\"recordingAudioActive\"></a>\n         <header><h1>recordingAudioActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> recordingAudioActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000226-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DISABLE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ENABLE\" </TD></tr>\n         </table>\n      </DIV>   <!-- recordingAudioActive -->\n      <div id=\"relativeHumidityDehumidifierThreshold\" class=\"section\" >\n         <a name=\"relativeHumidityDehumidifierThreshold\"></a>\n         <header><h1>relativeHumidityDehumidifierThreshold</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> relativeHumidityDehumidifierThreshold</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C9-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- relativeHumidityDehumidifierThreshold -->\n      <div id=\"relativeHumidityHumidifierThreshold\" class=\"section\" >\n         <a name=\"relativeHumidityHumidifierThreshold\"></a>\n         <header><h1>relativeHumidityHumidifierThreshold</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> relativeHumidityHumidifierThreshold</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000CA-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- relativeHumidityHumidifierThreshold -->\n      <div id=\"relayControlPoint\" class=\"section\" >\n         <a name=\"relayControlPoint\"></a>\n         <header><h1>relayControlPoint</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> relayControlPoint</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000005E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- relayControlPoint -->\n      <div id=\"relayEnabled\" class=\"section\" >\n         <a name=\"relayEnabled\"></a>\n         <header><h1>relayEnabled</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> relayEnabled</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000005B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- relayEnabled -->\n      <div id=\"relayState\" class=\"section\" >\n         <a name=\"relayState\"></a>\n         <header><h1>relayState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> relayState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000005C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  5</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- relayState -->\n      <div id=\"remainingDuration\" class=\"section\" >\n         <a name=\"remainingDuration\"></a>\n         <header><h1>remainingDuration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> remainingDuration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000D4-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3600</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- remainingDuration -->\n      <div id=\"remoteKey\" class=\"section\" >\n         <a name=\"remoteKey\"></a>\n         <header><h1>remoteKey</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> remoteKey</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E1-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  16</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"REWIND\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"FAST_FORWARD\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"NEXT_TRACK\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"PREVIOUS_TRACK\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"ARROW_UP\" </TD></tr>\n            <tr><TD> 5 </TD><TD> \"ARROW_DOWN\" </TD></tr>\n            <tr><TD> 6 </TD><TD> \"ARROW_LEFT\" </TD></tr>\n            <tr><TD> 7 </TD><TD> \"ARROW_RIGHT\" </TD></tr>\n            <tr><TD> 8 </TD><TD> \"SELECT\" </TD></tr>\n            <tr><TD> 9 </TD><TD> \"BACK\" </TD></tr>\n            <tr><TD> 10 </TD><TD> \"EXIT\" </TD></tr>\n            <tr><TD> 11 </TD><TD> \"PLAY_PAUSE\" </TD></tr>\n            <tr><TD> 12 </TD><TD> \"UNKNOWN12\" </TD></tr>\n            <tr><TD> 13 </TD><TD> \"UNKNOWN13\" </TD></tr>\n            <tr><TD> 14 </TD><TD> \"UNKNOWN14\" </TD></tr>\n            <tr><TD> 15 </TD><TD> \"INFORMATION\" </TD></tr>\n            <tr><TD> 16 </TD><TD> \"UNKNOWN16\" </TD></tr>\n         </table>\n      </DIV>   <!-- remoteKey -->\n      <div id=\"resetFilterIndication\" class=\"section\" >\n         <a name=\"resetFilterIndication\"></a>\n         <header><h1>resetFilterIndication</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> resetFilterIndication</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000AD-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- resetFilterIndication -->\n      <div id=\"rotationDirection\" class=\"section\" >\n         <a name=\"rotationDirection\"></a>\n         <header><h1>rotationDirection</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> rotationDirection</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000028-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"CLOCKWISE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"COUNTER_CLOCKWISE\" </TD></tr>\n         </table>\n      </DIV>   <!-- rotationDirection -->\n      <div id=\"rotationSpeed\" class=\"section\" >\n         <a name=\"rotationSpeed\"></a>\n         <header><h1>rotationSpeed</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> rotationSpeed</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000029-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- rotationSpeed -->\n      <div id=\"routerStatus\" class=\"section\" >\n         <a name=\"routerStatus\"></a>\n         <header><h1>routerStatus</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> routerStatus</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000020E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"READY\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"NOT_READY\" </TD></tr>\n         </table>\n      </DIV>   <!-- routerStatus -->\n      <div id=\"saturation\" class=\"section\" >\n         <a name=\"saturation\"></a>\n         <header><h1>saturation</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> saturation</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000002F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- saturation -->\n      <div id=\"securitySystemAlarmType\" class=\"section\" >\n         <a name=\"securitySystemAlarmType\"></a>\n         <header><h1>securitySystemAlarmType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> securitySystemAlarmType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000008E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- securitySystemAlarmType -->\n      <div id=\"securitySystemCurrentState\" class=\"section\" >\n         <a name=\"securitySystemCurrentState\"></a>\n         <header><h1>securitySystemCurrentState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> securitySystemCurrentState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000066-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  4</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"STAY_ARM\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"AWAY_ARM\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"NIGHT_ARM\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"DISARMED\" </TD></tr>\n            <tr><TD> 4 </TD><TD> \"ALARM_TRIGGERED\" </TD></tr>\n         </table>\n      </DIV>   <!-- securitySystemCurrentState -->\n      <div id=\"securitySystemTargetState\" class=\"section\" >\n         <a name=\"securitySystemTargetState\"></a>\n         <header><h1>securitySystemTargetState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> securitySystemTargetState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000067-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"STAY_ARM\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"AWAY_ARM\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"NIGHT_ARM\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"DISARM\" </TD></tr>\n         </table>\n      </DIV>   <!-- securitySystemTargetState -->\n      <div id=\"selectedAudioStreamConfiguration\" class=\"section\" >\n         <a name=\"selectedAudioStreamConfiguration\"></a>\n         <header><h1>selectedAudioStreamConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> selectedAudioStreamConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000128-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- selectedAudioStreamConfiguration -->\n      <div id=\"selectedCameraRecordingConfiguration\" class=\"section\" >\n         <a name=\"selectedCameraRecordingConfiguration\"></a>\n         <header><h1>selectedCameraRecordingConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> selectedCameraRecordingConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000209-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- selectedCameraRecordingConfiguration -->\n      <div id=\"selectedRTPStreamConfiguration\" class=\"section\" >\n         <a name=\"selectedRTPStreamConfiguration\"></a>\n         <header><h1>selectedRTPStreamConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> selectedRTPStreamConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000117-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- selectedRTPStreamConfiguration -->\n      <div id=\"serialNumber\" class=\"section\" >\n         <a name=\"serialNumber\"></a>\n         <header><h1>serialNumber</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> serialNumber</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000030-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- serialNumber -->\n      <div id=\"serviceLabelIndex\" class=\"section\" >\n         <a name=\"serviceLabelIndex\"></a>\n         <header><h1>serviceLabelIndex</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> serviceLabelIndex</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000CB-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  255</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- serviceLabelIndex -->\n      <div id=\"serviceLabelNamespace\" class=\"section\" >\n         <a name=\"serviceLabelNamespace\"></a>\n         <header><h1>serviceLabelNamespace</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> serviceLabelNamespace</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000CD-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"DOTS\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ARABIC_NUMERALS\" </TD></tr>\n         </table>\n      </DIV>   <!-- serviceLabelNamespace -->\n      <div id=\"setDuration\" class=\"section\" >\n         <a name=\"setDuration\"></a>\n         <header><h1>setDuration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> setDuration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000D3-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3600</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- setDuration -->\n      <div id=\"setupDataStreamTransport\" class=\"section\" >\n         <a name=\"setupDataStreamTransport\"></a>\n         <header><h1>setupDataStreamTransport</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> setupDataStreamTransport</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000131-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- setupDataStreamTransport -->\n      <div id=\"setupEndpoints\" class=\"section\" >\n         <a name=\"setupEndpoints\"></a>\n         <header><h1>setupEndpoints</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> setupEndpoints</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000118-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- setupEndpoints -->\n      <div id=\"setupTransferTransport\" class=\"section\" >\n         <a name=\"setupTransferTransport\"></a>\n         <header><h1>setupTransferTransport</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> setupTransferTransport</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000201-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- setupTransferTransport -->\n      <div id=\"signalToNoiseRatio\" class=\"section\" >\n         <a name=\"signalToNoiseRatio\"></a>\n         <header><h1>signalToNoiseRatio</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> signalToNoiseRatio</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000241-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- signalToNoiseRatio -->\n      <div id=\"siriInputType\" class=\"section\" >\n         <a name=\"siriInputType\"></a>\n         <header><h1>siriInputType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> siriInputType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000132-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"PUSH_BUTTON_TRIGGERED_APPLE_TV\" </TD></tr>\n         </table>\n      </DIV>   <!-- siriInputType -->\n      <div id=\"slatType\" class=\"section\" >\n         <a name=\"slatType\"></a>\n         <header><h1>slatType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> slatType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C0-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"HORIZONTAL\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"VERTICAL\" </TD></tr>\n         </table>\n      </DIV>   <!-- slatType -->\n      <div id=\"sleepDiscoveryMode\" class=\"section\" >\n         <a name=\"sleepDiscoveryMode\"></a>\n         <header><h1>sleepDiscoveryMode</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> sleepDiscoveryMode</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E8-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NOT_DISCOVERABLE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ALWAYS_DISCOVERABLE\" </TD></tr>\n         </table>\n      </DIV>   <!-- sleepDiscoveryMode -->\n      <div id=\"sleepInterval\" class=\"section\" >\n         <a name=\"sleepInterval\"></a>\n         <header><h1>sleepInterval</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> sleepInterval</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000023A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- sleepInterval -->\n      <div id=\"smokeDetected\" class=\"section\" >\n         <a name=\"smokeDetected\"></a>\n         <header><h1>smokeDetected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> smokeDetected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000076-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SMOKE_NOT_DETECTED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"SMOKE_DETECTED\" </TD></tr>\n         </table>\n      </DIV>   <!-- smokeDetected -->\n      <div id=\"softwareRevision\" class=\"section\" >\n         <a name=\"softwareRevision\"></a>\n         <header><h1>softwareRevision</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> softwareRevision</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000054-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- softwareRevision -->\n      <div id=\"statusActive\" class=\"section\" >\n         <a name=\"statusActive\"></a>\n         <header><h1>statusActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> statusActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000075-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- statusActive -->\n      <div id=\"statusFault\" class=\"section\" >\n         <a name=\"statusFault\"></a>\n         <header><h1>statusFault</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> statusFault</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000077-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NO_FAULT\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"GENERAL_FAULT\" </TD></tr>\n         </table>\n      </DIV>   <!-- statusFault -->\n      <div id=\"statusJammed\" class=\"section\" >\n         <a name=\"statusJammed\"></a>\n         <header><h1>statusJammed</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> statusJammed</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000078-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NOT_JAMMED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"JAMMED\" </TD></tr>\n         </table>\n      </DIV>   <!-- statusJammed -->\n      <div id=\"statusLowBattery\" class=\"section\" >\n         <a name=\"statusLowBattery\"></a>\n         <header><h1>statusLowBattery</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> statusLowBattery</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000079-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"BATTERY_LEVEL_NORMAL\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"BATTERY_LEVEL_LOW\" </TD></tr>\n         </table>\n      </DIV>   <!-- statusLowBattery -->\n      <div id=\"statusTampered\" class=\"section\" >\n         <a name=\"statusTampered\"></a>\n         <header><h1>statusTampered</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> statusTampered</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000007A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NOT_TAMPERED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TAMPERED\" </TD></tr>\n         </table>\n      </DIV>   <!-- statusTampered -->\n      <div id=\"streamingStatus\" class=\"section\" >\n         <a name=\"streamingStatus\"></a>\n         <header><h1>streamingStatus</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> streamingStatus</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000120-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- streamingStatus -->\n      <div id=\"sulphurDioxideDensity\" class=\"section\" >\n         <a name=\"sulphurDioxideDensity\"></a>\n         <header><h1>sulphurDioxideDensity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> sulphurDioxideDensity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C5-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- sulphurDioxideDensity -->\n      <div id=\"supportedAudioRecordingConfiguration\" class=\"section\" >\n         <a name=\"supportedAudioRecordingConfiguration\"></a>\n         <header><h1>supportedAudioRecordingConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedAudioRecordingConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000207-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- supportedAudioRecordingConfiguration -->\n      <div id=\"supportedAudioStreamConfiguration\" class=\"section\" >\n         <a name=\"supportedAudioStreamConfiguration\"></a>\n         <header><h1>supportedAudioStreamConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedAudioStreamConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000115-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedAudioStreamConfiguration -->\n      <div id=\"supportedCameraRecordingConfiguration\" class=\"section\" >\n         <a name=\"supportedCameraRecordingConfiguration\"></a>\n         <header><h1>supportedCameraRecordingConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedCameraRecordingConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000205-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- supportedCameraRecordingConfiguration -->\n      <div id=\"supportedDataStreamTransportConfiguration\" class=\"section\" >\n         <a name=\"supportedDataStreamTransportConfiguration\"></a>\n         <header><h1>supportedDataStreamTransportConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedDataStreamTransportConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000130-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedDataStreamTransportConfiguration -->\n      <div id=\"supportedCharacteristicValueTransitionConfiguration\" class=\"section\" >\n         <a name=\"supportedCharacteristicValueTransitionConfiguration\"></a>\n         <header><h1>supportedCharacteristicValueTransitionConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedCharacteristicValueTransitionConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000144-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedCharacteristicValueTransitionConfiguration -->\n      <div id=\"supportedDiagnosticsSnapshot\" class=\"section\" >\n         <a name=\"supportedDiagnosticsSnapshot\"></a>\n         <header><h1>supportedDiagnosticsSnapshot</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedDiagnosticsSnapshot</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000238-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedDiagnosticsSnapshot -->\n      <div id=\"supportedRTPConfiguration\" class=\"section\" >\n         <a name=\"supportedRTPConfiguration\"></a>\n         <header><h1>supportedRTPConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedRTPConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000116-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedRTPConfiguration -->\n      <div id=\"supportedRouterConfiguration\" class=\"section\" >\n         <a name=\"supportedRouterConfiguration\"></a>\n         <header><h1>supportedRouterConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedRouterConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000210-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedRouterConfiguration -->\n      <div id=\"supportedTransferTransportConfiguration\" class=\"section\" >\n         <a name=\"supportedTransferTransportConfiguration\"></a>\n         <header><h1>supportedTransferTransportConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedTransferTransportConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000202-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedTransferTransportConfiguration -->\n      <div id=\"supportedVideoRecordingConfiguration\" class=\"section\" >\n         <a name=\"supportedVideoRecordingConfiguration\"></a>\n         <header><h1>supportedVideoRecordingConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedVideoRecordingConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000206-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- supportedVideoRecordingConfiguration -->\n      <div id=\"supportedVideoStreamConfiguration\" class=\"section\" >\n         <a name=\"supportedVideoStreamConfiguration\"></a>\n         <header><h1>supportedVideoStreamConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedVideoStreamConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000114-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedVideoStreamConfiguration -->\n      <div id=\"swingMode\" class=\"section\" >\n         <a name=\"swingMode\"></a>\n         <header><h1>swingMode</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> swingMode</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B6-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SWING_DISABLED\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"SWING_ENABLED\" </TD></tr>\n         </table>\n      </DIV>   <!-- swingMode -->\n      <div id=\"targetAirPurifierState\" class=\"section\" >\n         <a name=\"targetAirPurifierState\"></a>\n         <header><h1>targetAirPurifierState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetAirPurifierState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000A8-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"MANUAL\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"AUTO\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetAirPurifierState -->\n      <div id=\"targetControlList\" class=\"section\" >\n         <a name=\"targetControlList\"></a>\n         <header><h1>targetControlList</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetControlList</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000124-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write, Paired Read, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- targetControlList -->\n      <div id=\"targetControlSupportedConfiguration\" class=\"section\" >\n         <a name=\"targetControlSupportedConfiguration\"></a>\n         <header><h1>targetControlSupportedConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetControlSupportedConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000123-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- targetControlSupportedConfiguration -->\n      <div id=\"targetDoorState\" class=\"section\" >\n         <a name=\"targetDoorState\"></a>\n         <header><h1>targetDoorState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetDoorState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000032-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OPEN\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CLOSED\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetDoorState -->\n      <div id=\"targetFanState\" class=\"section\" >\n         <a name=\"targetFanState\"></a>\n         <header><h1>targetFanState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetFanState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000BF-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"MANUAL\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"AUTO\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetFanState -->\n      <div id=\"targetHeaterCoolerState\" class=\"section\" >\n         <a name=\"targetHeaterCoolerState\"></a>\n         <header><h1>targetHeaterCoolerState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetHeaterCoolerState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B2-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"AUTO\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HEAT\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"COOL\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetHeaterCoolerState -->\n      <div id=\"targetHeatingCoolingState\" class=\"section\" >\n         <a name=\"targetHeatingCoolingState\"></a>\n         <header><h1>targetHeatingCoolingState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetHeatingCoolingState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000033-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OFF\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HEAT\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"COOL\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"AUTO\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetHeatingCoolingState -->\n      <div id=\"targetHorizontalTiltAngle\" class=\"section\" >\n         <a name=\"targetHorizontalTiltAngle\"></a>\n         <header><h1>targetHorizontalTiltAngle</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetHorizontalTiltAngle</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000007B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -90</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  90</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- targetHorizontalTiltAngle -->\n      <div id=\"targetHumidifierDehumidifierState\" class=\"section\" >\n         <a name=\"targetHumidifierDehumidifierState\"></a>\n         <header><h1>targetHumidifierDehumidifierState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetHumidifierDehumidifierState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B4-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"HUMIDIFIER_OR_DEHUMIDIFIER\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HUMIDIFIER\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"DEHUMIDIFIER\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetHumidifierDehumidifierState -->\n      <div id=\"targetMediaState\" class=\"section\" >\n         <a name=\"targetMediaState\"></a>\n         <header><h1>targetMediaState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetMediaState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000137-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"PLAY\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"PAUSE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"STOP\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetMediaState -->\n      <div id=\"targetPosition\" class=\"section\" >\n         <a name=\"targetPosition\"></a>\n         <header><h1>targetPosition</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetPosition</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000007C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- targetPosition -->\n      <div id=\"targetRelativeHumidity\" class=\"section\" >\n         <a name=\"targetRelativeHumidity\"></a>\n         <header><h1>targetRelativeHumidity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetRelativeHumidity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000034-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- targetRelativeHumidity -->\n      <div id=\"targetTemperature\" class=\"section\" >\n         <a name=\"targetTemperature\"></a>\n         <header><h1>targetTemperature</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetTemperature</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000035-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Unit: </TD><TD>  celsius</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  10</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  38</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  0.1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- targetTemperature -->\n      <div id=\"targetTiltAngle\" class=\"section\" >\n         <a name=\"targetTiltAngle\"></a>\n         <header><h1>targetTiltAngle</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetTiltAngle</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C2-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -90</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  90</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- targetTiltAngle -->\n      <div id=\"targetVerticalTiltAngle\" class=\"section\" >\n         <a name=\"targetVerticalTiltAngle\"></a>\n         <header><h1>targetVerticalTiltAngle</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetVerticalTiltAngle</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000007D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Unit: </TD><TD>  arcdegrees</TD></tr>\n            <tr><TD> Min Value: </TD><TD>  -90</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  90</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- targetVerticalTiltAngle -->\n      <div id=\"targetVisibilityState\" class=\"section\" >\n         <a name=\"targetVisibilityState\"></a>\n         <header><h1>targetVisibilityState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> targetVisibilityState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000134-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"SHOWN\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"HIDDEN\" </TD></tr>\n         </table>\n      </DIV>   <!-- targetVisibilityState -->\n      <div id=\"temperatureDisplayUnits\" class=\"section\" >\n         <a name=\"temperatureDisplayUnits\"></a>\n         <header><h1>temperatureDisplayUnits</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> temperatureDisplayUnits</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000036-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"CELSIUS\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"FAHRENHEIT\" </TD></tr>\n         </table>\n      </DIV>   <!-- temperatureDisplayUnits -->\n      <div id=\"thirdPartyCameraActive\" class=\"section\" >\n         <a name=\"thirdPartyCameraActive\"></a>\n         <header><h1>thirdPartyCameraActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> thirdPartyCameraActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000021C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"OFF\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"ON\" </TD></tr>\n         </table>\n      </DIV>   <!-- thirdPartyCameraActive -->\n      <div id=\"transmitPower\" class=\"section\" >\n         <a name=\"transmitPower\"></a>\n         <header><h1>transmitPower</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> transmitPower</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000242-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- transmitPower -->\n      <div id=\"MaximumTransmitPower\" class=\"section\" >\n         <a name=\"MaximumTransmitPower\"></a>\n         <header><h1>MaximumTransmitPower</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> MaximumTransmitPower</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000243-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- MaximumTransmitPower -->\n      <div id=\"tunnelConnectionTimeout\" class=\"section\" >\n         <a name=\"tunnelConnectionTimeout\"></a>\n         <header><h1>tunnelConnectionTimeout</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> tunnelConnectionTimeout</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000061-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write, Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- tunnelConnectionTimeout -->\n      <div id=\"tunneledAccessoryAdvertising\" class=\"section\" >\n         <a name=\"tunneledAccessoryAdvertising\"></a>\n         <header><h1>tunneledAccessoryAdvertising</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> tunneledAccessoryAdvertising</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000060-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write, Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- tunneledAccessoryAdvertising -->\n      <div id=\"tunneledAccessoryConnected\" class=\"section\" >\n         <a name=\"tunneledAccessoryConnected\"></a>\n         <header><h1>tunneledAccessoryConnected</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> tunneledAccessoryConnected</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000059-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write, Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"FALSE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"TRUE\" </TD></tr>\n         </table>\n      </DIV>   <!-- tunneledAccessoryConnected -->\n      <div id=\"tunneledAccessoryStateNumber\" class=\"section\" >\n         <a name=\"tunneledAccessoryStateNumber\"></a>\n         <header><h1>tunneledAccessoryStateNumber</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> tunneledAccessoryStateNumber</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000058-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> int</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- tunneledAccessoryStateNumber -->\n      <div id=\"vocDensity\" class=\"section\" >\n         <a name=\"vocDensity\"></a>\n         <header><h1>vocDensity</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> vocDensity</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000C8-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1000</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- vocDensity -->\n      <div id=\"valveType\" class=\"section\" >\n         <a name=\"valveType\"></a>\n         <header><h1>valveType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> valveType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000D5-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"GENERIC_VALVE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"IRRIGATION\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"SHOWER_HEAD\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"WATER_FAUCET\" </TD></tr>\n         </table>\n      </DIV>   <!-- valveType -->\n      <div id=\"version\" class=\"section\" >\n         <a name=\"version\"></a>\n         <header><h1>version</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> version</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000037-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- version -->\n      <div id=\"videoAnalysisActive\" class=\"section\" >\n         <a name=\"videoAnalysisActive\"></a>\n         <header><h1>videoAnalysisActive</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> videoAnalysisActive</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000229-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- videoAnalysisActive -->\n      <div id=\"volume\" class=\"section\" >\n         <a name=\"volume\"></a>\n         <header><h1>volume</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> volume</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000119-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Unit: </TD><TD>  percentage</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events</TD></tr>\n         </table>\n      </DIV>   <!-- volume -->\n      <div id=\"volumeControlType\" class=\"section\" >\n         <a name=\"volumeControlType\"></a>\n         <header><h1>volumeControlType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> volumeControlType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000E9-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  3</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"NONE\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"RELATIVE\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"RELATIVE_WITH_CURRENT\" </TD></tr>\n            <tr><TD> 3 </TD><TD> \"ABSOLUTE\" </TD></tr>\n         </table>\n      </DIV>   <!-- volumeControlType -->\n      <div id=\"volumeSelector\" class=\"section\" >\n         <a name=\"volumeSelector\"></a>\n         <header><h1>volumeSelector</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> volumeSelector</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000EA-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"INCREMENT\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"DECREMENT\" </TD></tr>\n         </table>\n      </DIV>   <!-- volumeSelector -->\n      <div id=\"wanConfigurationList\" class=\"section\" >\n         <a name=\"wanConfigurationList\"></a>\n         <header><h1>wanConfigurationList</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> wanConfigurationList</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000211-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- wanConfigurationList -->\n      <div id=\"wanStatusList\" class=\"section\" >\n         <a name=\"wanStatusList\"></a>\n         <header><h1>wanStatusList</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> wanStatusList</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000212-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- wanStatusList -->\n      <div id=\"wakeConfiguration\" class=\"section\" >\n         <a name=\"wakeConfiguration\"></a>\n         <header><h1>wakeConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> wakeConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000222-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- wakeConfiguration -->\n      <div id=\"waterLevel\" class=\"section\" >\n         <a name=\"waterLevel\"></a>\n         <header><h1>waterLevel</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> waterLevel</TD></tr>\n            <tr><TD> UUID: </TD><TD> 000000B5-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> float</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  100</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- waterLevel -->\n      <div id=\"wifiCapabilities\" class=\"section\" >\n         <a name=\"wifiCapabilities\"></a>\n         <header><h1>wifiCapabilities</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> wifiCapabilities</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000022C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- wifiCapabilities -->\n      <div id=\"wifiConfigurationControl\" class=\"section\" >\n         <a name=\"wifiConfigurationControl\"></a>\n         <header><h1>wifiConfigurationControl</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> wifiConfigurationControl</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000022D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Events, Timed Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- wifiConfigurationControl -->\n      <div id=\"wifiSatelliteStatus\" class=\"section\" >\n         <a name=\"wifiSatelliteStatus\"></a>\n         <header><h1>wifiSatelliteStatus</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> wifiSatelliteStatus</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000021E-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  2</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n         <h3>Constants</h3>\n         <table>\n            <TD> Value </TD><TD> String </TD>\n            <tr><TD> 0 </TD><TD> \"UNKNOWN\" </TD></tr>\n            <tr><TD> 1 </TD><TD> \"CONNECTED\" </TD></tr>\n            <tr><TD> 2 </TD><TD> \"NOT_CONNECTED\" </TD></tr>\n         </table>\n      </DIV>   <!-- wifiSatelliteStatus -->\n      <div id=\"assetUpdateReadiness\" class=\"section\" >\n         <a name=\"assetUpdateReadiness\"></a>\n         <header><h1>assetUpdateReadiness</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> assetUpdateReadiness</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000269-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- assetUpdateReadiness -->\n      <div id=\"supportedAssetTypes\" class=\"section\" >\n         <a name=\"supportedAssetTypes\"></a>\n         <header><h1>supportedAssetTypes</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedAssetTypes</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000268-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedAssetTypes -->\n      <div id=\"configurationState\" class=\"section\" >\n         <a name=\"configurationState\"></a>\n         <header><h1>configurationState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> configurationState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000263-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint16</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- configurationState -->\n      <div id=\"NFCAccessControlPoint\" class=\"section\" >\n         <a name=\"NFCAccessControlPoint\"></a>\n         <header><h1>NFCAccessControlPoint</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> NFCAccessControlPoint</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000264-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- NFCAccessControlPoint -->\n      <div id=\"NFCAccessSupportedConfiguration\" class=\"section\" >\n         <a name=\"NFCAccessSupportedConfiguration\"></a>\n         <header><h1>NFCAccessSupportedConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> NFCAccessSupportedConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000265-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- NFCAccessSupportedConfiguration -->\n      <div id=\"SiriEndpointSessionStatus\" class=\"section\" >\n         <a name=\"SiriEndpointSessionStatus\"></a>\n         <header><h1>SiriEndpointSessionStatus</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> SiriEndpointSessionStatus</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000254-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- SiriEndpointSessionStatus -->\n      <div id=\"threadControlPoint\" class=\"section\" >\n         <a name=\"threadControlPoint\"></a>\n         <header><h1>threadControlPoint</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> threadControlPoint</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000704-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- threadControlPoint -->\n      <div id=\"threadNodeCapabilities\" class=\"section\" >\n         <a name=\"threadNodeCapabilities\"></a>\n         <header><h1>threadNodeCapabilities</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> threadNodeCapabilities</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000702-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint16</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  31</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- threadNodeCapabilities -->\n      <div id=\"threadStatus\" class=\"section\" >\n         <a name=\"threadStatus\"></a>\n         <header><h1>threadStatus</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> threadStatus</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000703-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint16</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  6</TD></tr>\n            <tr><TD> Min Step: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Events</TD></tr>\n         </table>\n      </DIV>   <!-- threadStatus -->\n      <div id=\"threadOpenThreadVersion\" class=\"section\" >\n         <a name=\"threadOpenThreadVersion\"></a>\n         <header><h1>threadOpenThreadVersion</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> threadOpenThreadVersion</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000706-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- threadOpenThreadVersion -->\n      <div id=\"accessCodeControlPoint\" class=\"section\" >\n         <a name=\"accessCodeControlPoint\"></a>\n         <header><h1>accessCodeControlPoint</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> accessCodeControlPoint</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000262-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- accessCodeControlPoint -->\n      <div id=\"accessCodeSupportedConfiguration\" class=\"section\" >\n         <a name=\"accessCodeSupportedConfiguration\"></a>\n         <header><h1>accessCodeSupportedConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> accessCodeSupportedConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000261-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- accessCodeSupportedConfiguration -->\n      <div id=\"airPlayEnable\" class=\"section\" >\n         <a name=\"airPlayEnable\"></a>\n         <header><h1>airPlayEnable</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> airPlayEnable</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000025B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- airPlayEnable -->\n      <div id=\"characteristicValueActiveTransitionCount\" class=\"section\" >\n         <a name=\"characteristicValueActiveTransitionCount\"></a>\n         <header><h1>characteristicValueActiveTransitionCount</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> characteristicValueActiveTransitionCount</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000024B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- characteristicValueActiveTransitionCount -->\n      <div id=\"cryptoHash\" class=\"section\" >\n         <a name=\"cryptoHash\"></a>\n         <header><h1>cryptoHash</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> cryptoHash</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000250-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- cryptoHash -->\n      <div id=\"firmwareUpdateReadiness\" class=\"section\" >\n         <a name=\"firmwareUpdateReadiness\"></a>\n         <header><h1>firmwareUpdateReadiness</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> firmwareUpdateReadiness</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000234-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- firmwareUpdateReadiness -->\n      <div id=\"firmwareUpdateStatus\" class=\"section\" >\n         <a name=\"firmwareUpdateStatus\"></a>\n         <header><h1>firmwareUpdateStatus</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> firmwareUpdateStatus</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000235-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- firmwareUpdateStatus -->\n      <div id=\"hardwareFinish\" class=\"section\" >\n         <a name=\"hardwareFinish\"></a>\n         <header><h1>hardwareFinish</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> hardwareFinish</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000026C-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- hardwareFinish -->\n      <div id=\"MetricsBufferFullState\" class=\"section\" >\n         <a name=\"MetricsBufferFullState\"></a>\n         <header><h1>MetricsBufferFullState</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> MetricsBufferFullState</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000272-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> bool</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- MetricsBufferFullState -->\n      <div id=\"multiFunctionButton\" class=\"section\" >\n         <a name=\"multiFunctionButton\"></a>\n         <header><h1>multiFunctionButton</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> multiFunctionButton</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000026B-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- multiFunctionButton -->\n      <div id=\"selectedDiagnosticsModes\" class=\"section\" >\n         <a name=\"selectedDiagnosticsModes\"></a>\n         <header><h1>selectedDiagnosticsModes</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> selectedDiagnosticsModes</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000024D-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint32</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- selectedDiagnosticsModes -->\n      <div id=\"selectedSleepConfiguration\" class=\"section\" >\n         <a name=\"selectedSleepConfiguration\"></a>\n         <header><h1>selectedSleepConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> selectedSleepConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000252-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write, Write Response</TD></tr>\n         </table>\n      </DIV>   <!-- selectedSleepConfiguration -->\n      <div id=\"siriEnable\" class=\"section\" >\n         <a name=\"siriEnable\"></a>\n         <header><h1>siriEnable</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> siriEnable</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000255-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- siriEnable -->\n      <div id=\"siriEngineVersion\" class=\"section\" >\n         <a name=\"siriEngineVersion\"></a>\n         <header><h1>siriEngineVersion</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> siriEngineVersion</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000025A-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- siriEngineVersion -->\n      <div id=\"siriLightOnUse\" class=\"section\" >\n         <a name=\"siriLightOnUse\"></a>\n         <header><h1>siriLightOnUse</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> siriLightOnUse</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000258-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- siriLightOnUse -->\n      <div id=\"siriListening\" class=\"section\" >\n         <a name=\"siriListening\"></a>\n         <header><h1>siriListening</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> siriListening</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000256-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- siriListening -->\n      <div id=\"siriTouchToUse\" class=\"section\" >\n         <a name=\"siriTouchToUse\"></a>\n         <header><h1>siriTouchToUse</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> siriTouchToUse</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000257-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint8</TD></tr>\n            <tr><TD> Max Value: </TD><TD>  1</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- siriTouchToUse -->\n      <div id=\"StagedFirmwareVersion\" class=\"section\" >\n         <a name=\"StagedFirmwareVersion\"></a>\n         <header><h1>StagedFirmwareVersion</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> StagedFirmwareVersion</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000249-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> string</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Events, Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- StagedFirmwareVersion -->\n      <div id=\"supportedMetrics\" class=\"section\" >\n         <a name=\"supportedMetrics\"></a>\n         <header><h1>supportedMetrics</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedMetrics</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000271-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read, Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- supportedMetrics -->\n      <div id=\"supportedFirmwareUpdateConfiguration\" class=\"section\" >\n         <a name=\"supportedFirmwareUpdateConfiguration\"></a>\n         <header><h1>supportedFirmwareUpdateConfiguration</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> supportedFirmwareUpdateConfiguration</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000233-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> tlv8</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- supportedFirmwareUpdateConfiguration -->\n      <div id=\"tapType\" class=\"section\" >\n         <a name=\"tapType\"></a>\n         <header><h1>tapType</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> tapType</TD></tr>\n            <tr><TD> UUID: </TD><TD> 0000022F-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> uint16</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Read</TD></tr>\n         </table>\n      </DIV>   <!-- tapType -->\n      <div id=\"token\" class=\"section\" >\n         <a name=\"token\"></a>\n         <header><h1>token</h1></header>\n         <h3>Properties</h3>\n         <table>\n            <tr><TD> Type: </TD><TD> token</TD></tr>\n            <tr><TD> UUID: </TD><TD> 00000231-0000-1000-8000-0026BB765291</TD></tr>\n            <tr><TD> Format: </TD><TD> data</TD></tr>\n            <tr><TD> Perms: </TD><TD>  Paired Write</TD></tr>\n         </table>\n      </DIV>   <!-- token -->\n      <div id=\"Directives\" class=\"section\">\n         <h2>CMD4 Directives</h2>\n         <p>These directives appear within the \"Cmd4\" plugin header and reflect how Cmd4 will behave overall.</p>\n         <TABLE WIDTH=\"100%\">\n            <TR ALIGN=\"left\"><TH>Cmd4Directive<TH>Type<TH PADDING=\"50px\">Default<TH>Description</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"debug_D\">debug</a><TD>  < Bool >  <TD>    false    <TD> Output Debug messages. Can also be accomplished with setenv DEBUG=Cmd4</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"outputConstants_D\">outputConstants</a><TD>  < Bool >  <TD>    false    <TD> If Cmd4 will send Strings like \"TRUE\" or \"FALSE\" instead of 0 | 1 for all Accessories</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"statusMsg_D\"> statusMsg</a><TD> < Bool > <TD> TRUE <TD> Cmd4 will log a Set Status Message for all Accessories.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"interval_D\"> interval</a><TD> interval <TD> 60 < seconds > <TD> How long before killing the state command of all polled characteristics. See <a href=\"#interval\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">interval</a> in Accessory Directives for full description as it can also be set per accessory or per characteristic.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"timeout_D\"> timeout</a><TD> timeout <TD> 60000 < msec > <TD> How long before killing the state command of all polled characteristics. See <a href=\"#timeout\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">timeout</a> in Accessory Directives for full description as it can also be set per accessory or per characteristic.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"queueTypes_D\"> queueTypes</a><TD> < Array of { \"queue\": < \"SomeName\" >, \"queueType\": < \"Sequential\" | \"WoRm\" > \"retries\": < 0 > } <TD> none <TD> Pre-defines Queue types. This Directive can also be per queue as noted by its presence as an accessory directive.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"definitions_D\"> definitions</a><TD> < Array > <TD> <TD> An Array of new Characteristic Objects. See <a href=\"#CUSTOM_CHARACTERISTICS\" onclick=\"toggleVisibility( 'CustomCharacteristics');\">Custom Characteristics, around line 339</a> for more information</TR>\n         </TABLE>\n      </DIV>   <!-- main -->\n      <div id=\"AccessoryDirectives\" class=\"section\">\n         <h2><a name=\"CMD4 Accessory Directives\">CMD4 Accessory Directives</a></h2>\n         <p>These directives appear within the characteristic section of the Cmd4 Accessory</p>\n         <TABLE WIDTH=\"100%\" border: 1px solid black >\n            <TR cols=\"4\" ALIGN=\"left\"><TH>Cmd4Directive<TH>Type<TH PADDING=\"50px\">Default<TH>Description</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"subType\">subType</a><TD> < unique string > <TD> accessory.name <TD> Used to distinguish accessories that have same Type and Name.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"outputConstants\">outputConstants</a><TD>  < Bool >  <TD>    false    <TD> If Cmd4 will send Strings like \"TRUE\" or \"FALSE\" instead of 0 | 1 </TR>\n            <TR ALIGN=\"left\"><TD><a name=\"statusMsg\">statusMsg</a><TD>  < Bool >  <TD>  TRUE <TD>Cmd4 will log a Set Status Message</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"publishExternally\">publishExternally</a><TD>  < Bool >  <TD>    false     <TD> Tell Homebridge to publish the device as its own bridge. </TR>\n            <TR ALIGN=\"left\"><TD><a name=\"stateChangeResponseTime\">stateChangeResponseTime</a><TD> < seconds > <TD> 60 <TD> How long to wait between a Set and Get command.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"interval\">interval</a><TD> < seconds > <TD> 60 < seconds > <TD> How long between polls of all polled characteristics.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"timeout\">timeout</a><TD> < msec > <TD> 60000 < msec > <TD> How long before killing the state command of all polled characteristics.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"polling\">polling</a><TD> < Bool > <TD> false <TD> If the characteristics should be polled for state change.</TR>\n            <TR><TD><TD COLSPAN=3> or  [{\"characteristic\" < characteristic >, [ \"interval\": < sec >, \"timeout\": < msec > ] }] The timeout and interval override any higher directive.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"queue\"> queue</a><TD> queue <TD> < String > <TD> Defines which Queue polled characteristics will be placed.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"state_cmd\">state_cmd</a><TD>  < state_cmd > <TD> See Description <TD> The command used to Get/Set Device characteristic State.</TR>\n            <TR><TD COLSPAN=\"4\">The state_cmd represents the path to your script. Cmd4 appends the Get/Set shown.<BR>\n            state_cmd Get < DisplayName > < characteristic ><BR>\n            state_cmd Set < DisplayName > < characteristic > < value ></TD></TR>\n            <TR ALIGN=\"left\"><TD><a name=\"state_cmd_prefix\">state_cmd_prefix</a><TD>  < String > <TD> <TD> A String prepended to the < state_cmd >.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"state_cmd_suffix\">state_cmd_suffix</a><TD> < String > <TD> <TD> A String appended to the < state_cmd >.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"props\">props</a><TD>  < Bool >  <TD>    false     <TD> A way to override Hap Characteristiic Properties<BR>\n                     Only used to set min/max temperatures, for instance:</TR>\n            <TR ALIGN=\"Left\"><TD><TD COLSPAN=3>\"props\" : { \"currentTemperature\": { \"maxValue\":100, \"minValue\": -100, \"minStep\": 0.1}}</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"category\">category</a><TD> < CATEGORY > <TD> <TD> See <a href=\"https://developers.homebridge.io/#/categories\">Homebridge Categories</a> for a complete list of possible categories.  </TR>\n            <TR ALIGN=\"left\"><TD><a name=\"fakegato\">fakegato</a><TD>  < JSON >  <TD> <TD> See the section, <a href=\"https://github.com/ztalbot2000/homebridge-cmd4/docs/Developers.md#fakegatotag\"> \"Adding in Fakegato history\"</a> below.</TR>\n            <TR ALIGN=\"left\"><TD><a name=\"linkedTypes\">linkedTypes</a><TD>  < JSON >  <TD> <TD> Other Cmd4 Accessories like Input Source for HDMI inputs. </TR>\n         </TABLE>\n      </DIV>   <!-- main -->\n      <div id=\"CustomCharacteristics\" class=\"section\">\n         <h2><a name=\"CUSTOM_CHARACTERISTICS\">Custom Characteristics</a></h2>\n         <p>These directives appear within the Cmd4 Platform section</p><BR>\n         <p>IMPORTANT - It is unlikely that adding custom characteristics will be supported by any GUI or SIRI<BR>\n         <BR><BR>\n         <p>Custom characteristics in Cmd4 do not stray far from how Homebridge uses them from HAP-NodeJS. To create a custom characteristic an object entry is programmatically added to <a href=\"https://github.com/ztalbot2000/homebridge-cmd4/blob/master/lib/CMD4_ACC_TYPE_ENUM.js\">lib/CMD4_ACC_TYPE_ENUM.js</a> via an entry you define in your config.json. The best way to show how to define a custom characteristic is through an example</p>.\n         <pre>\n            {\n               \"platform\": \"Cmd4\",\n               \"outputConstants\": false,\n               \"statusMsg\": true,\n               \"Definitions\": [\n                  { \"type\": \"PointX\",\n                    \"description\": \"An X Coordinate\",\n                    \"props\": { \"format\": \"uint32\",\n                               \"minValue\": 0,\n                               \"minStep\": 1,\n                               \"perms\": [ \"ev\", \"pr\", \"pw\" ]\n                             }\n                  }\n               ],\n               \"accessories\": [\n                  { \"type\": \"Switch\",\n                    \"name\": \"PS_4\",\n                    \"PointX\": 3267,\n                    \"on\": false,\n                    \"polling\": [ { \"characteristic\": \"on\", \"interval\": 50 },\n                                 { \"characteristic\": \"pointX\", \"interval\": 5 }\n                               ],\n                    \"state_cmd\": \"node .homebridge/Cmd4Scripts/AnyDevice.js\"\n                  }\n               ]\n            }\n         </pre>\n         <BR><BR>\n         <p>The definitions for \"props\" can be found at: <a href=\"https://github.com/homebridge/HAP-NodeJS/blob/master/src/lib/Characteristic.ts\">HAP Characteristics - line 259</a></p>\n      </DIV>   <!-- CustomCharacteristics -->\n      <div id=\"JS Template\" class=\"section\">\n         <h2><a name=\"JS Template\">Example Cmd4 JavaScript Template</a></h2>\n         <p> This script is auto generated from: <a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/./Extras/Cmd4Scripts/Examples/ExampleJavaScript_template.js>./Extras/Cmd4Scripts/Examples/ExampleJavaScript_template.js </a></p>\n         <pre>\n#!/usr/bin/env node\n//  ExampleScript_template.js\n//\n// Description:\n//   This script is a goood starting place for you to create Cmd4 Scripts\n//   of your own\n//\n// Parameters are:\n//    Get < Any accessory name > < Characteristic >\n//    Set < Any accessory name > < Characteristic > < value >\n//\n// Note 1: These paramaters match the those of the Cmd4 plugin.\n//         A full lost of supported devices and characteristics can be\n//         found at:\n//         https://ztalbot2000.github.io/homebridge-cmd4\n//\n// How it works:\n//    The Cmd4 plugin will call this script to retrieve those states\n//    you have defined as not Cached to Get/Set your devices characteristic\n//    states.\n//\n//    For example:\n//       node ExampleScript_template.js Set My_Door TargetDoorState 0\n//     or\n//       node ExampleScript.js Get My_Door CurrentDoorState\n//\n//\n\n'use strict';\n\nvar length = process.argv.length;\nvar device = \"My_Door\";\nvar io = \"\";\nvar characteristic = \"\";\nvar option = \"\";\n\nif ( length == 2 ) process.exit( 0 );\n\nif ( length <= 2 ) {\n    console.log( \"Usage: \" + process.argv[0] + \" < Get > < AccessoryName > < Characteristic >\" );\n    console.log( \"       \" + process.argv[0] + \" < Set > < AccessoryName > < Characteristic > < Value >\" );\n    process.exit( -1 );\n}\n\nif ( length >= 2 ) io = process.argv[2];\nif ( length >= 3 ) device = process.argv[3];\nif ( length >= 4 ) characteristic  = process.argv[4];\nif ( length >= 5 ) option  = process.argv[5];\n\nvar c = \"\";\n\nswitch( io )\n{\n    case \"Get\":\n    {\n        switch( characteristic )\n        {\n            case \"CurrentDoorState\":\n            {\n               console.log( 0 );\n\n               // See https://ztalbot2000.github.io/homebridge-cmd4\n               // For the possible values and characteristics\n               // available per device. It will show somethink like:\n               // Valid Values:\n               // 0 - \"Open. The door is fully open.\"\n               // 1 - \"Closed. The door is fully closed.\"\n               // 2 - \"Opening. The door is actively opening.\"\n               // 3 - \"Closing. The door is actively closing.\"\n               // 4 - \"Stopped. The door is not moving, and it is not fully\n               //      open nor fully closed.\"\n               // 5-255 - \"Reserved\"\n\n               break;\n            }\n            case \"TargetDoorState\":\n            {\n                console.log( 0 );\n                break;\n            }\n            case \"ObstructionDetected\":\n            {\n                console.log ( 0 );\n                break;\n            }\n            case \"LockCurrentState\":\n            {\n                console.log ( 0 );\n                break;\n            }\n            default:\n                console.error( \"Unhandled characteristic for:\"  + io  +  \" Device:\" + device  +  \" Characteristic:\" + characteristic );\n                process.exit( -1 );\n        }\n\n        break;\n\n    } // End of Switch for \"Get\"\n    case \"Set\":\n    {\n        switch( characteristic )\n        {\n            case \"CurrentDoorState\":\n            {\n               // Current Door State is not settable. The\n               // call would be to TargetDoorState. This is here\n               // for debugging only.\n\n               break;\n            }\n            case \"TargetDoorState\":\n            {\n                // Do something of your own here.\n\n                break;\n            }\n            case \"ObstructionDetected\":\n            {\n               // Obstruction Detected is not settable. It\n               // call is a read-only characteristic. This is here\n               // for debugging only.\n               break;\n            }\n            case \"LockCurrentState\":\n            {\n                // Lock Current State is not settable. It\n                // call is a read-only characteristic. This is here\n                // for debugging only.\n                break;\n            }\n            default:\n                console.error( \"UnHandled Characteristic for:\"  + io  +  \" Device:\" + device  +  \" Characteristic:\" + characteristic );\n                process.exit( -1 );\n        }\n\n        break;\n    } // End of Switch Device for \"Set\"\n    default:\n        console.error( \"Unknown IO\" + io );\n        process.exit( -1 );\n}\n\n//console.log( \"Say What Device:\" + device + \" Characteristic:\" + characteristic + \" Option:\" + option );\n\n// You must exit with a zero status, confirming the script rannsuccessfully.\nprocess.exit( 0 );\n\n\n         </pre>\n      </DIV>   <!-- main -->\n      <div id=\"Bash Template\" class=\"section\">\n         <h2><a name=\"Bash Template\">Example Cmd4 Shell Script Template</a></h2>\n         <p> This script is auto generated from: <a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/./Extras/Cmd4Scripts/Examples/ExampleShellScript_template.sh>./Extras/Cmd4Scripts/Examples/ExampleShellScript_template.sh </a></p>\n         <pre>\n#!/bin/bash\n\n#  ExampleScript_template.sh\n#\n# Description:\n#   This script is a goood starting place for you to create Cmd4 Scripts\n#   of your own\n#\n# Parameters are:\n#    Get < Any accessory name > < Characteristic>\n#    Set < Any accessory name > < Characteristic> < value >\n#\n# Note 1: These paramaters match the those of the Cmd4 plugin.\n#         A full lost of supported devices and characteristics can be\n#         found at:\n#         https://ztalbot2000.github.io/homebridge-cmd4\n#\n# How it works:\n#\n#    The Cmd4 plugin will call this script to retrieve those states\n#    you have defined as not Cached to Get/Set your devices characteristic\n#    states.\n#\n#    For example:\n#       bash ExampleScript_template.sh Set My_Door TargetDoorState 0\n#     or\n#       bash ExampleScript.sh Get My_Door CurrentDoorState\n#\n\nset -e\n\n# Exit immediately for unbound variables.\nset -u\n\n\nlength=$#\ndevice=\"\"\nio=\"\"\ncharacteristic=\"\"\noption=\"\"\n\nif [ $length -le 1 ]; then\n   printf \"Usage: $0 Get < AccessoryName > < Characteristic >\\n\"\n   printf \"Usage: $0 Set < AccessoryName > < Characteristic > < Value >\\n\"\n   exit -1\nfi\n\n# printf \"args =$#\\n\"   # debug\n# printf \"arg1 =$1\\n\"   # debug\n\nif [ $length -ge 1 ]; then\n    io=$1\n    # printf \"io=$io\\n\"   # debug\nfi\nif [ $length -ge 2 ]; then\n    device=$2\n    # printf \"device = ${device}\\n\"   # debug\nfi\nif [ $length -ge 3 ]; then\n    characteristic=$3\n    # printf \"Characteristic = ${characteristic}\\n\"   # debug\nfi\nif [ $length -ge 4 ]; then\n    option=$4\n    # printf \"option = ${option}\\n\"   # debug\nfi\n\nif [ \"${io}\" == \"Get\" ]; then\n   case $characteristic in\n      'CurrentDoorState')\n\n         printf \"0\\n\"          # Door is open\n\n         # See https://ztalbot2000.github.io/homebridge-cmd4\n         # For the possible values and characteristics\n         # available per device. It will show somethink like:\n         # Valid Values:\n         # 0 - \"Open. The door is fully open.\"\n         # 1 - \"Closed. The door is fully closed.\"\n         # 2 - \"Opening. The door is actively opening.\"\n         # 3 - \"Closing. The door is actively closing.\"\n         # 4 - \"Stopped. The door is not moving, and it is not fully\n         #      open nor fully closed.\"\n         # 5-255 - \"Reserved\"\n         exit 0\n         ;;\n      'TargetDoorState')\n         printf \"0\\n\"\n         exit 0\n         ;;\n      'ObstructionDetected')\n         printf \"0\\n\"\n         exit 0\n         ;;\n      'LockCurrentState')\n         printf \"0\\n\"\n         exit 0\n         ;;\n      *)\n         printf \"UnHandled Get ${device}  Characteristic ${characteristic}\\n\"\n         exit -1\n         ;;\n    esac\nfi\nif [ \"${io}\" == 'Set' ]; then\n   case $characteristic in\n      'CurrentDoorState')\n         # Current Door State is not settable. The\n         # call would be to TargetDoorState. This is here\n         # for debugging only.\n\n         exit 0\n         ;;\n      'TargetDoorState')\n         # Do something of your own here.\n         exit 0\n         ;;\n      'ObstructionDetected')\n         # Obstruction Detected is not settable. It\n         # call is a read-only characteristic. This is here\n         # for debugging only.\n         exit 0\n         ;;\n      'LockCurrentState')\n         # Lock Current State is not settable. It\n         # call is a read-only characteristic. This is here\n         # for debugging only.\n         exit 0\n         ;;\n      *)\n         printf \"UnHandled Set GarageDoorOpenner Characteristic ${characteristic}\"\n         exit -1\n         ;;\n    esac\nfi\nprintf \"Unknown io command ${io}\\n\"\nexit -1\n\n\n         </pre>\n      </DIV>   <!-- main -->\n   </DIV>   <!-- main -->\n</DIV>   <!-- content -->\n<script>\n   var acc = document.getElementsByClassName(\"accordion\");\nvar i;\n\nfor (i = 0; i < acc.length; i++) {\n  acc[i].addEventListener(\"click\", function() {\n    this.classList.toggle(\"active\");\n    var panel = this.nextElementSibling;\n    if (panel.style.display === \"block\") {\n      panel.style.display = \"none\";\n    } else {\n      panel.style.display = \"block\";\n    }\n  });\n}\n</script>\n<script>\n   \n// Loop through all dropdown buttons to toggle between hiding and\n// showing its dropdown content - This allows the user to have\n// multiple dropdowns without any conflict\n\nvar dropdown = document.getElementsByClassName(\"dropdown-btn\");\n\nfor (let i = 0; i < dropdown.length; i++)\n{\n  dropdown[i].addEventListener(\"click\", function()\n  {\n     this.classList.toggle(\"active\");\n     var dropdownContent = this.nextElementSibling;\n     if (dropdownContent.style.display === \"block\")\n     {\n        dropdownContent.style.display = \"none\";\n     } else {\n        dropdownContent.style.display = \"block\";\n     }\n  });\n}\n</script>\n<script type=\"text/javascript\">\n   \nfunction toggleVisibility( id )\n{\n   var e = document.getElementById( id );\n   /* Hide the last one off */\n   if ( window.lastToggledE !== undefined )\n   {\n      window.lastToggledE.style.display = \"none\";\n   }\n\n   /* Show the new one on */\n   if ( e.style.display = \"none\" )\n   {\n      e.style.display = \"block\";\n   }\n\n   /* Set the last one to this one */\n   window.lastToggledE = e;\n}\n</script>\n</BODY>\n</HTML>\n"
  },
  {
    "path": "docs/index.html",
    "content": "<!DOCTYPE html>\n<HTML>\n    <HEAD>\n       <META http-equiv=\"refresh\" content=\"0; url='https://ztalbot2000.github.io/homebridge-cmd4/autoGenerated/CMD4_AccessoryDescriptions.html'\">\n   </HEAD>\n  <BODY>\n     <p>Please follow <a HREF=\"https://ztalbot2000.github.io/homebridge-cmd4/autoGenerated/CMD4_AccessoryDescriptions.html\">this link</a>.</p>\n  </BODY>\n</HTML>\n"
  },
  {
    "path": "index.js",
    "content": "\"use strict\";\n\n//\n//                           Homebridge\n// Flow                     /          \\\n//                         /            \\\n//      api.registerPlatform             api.registerAccessory\n//     forEach Accessories{ }        Any { } before/after Accessories{ }\n//         Cmd4Platform                      Cmd4Accessory\n//         Cmd4Accessory\n//\n//\n//\n//\n//\n//\n//\n//\n//\n//\n\n// The Cmd4 Classes\nconst Cmd4Accessory = require( \"./Cmd4Accessory\" ).Cmd4Accessory;\nconst Cmd4Platform = require( \"./Cmd4Platform\" ).Cmd4Platform;\n\nconst settings = require( \"./cmd4Settings\" );\n\n// Pretty colors\nconst chalk = require( \"chalk\" );\n\n// The Library files that know all.\nvar CHAR_DATA = require( \"./lib/CMD4_CHAR_TYPE_ENUMS\" );\nvar ACC_DATA = require( \"./lib/CMD4_ACC_TYPE_ENUM\" );\nvar DEVICE_DATA = require( \"./lib/CMD4_DEVICE_TYPE_ENUM\" );\n\nmodule.exports =\n{\n   default: function ( api )\n   {\n      // Init the libraries for all to use\n      let CMD4_CHAR_TYPE_ENUMS = CHAR_DATA.init( api.hap.Formats, api.hap.Units, api.hap.Perms );\n      let CMD4_ACC_TYPE_ENUM = ACC_DATA.init( api.hap.Characteristic, api.hap.Formats, api.hap.Units, api.hap.Perms );\n      let CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init(\n         CMD4_ACC_TYPE_ENUM, api.hap.Service, api.hap.Characteristic, api.hap.Categories );\n\n      api.registerAccessory( settings.PLATFORM_NAME, Cmd4Accessory );\n      api.registerPlatform( settings.PLATFORM_NAME, Cmd4Platform );\n\n      setTimeout( checkForUpdates, 1800 );\n\n      // This is not required by homebridge and does not affect it.  I use it for\n      // unit testing.\n      return { CMD4_CHAR_TYPE_ENUMS,\n               CMD4_ACC_TYPE_ENUM,\n               CMD4_DEVICE_TYPE_ENUM,\n               api\n             };\n   },\n   // These would be the uninitialized values,\n   // used for unit testing\n   CHAR_DATA:   CHAR_DATA,  // properties would be { } empty.\n   ACC_DATA:    ACC_DATA,   // properties would be { } empty.\n   DEVICE_DATA: DEVICE_DATA // properties would be { } empty.\n}\n\nfunction checkForUpdates( )\n{\n   // Don't show the updates message in mocha test mode\n   if ( process.argv.includes( \"test/mocha-setup\" ) )\n      return;\n\n   const { getLatestVersion, isVersionNewerThanPackagedVersion }  = require( \"./utils/versionChecker\" );\n   const myPkg = require( \"./package.json\" );\n\n   ( async( ) =>\n   {\n      // Fix for #127, constant crash loops when no internet connection\n      // trying to get latest Cmd4 version.\n      // thx nano9g\n      try\n      {\n         let lv = await getLatestVersion( );\n\n         if ( isVersionNewerThanPackagedVersion( lv ) )\n         {\n            console.log( chalk.green( `[UPDATE AVAILABLE] ` ) + `Version ${lv} of ${myPkg.name} is available. Any release notes can be found here: ` + chalk.underline( `${myPkg.changelog}` ) );\n         }\n\n      }\n      catch( error )\n      {\n         console.log( chalk.yellow( `[UPDATE CHECK FAILED] ` ) + `Could not check for newer versions of ${myPkg.name} due to error ${error.name}: ${error.message}`)\n      }\n   })( );\n}\n"
  },
  {
    "path": "lib/CMD4_ACC_TYPE_ENUM.js",
    "content": "'use strict';\n\n// The sObject.defineProperty is to resolve a lint issue.\n// See utils/indexOfEnumLintTest.js for further information.\nlet indexOfEnum = require( \"../utils/indexOfEnum\" );\nObject.defineProperty( exports, \"indexOfEnum\", { enumerable: true, get: function ( ){ return indexOfEnum.indexOfEnum; } });\n\nfunction stringToBool( str )\n{\n   str += '';\n   str = str.toUpperCase( );\n   if ( str == \"0\" || str == \"FALSE\" ) return false;\n   if ( str == \"1\" || str == \"TRUE\" ) return true;\n\n   return undefined;\n}\nfunction stringToFloat( str )\n{\n   if ( !isNaN( str ) )\n   {\n      let rc = parseFloat( str );\n      if ( ! isNaN( rc ) )\n         return rc;\n   }\n   return undefined;\n}\nfunction stringToInt( str )\n{\n   str += '';\n\n   // Convert it to a Number, no matter what\n   let result = Number( str );\n\n   if ( typeof result == \"number\" )\n      return result;\n\n   return undefined;\n}\nfunction stringToString( str )\n{\n   if ( typeof str == \"string\" )\n      return str;\n   // more or less to pass previous testcases\n   if ( typeof str == \"number\" )\n      return str += '';\n\n   return undefined;\n}\nfunction stringPassThru( str )\n{\n   return str;\n}\nfunction stringToTLV8( str )\n{\n   return str;\n}\n\nclass CustomCharacteristic\n{\n   constructor( api, type, UUID, props )\n   {\n      this.characteristic = { };\n      this.api = api;\n\n      var _a;\n      this.characteristic[ type ] = (_a = class extends this.api.hap.Characteristic\n      {\n         constructor() {\n            super(type, UUID, props);\n            this.value = this.getDefaultValue();\n         }\n      },\n      _a.UUID = UUID,\n      _a);\n   }\n}\n\n// NOTE - DO NOT CHANGE TO LOWER CASE\n//      - This would mean ALL testcases would have to be changed as well.\n//:76,375s/^   \\([A-Z]\\)/   \\l\\1/\nvar CMD4_ACC_TYPE_ENUM =\n{\n   AccessControlLevel:                      0,\n   AccessoryFlags:                          1,\n   AccessoryIdentifier:                     2,\n   Active:                                  3,\n   ActiveIdentifier:                        4,\n   ActivityInterval:                        5,\n   AdministratorOnlyAccess:                 6,\n   AirParticulateDensity:                   7,\n   AirParticulateSize:                      8,\n   AirQuality:                              9,\n   AppMatchingIdentifier:                   10,\n   AudioFeedback:                           11,\n   BatteryLevel:                            12,\n   Brightness:                              13,\n   ButtonEvent:                             14,\n   CCAEnergyDetectThreshold:                15,\n   CCASignalDetectThreshold:                16,\n   CameraOperatingModeIndicator:            17,\n   CarbonDioxideDetected:                   18,\n   CarbonDioxideLevel:                      19,\n   CarbonDioxidePeakLevel:                  20,\n   CarbonMonoxideDetected:                  21,\n   CarbonMonoxideLevel:                     22,\n   CarbonMonoxidePeakLevel:                 23,\n   Category:                                24,\n   CharacteristicValueTransitionControl:    25,\n   ChargingState:                           26,\n   ClosedCaptions:                          27,\n   ColorTemperature:                        28,\n   ConfigureBridgedAccessory:               29,\n   ConfigureBridgedAccessoryStatus:         30,\n   ConfiguredName:                          31,\n   ContactSensorState:                      32,\n   CoolingThresholdTemperature:             33,\n   CurrentAirPurifierState:                 34,\n   CurrentAmbientLightLevel:                35,\n   CurrentDoorState:                        36,\n   CurrentFanState:                         37,\n   CurrentHeaterCoolerState:                38,\n   CurrentHeatingCoolingState:              39,\n   CurrentHorizontalTiltAngle:              40,\n   CurrentHumidifierDehumidifierState:      41,\n   CurrentMediaState:                       42,\n   CurrentPosition:                         43,\n   CurrentRelativeHumidity:                 44,\n   CurrentSlatState:                        45,\n   CurrentTemperature:                      46,\n   CurrentTiltAngle:                        47,\n   CurrentTime:                             48,\n   CurrentTransport:                        49,\n   CurrentVerticalTiltAngle:                50,\n   CurrentVisibilityState:                  51,\n   DataStreamHAPTransport:                  52,\n   DataStreamHAPTransportInterrupt:         53,\n   DayoftheWeek:                            54,\n   DiagonalFieldOfView:                     55,\n   DigitalZoom:                             56,\n   DiscoverBridgedAccessories:              57,\n   DiscoveredBridgedAccessories:            58,\n   DisplayOrder:                            59,\n   EventRetransmissionMaximum:              60,\n   EventSnapshotsActive:                    61,\n   EventTransmissionCounters:               62,\n   FilterChangeIndication:                  63,\n   FilterLifeLevel:                         64,\n   FirmwareRevision:                        65,\n   HardwareRevision:                        66,\n   HeartBeat:                               67,\n   HeatingThresholdTemperature:             68,\n   HoldPosition:                            69,\n   HomeKitCameraActive:                     70,\n   Hue:                                     71,\n   Identifier:                              72,\n   Identify:                                73,\n   ImageMirroring:                          74,\n   ImageRotation:                           75,\n   InUse:                                   76,\n   InputDeviceType:                         77,\n   InputSourceType:                         78,\n   IsConfigured:                            79,\n   LeakDetected:                            80,\n   LinkQuality:                             81,\n   ListPairings:                            82,\n   LockControlPoint:                        83,\n   LockCurrentState:                        84,\n   LockLastKnownAction:                     85,\n   LockManagementAutoSecurityTimeout:       86,\n   LockPhysicalControls:                    87,\n   LockTargetState:                         88,\n   Logs:                                    89,\n   MACRetransmissionMaximum:                90,\n   MACTransmissionCounters:                 91,\n   ManagedNetworkEnable:                    92,\n   ManuallyDisabled:                        93,\n   Manufacturer:                            94,\n   Model:                                   95,\n   MotionDetected:                          96,\n   Mute:                                    97,\n   Name:                                    98,\n   NetworkAccessViolationControl:           99,\n   NetworkClientProfileControl:             100,\n   NetworkClientStatusControl:              101,\n   NightVision:                             102,\n   NitrogenDioxideDensity:                  103,\n   ObstructionDetected:                     104,\n   OccupancyDetected:                       105,\n   On:                                      106,\n   OperatingStateResponse:                  107,\n   OpticalZoom:                             108,\n   OutletInUse:                             109,\n   OzoneDensity:                            110,\n   PM10Density:                             111,\n   PM2_5Density:                            112,\n   PairSetup:                               113,\n   PairVerify:                              114,\n   PairingFeatures:                         115,\n   PairingPairings:                         116,\n   PasswordSetting:                         117,\n   PeriodicSnapshotsActive:                 118,\n   PictureMode:                             119,\n   Ping:                                    120,\n   PositionState:                           121,\n   PowerModeSelection:                      122,\n   ProductData:                             123,\n   ProgramMode:                             124,\n   ProgrammableSwitchEvent:                 125,\n   ProgrammableSwitchOutputState:           126,\n   Reachable:                               127,\n   ReceivedSignalStrengthIndication:        128,\n   ReceiverSensitivity:                     129,\n   RecordingAudioActive:                    130,\n   RelativeHumidityDehumidifierThreshold:   131,\n   RelativeHumidityHumidifierThreshold:     132,\n   RelayControlPoint:                       133,\n   RelayEnabled:                            134,\n   RelayState:                              135,\n   RemainingDuration:                       136,\n   RemoteKey:                               137,\n   ResetFilterIndication:                   138,\n   RotationDirection:                       139,\n   RotationSpeed:                           140,\n   RouterStatus:                            141,\n   Saturation:                              142,\n   SecuritySystemAlarmType:                 143,\n   SecuritySystemCurrentState:              144,\n   SecuritySystemTargetState:               145,\n   SelectedAudioStreamConfiguration:        146,\n   SelectedCameraRecordingConfiguration:    147,\n   SelectedRTPStreamConfiguration:          148,\n   SerialNumber:                            149,\n   ServiceLabelIndex:                       150,\n   ServiceLabelNamespace:                   151,\n   SetDuration:                             152,\n   SetupDataStreamTransport:                153,\n   SetupEndpoints:                          154,\n   SetupTransferTransport:                  155,\n   SignalToNoiseRatio:                      156,\n   SiriInputType:                           157,\n   SlatType:                                158,\n   SleepDiscoveryMode:                      159,\n   SleepInterval:                           160,\n   SmokeDetected:                           161,\n   SoftwareRevision:                        162,\n   StatusActive:                            163,\n   StatusFault:                             164,\n   StatusJammed:                            165,\n   StatusLowBattery:                        166,\n   StatusTampered:                          167,\n   StreamingStatus:                         168,\n   SulphurDioxideDensity:                   169,\n   SupportedAudioRecordingConfiguration:    170,\n   SupportedAudioStreamConfiguration:       171,\n   SupportedCameraRecordingConfiguration:   172,\n   SupportedCharacteristicValueTransitionConfiguration:    173,\n   SupportedDataStreamTransportConfiguration:   174,\n   SupportedDiagnosticsSnapshot:            175,\n   SupportedRTPConfiguration:               176,\n   SupportedRouterConfiguration:            177,\n   SupportedTransferTransportConfiguration: 178,\n   SupportedVideoRecordingConfiguration:    179,\n   SupportedVideoStreamConfiguration:       180,\n   SwingMode:                               181,\n   TargetAirPurifierState:                  182,\n   TargetAirQuality:                        183,\n   TargetControlList:                       184,\n   TargetControlSupportedConfiguration:     185,\n   TargetDoorState:                         186,\n   TargetFanState:                          187,\n   TargetHeaterCoolerState:                 188,\n   TargetHeatingCoolingState:               189,\n   TargetHorizontalTiltAngle:               190,\n   TargetHumidifierDehumidifierState:       191,\n   TargetMediaState:                        192,\n   TargetPosition:                          193,\n   TargetRelativeHumidity:                  194,\n   TargetSlatState:                         195,\n   TargetTemperature:                       196,\n   TargetTiltAngle:                         197,\n   TargetVerticalTiltAngle:                 198,\n   TargetVisibilityState:                   199,\n   TemperatureDisplayUnits:                 200,\n   ThirdPartyCameraActive:                  201,\n   TimeUpdate:                              202,\n   TransmitPower:                           203,\n   MaximumTransmitPower:                    204,\n   TunnelConnectionTimeout:                 205,\n   TunneledAccessoryAdvertising:            206,\n   TunneledAccessoryConnected:              207,\n   TunneledAccessoryStateNumber:            208,\n   VOCDensity:                              209,\n   ValveType:                               210,\n   Version:                                 211,\n   VideoAnalysisActive:                     212,\n   Volume:                                  213,\n   VolumeControlType:                       214,\n   VolumeSelector:                          215,\n   WANConfigurationList:                    216,\n   WANStatusList:                           217,\n   WakeConfiguration:                       218,\n   WaterLevel:                              219,\n   WiFiCapabilities:                        220,\n   WiFiConfigurationControl:                221,\n   WiFiSatelliteStatus:                     222,\n\n   AssetUpdateReadiness:                    223,\n   SupportedAssetTypes:                     224,\n   ConfigurationState:                      225,\n   NFCAccessControlPoint:                   226,\n   NFCAccessSupportedConfiguration:         227,\n   SiriEndpointSessionStatus:               228,\n   ThreadControlPoint:                      229,\n   ThreadNodeCapabilities:                  230,\n   ThreadStatus:                            231,\n   ThreadOpenThreadVersion:                 232,\n\n   // Added Mar 2024\n   AccessCodeControlPoint:                  233,\n   AccessCodeSupportedConfiguration:        234,\n   AirPlayEnable:                           235,\n   CharacteristicValueActiveTransitionCount: 236,\n   CryptoHash:                              237,\n   FirmwareUpdateReadiness:                 238,\n   FirmwareUpdateStatus:                    239,\n   HardwareFinish:                          240,\n   MetricsBufferFullState:                  241,\n   MultifunctionButton:                     242,\n   SelectedDiagnosticsModes:                243,\n   SelectedSleepConfiguration:              244,\n   SiriEnable:                              245,\n   SiriEngineVersion:                       246,\n   SiriLightOnUse:                          247,\n   SiriListening:                           248,\n   SiriTouchToUse:                          249,\n   StagedFirmwareVersion:                   250,\n   SupportedMetrics:                        251,\n   SupportedFirmwareUpdateConfiguration:    252,\n   TapType:                                 253,\n   Token:                                   254,\n\n   EOL:                                     255,\n\n   properties: { },\n\n   accEnumIndexToUC: function( index )\n   {\n      return CMD4_ACC_TYPE_ENUM.properties[ index ].type;\n   },\n   accEnumIndexToLC: function( index )\n   {\n      return CMD4_ACC_TYPE_ENUM.properties[ index ].sche;\n   },\n   indexOfEnum: function( characteristicString )\n   {\n      let accTypeEnumIndex = -1;\n      accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.type === characteristicString );\n      if ( accTypeEnumIndex >= 0 )\n         return accTypeEnumIndex;\n\n      return CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.sche === characteristicString );\n   },\n\n   add: function( api, type, description, props, validValues )\n   {\n      let UUID = api.hap.uuid.generate( type );\n      let characteristic = new CustomCharacteristic( api, type, UUID, props );\n\n      let hapFormats = api.hap.Formats;\n\n      let stringConversionFunction;\n      switch ( props.format )\n      {\n         case hapFormats.BOOL:\n            stringConversionFunction = function ( str ){ return stringToBool( str ); };\n            props.allowedWordCount = 1;\n            break;\n         case hapFormats.INT:\n         case hapFormats.UINT8:\n         case hapFormats.UINT16:\n         case hapFormats.UINT32:\n         case hapFormats.UINT64:\n            stringConversionFunction = function ( str ){ return stringToInt( str ); };\n            props.allowedWordCount = 1;\n            break;\n         case hapFormats.FLOAT:\n            stringConversionFunction = function ( str ){ return stringToFloat( str ); };\n            props.allowedWordCount = 1;\n            break;\n         case hapFormats.STRING:\n            stringConversionFunction = function ( str ){ return stringToString( str ); };\n            props.allowedWordCount = 0;\n            break;\n         case hapFormats.DATA:\n            stringConversionFunction = function ( str ){ return stringPassThru( str ); };\n            props.allowedWordCount = 0;\n            break;\n         case hapFormats.TLV8:\n            stringConversionFunction = function ( str ){ return stringToTLV8( str ); };\n            props.allowedWordCount = 0;\n            break;\n         case hapFormats.DICT:\n            stringConversionFunction = function ( str ){ return stringPassThru( str ); };\n            props.allowedWordCount = 0;\n            break;\n      }\n\n      CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.EOL ] =\n         { \"type\": type,\n           \"characteristic\": characteristic.characteristic[ type ],\n           \"UUID\": UUID,\n           \"description\": description,\n           \"relatedCurrentAccTypeEnumIndex\": null,\n           \"relatedTargetAccTypeEnumIndex\": null,\n           \"stringConversionFunction\": stringConversionFunction,\n           \"props\": props,\n           \"validValues\": validValues\n         };\n      CMD4_ACC_TYPE_ENUM[ type ] = CMD4_ACC_TYPE_ENUM.EOL;\n\n      CMD4_ACC_TYPE_ENUM.EOL ++;\n\n      // The returned characteristic is not good for anything but unit testing.\n      // The one used for services is the above: characteristic.characteristic[ type ]\n      return characteristic;\n   },\n};\n\n// Export both the init function and the uninitialized data for unit testing\nmodule.exports =\n{\n   init: function (Characteristic, hapFormats, hapUnits, hapPerms)\n   {\n\n      // Fill in the properties of all possible characteristics\n      // props was added because calling getCharacteridtic().props.perms adds\n      // the characteristic in by default. This costs some lines, but is advantageous.\n\n      // NOTE - DO NOT CHANGE TYPE TO LOWER CASE.\n      //      - HOW Would you handle MACTransmission, UUID, ...\n      //        If checking char.At(0).toUpperCase ?\n      //        :g/type: \"\\([A-Z]\\)/s//type: \"\\l\\1/g\n      //        :g/sche: \"\\([A-Z]\\)/s//sche: \"\\l\\1/g\n      //        :g/type: \"\\([a-z]\\)/s//type: \"\\u\\1/g\n      CMD4_ACC_TYPE_ENUM.properties =\n      {\n         0:   { type: \"AccessControlLevel\",\n                sche: \"accessControlLevel\",\n                characteristic: Characteristic.AccessControlLevel,\n                deprecated: false,\n                UUID: \"000000E5-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Access Control Level\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         1:   { type: \"AccessoryFlags\",\n                sche: \"accessoryFlags\",\n                characteristic: Characteristic.AccessoryFlags,\n                deprecated: false,\n                UUID: \"000000A6-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Accessory Flags\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         2:   { type: \"AccessoryIdentifier\",   // HomeKitTypes-Bridge\n                sche: \"accessoryIdentifier\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.AccessoryIdentifier,\n                deprecated: false,\n                UUID: \"00000057-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Accessory Identifier String\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         3:   { type: \"Active\",\n                sche: \"active\",\n                characteristic: Characteristic.Active,\n                deprecated: false,\n                UUID: \"000000B0-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is ACTIVE/INACTIVE\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.Active,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.Active,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                   },\n                validValues:   // Checked 04/24/2020\n                   {\"INACTIVE\": Characteristic.Active.INACTIVE,\n                    \"ACTIVE\":   Characteristic.Active.ACTIVE\n                   }\n              },\n         4:   { type: \"ActiveIdentifier\",   // HomeKitTypes-Television\n                sche: \"activeIdentifier\",   // HomeKitTypes-Television\n                characteristic: Characteristic.ActiveIdentifier,\n                deprecated: false,\n                UUID: \"000000E7-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Active Identifier\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         5:   { type: \"ActivityInterval\",   // HomeKit - Checke3d 11-19-2020\n                sche: \"activityInterval\",   // HomeKit - Checke3d 11-19-2020\n                characteristic: Characteristic.ActivityInterval,\n                deprecated: false,\n                UUID: \"0000023B-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Activity Interval\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         6:   { type: \"AdministratorOnlyAccess\",\n                sche: \"administratorOnlyAccess\",\n                characteristic: Characteristic.AdministratorOnlyAccess,\n                deprecated: false,\n                UUID: \"00000001-0000-1000-8000-0026BB765291\",\n                description: \"If the Device has 2cwAdmin Only Access\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         7:   { type: \"AirParticulateDensity\",\n                sche: \"airParticulateDensity\",\n                characteristic: Characteristic.AirParticulateDensity,\n                deprecated: false,\n                UUID: \"00000064-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Air Particulate Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         8:   { type: \"AirParticulateSize\",\n                sche: \"airParticulateSize\",\n                characteristic: Characteristic.AirParticulateSize,\n                deprecated: false,\n                UUID: \"00000065-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Air Particulate Size\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020\n                   {\"_2_5_M\": Characteristic.AirParticulateSize._2_5_M,\n                    \"_10_M\":  Characteristic.AirParticulateSize._10_M\n                   }\n              },\n         9:   { type: \"AirQuality\",\n                sche: \"airQuality\",\n                characteristic: Characteristic.AirQuality,\n                deprecated: false,\n                UUID: \"00000095-0000-1000-8000-0026BB765291\",\n                description: \"The Current Air Quality\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex:\n                   null,\n                   // @deprecated Removed and not used anymore as of homebridge v2\n                   // CMD4_ACC_TYPE_ENUM.TargetAirQuality,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 5,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020\n                   {\"UNKNOWN\":   Characteristic.AirQuality.UNKNOWN,\n                    \"EXCELLENT\": Characteristic.AirQuality.EXCELLENT,\n                              \"GOOD\":      Characteristic.AirQuality.GOOD,\n                              \"FAIR\":      Characteristic.AirQuality.FAIR,\n                              \"INFERIOR\":  Characteristic.AirQuality.INFERIOR,\n                              \"POOR\":      Characteristic.AirQuality.POOR\n                   }\n              },\n         10:  { type: \"AppMatchingIdentifier\",\n                sche: \"appMatchingIdentifier\",\n                characteristic: Characteristic.AppMatchingIdentifier,\n                deprecated: false,\n                UUID: \"000000A4-0000-1000-8000-0026BB765291\",\n                description: \"The Devices App Matching Identifier\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                /* eslint no-unused-vars: [\"error\", {\"args\": \"none\"}] */\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:   // Checked 11/20/2020\n                   {}\n              },\n         11:  { type: \"AudioFeedback\",\n                sche: \"audioFeedback\",\n                characteristic: Characteristic.AudioFeedback,\n                deprecated: false,\n                UUID: \"00000005-0000-1000-8000-0026BB765291\",\n                description: \"If Audio Feedback is Present\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         12:  { type: \"BatteryLevel\",\n                sche: \"batteryLevel\",\n                characteristic: Characteristic.BatteryLevel,\n                deprecated: false,\n                UUID: \"00000068-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Battery Level\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         13:  { type: \"Brightness\",\n                sche: \"brightness\",\n                characteristic: Characteristic.Brightness,\n                deprecated: false,\n                UUID: \"00000008-0000-1000-8000-0026BB765291\",\n                description: \"The Percentage of Existing Brightness\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         14:  { type: \"ButtonEvent\",\n                sche: \"buttonEvent\",\n                characteristic: Characteristic.ButtonEvent,\n                deprecated: false,\n                UUID: \"00000126-0000-1000-8000-0026BB765291\",\n                description: \"The Devices zbutton Event\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         15:  { type: \"CCAEnergyDetectThreshold\",\n                sche: \"ccaEnergyDetectThreshold\",\n                characteristic: Characteristic.CCAEnergyDetectThreshold,\n                deprecated: false,\n                UUID: \"00000246-0000-1000-8000-0026BB765291\",\n                description: \"The Devices CCA Energy Detect Threshold\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         16:  { type: \"CCASignalDetectThreshold\",\n                sche: \"ccaSignalDetectThreshold\",\n                characteristic: Characteristic.CCASignalDetectThreshold,\n                deprecated: false,\n                UUID: \"00000245-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Signal Detect Threshold\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         17:  { type: \"CameraOperatingModeIndicator\",\n                sche: \"cameraOperatingModeIndicator\",\n                characteristic: Characteristic.CameraOperatingModeIndicator,\n                deprecated: false,\n                UUID: \"0000021D-0000-1000-8000-0026BB765291\",\n                description: \"The State of the Camera's Operating Mode Indicator\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE\n                               ]\n                       },\n                validValues:\n                       { \"DISABLE\": 0,\n                         \"ENABLE\":  1\n                       }\n              },\n         18:  { type: \"CarbonDioxideDetected\",\n                sche: \"carbonDioxideDetected\",\n                characteristic: Characteristic.CarbonDioxideDetected,\n                deprecated: false,\n                UUID: \"00000092-0000-1000-8000-0026BB765291\",\n                description: \"If Carbon Dioxide has been Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"CO2_LEVELS_NORMAL\":\n                     Characteristic.CarbonDioxideDetected.CO2_LEVELS_NORMAL,\n                    \"CO2_LEVELS_ABNORMAL\":\n                     Characteristic.CarbonDioxideDetected.CO2_LEVELS_ABNORMAL\n                   }\n              },\n         19:  { type: \"CarbonDioxideLevel\",\n                sche: \"carbonDioxideLevel\",\n                characteristic: Characteristic.CarbonDioxideLevel,\n                deprecated: false,\n                UUID: \"00000093-0000-1000-8000-0026BB765291\",\n                description: \"The Amount of CO2 Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100000,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         20:  { type: \"CarbonDioxidePeakLevel\",\n                sche: \"carbonDioxidePeakLevel\",\n                characteristic: Characteristic.CarbonDioxidePeakLevel,\n                deprecated: false,\n                UUID: \"00000094-0000-1000-8000-0026BB765291\",\n                description: \"The Maximum Amount of CO2 Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100000,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         21:  { type: \"CarbonMonoxideDetected\",\n                sche: \"carbonMonoxideDetected\",\n                characteristic: Characteristic.CarbonMonoxideDetected,\n                deprecated: false,\n                UUID: \"00000069-0000-1000-8000-0026BB765291\",\n                description: \"Indication of CO Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"CO_LEVELS_NORMAL\":\n                     Characteristic.CarbonMonoxideDetected.CO_LEVELS_NORMAL,\n                    \"CO_LEVELS_ABNORMAL\":\n                     Characteristic.CarbonMonoxideDetected.CO_LEVELS_ABNORMAL\n                   }\n              },\n         22:  { type: \"CarbonMonoxideLevel\",\n                sche: \"carbonMonoxideLevel\",\n                characteristic: Characteristic.CarbonMonoxideLevel,\n                deprecated: false,\n                UUID: \"00000090-0000-1000-8000-0026BB765291\",\n                description: \"The Amount of CO Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         23:  { type: \"CarbonMonoxidePeakLevel\",\n                sche: \"carbonMonoxidePeakLevel\",\n                characteristic: Characteristic.CarbonMonoxidePeakLevel,\n                deprecated: false,\n                UUID: \"00000091-0000-1000-8000-0026BB765291\",\n                description: \"The Maximum Amount of CO Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         24:  { type: \"Category\",    // HomeKitTypes-Bridge\n                sche: \"category\",    // HomeKitTypes-Bridge\n                characteristic: Characteristic.Category,\n                deprecated: true,\n                UUID: \"000000A3-0000-1000-8000-0026BB765291\",\n                description: \"A Hint to HomeKitf of which Icon to Use\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        maxValue: 16,\n                        minValue: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         25:  { type: \"CharacteristicValueTransitionControl\",    // HomeKit\n                sche: \"characteristicValueTransitionControl\",    // HomeKit\n                characteristic: Characteristic.CharacteristicValueTransitionControl,\n                deprecated: false,\n                UUID: \"00000143-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Characteristic Value Transition Control\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         26:  { type: \"ChargingState\",\n                sche: \"chargingState\",\n                characteristic: Characteristic.ChargingState,\n                deprecated: false,\n                UUID: \"0000008F-0000-1000-8000-0026BB765291\",\n                description: \"The Current Charging State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n            validValues:   // Checked 04/24/2020. Note: HomeKit Spec has inProgress, Not CHARGING\n                   {\"NOT_CHARGING\": Characteristic.ChargingState.NOT_CHARGING,\n                    \"CHARGING\": Characteristic.ChargingState.CHARGING,\n                    \"NOT_CHARGEABLE\": Characteristic.ChargingState.NOT_CHARGEABLE\n                   }\n              },\n         27:  { type: \"ClosedCaptions\",    // HomeKitTypes-Television\n                sche: \"closedCaptions\",    // HomeKitTypes-Television\n                characteristic: Characteristic.ClosedCaptions,\n                deprecated: false,\n                UUID: \"000000DD-0000-1000-8000-0026BB765291\",\n                description: \"If Closed Captioning is Enabled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"DISABLED\": Characteristic.ClosedCaptions.DISABLED,\n                    \"ENABLED\":  Characteristic.ClosedCaptions.ENABLED\n                   }\n              },\n         28:  { type: \"ColorTemperature\",\n                sche: \"colorTemperature\",\n                characteristic: Characteristic.ColorTemperature,\n                deprecated: false,\n                UUID: \"000000CE-0000-1000-8000-0026BB765291\",\n                description: \"The Colors Current Temperature\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        maxValue: 500,\n                        minValue: 140,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         29:  { type: \"ConfigureBridgedAccessory\",    // HomeKitTypes-Bridge\n                sche: \"configureBridgedAccessory\",    // HomeKitTypes-Bridge\n                characteristic: Characteristic.ConfigureBridgedAccessory,\n                deprecated: true,\n                UUID: \"000000A0-0000-1000-8000-0026BB765291\",\n                description: \"The Configured Bridge Accessory\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         30:  { type: \"ConfigureBridgedAccessoryStatus\",    // HomeKitTypes-Bridge\n                sche: \"configureBridgedAccessoryStatus\",    // HomeKitTypes-Bridge\n                characteristic: Characteristic.ConfigureBridgedAccessoryStatus,\n                deprecated: true,\n                UUID: \"0000009D-0000-1000-8000-0026BB765291\",\n                description: \"The Configured Bridge Accessory Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         31:  { type: \"ConfiguredName\",    // HomeKitTypes-Television\n                sche: \"configuredName\",    // HomeKitTypes-Television\n                characteristic: Characteristic.ConfiguredName,\n                deprecated: false,\n                UUID: \"000000E3-0000-1000-8000-0026BB765291\",\n                description: \"Name of accessory, as displayed in HomeKit\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         32:  { type: \"ContactSensorState\",\n                sche: \"contactSensorState\",\n                characteristic: Characteristic.ContactSensorState,\n                deprecated: false,\n                UUID: \"0000006A-0000-1000-8000-0026BB765291\",\n                description: \"The Current RState of a Contact Sensor\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"CONTACT_DETECTED\": Characteristic.ContactSensorState.CONTACT_DETECTED,\n                    \"CONTACT_NOT_DETECTED\": Characteristic.ContactSensorState.CONTACT_NOT_DETECTED\n                   }\n              },\n         33:  { type: \"CoolingThresholdTemperature\",\n                sche: \"coolingThresholdTemperature\",\n                characteristic: Characteristic.CoolingThresholdTemperature,\n                deprecated: false,\n                UUID: \"0000000D-0000-1000-8000-0026BB765291\",\n                description: \"The Current Cooling Threshold Temperature\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.CELSIUS,\n                        maxValue: 35,\n                        minValue: 10,\n                        minStep: 0.1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         34:  { type: \"CurrentAirPurifierState\",\n                sche: \"currentAirPurifierState\",\n                characteristic: Characteristic.CurrentAirPurifierState,\n                deprecated: false,\n                UUID: \"000000A9-0000-1000-8000-0026BB765291\",\n                description: \"The Current Target Air Purification State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetAirPurifierState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020\n                   {\"INACTIVE\": Characteristic.CurrentAirPurifierState.INACTIVE,\n                    \"IDLE\": Characteristic.CurrentAirPurifierState.IDLE,\n                    \"PURIFYING_AIR\": Characteristic.CurrentAirPurifierState.PURIFYING_AIR\n                   }\n              },\n         35:  { type: \"CurrentAmbientLightLevel\",\n                sche: \"currentAmbientLightLevel\",\n                characteristic: Characteristic.CurrentAmbientLightLevel,\n                deprecated: false,\n                UUID: \"0000006B-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Ambient Light Level\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.LUX,\n                        maxValue: 100000,\n                        minValue: 0.0001,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         36:  { type: \"CurrentDoorState\",\n                sche: \"currentDoorState\",\n                characteristic: Characteristic.CurrentDoorState,\n                deprecated: false,\n                UUID: \"0000000E-0000-1000-8000-0026BB765291\",\n                description: \"The Doors Current Operating State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetDoorState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 4,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OPEN\":    Characteristic.CurrentDoorState.OPEN,\n                    \"CLOSED\":  Characteristic.CurrentDoorState.CLOSED,\n                    \"OPENING\": Characteristic.CurrentDoorState.OPENING,\n                    \"CLOSING\": Characteristic.CurrentDoorState.CLOSING,\n                    \"STOPPED\": Characteristic.CurrentDoorState.STOPPED\n                   }\n              },\n         37:  { type: \"CurrentFanState\",\n                sche: \"currentFanState\",\n                characteristic: Characteristic.CurrentFanState,\n                deprecated: false,\n                UUID: \"000000AF-0000-1000-8000-0026BB765291\",\n                description: \"The Fans Current Operating State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetFanState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"INACTIVE\":    Characteristic.CurrentFanState.INACTIVE,\n                    \"IDLE\":        Characteristic.CurrentFanState.IDLE,\n                    \"BLOWING_AIR\": Characteristic.CurrentFanState.BLOWING_AIR\n                   }\n              },\n         38:  { type: \"CurrentHeaterCoolerState\",\n                sche: \"currentHeaterCoolerState\",\n                characteristic: Characteristic.CurrentHeaterCoolerState,\n                deprecated: false,\n                UUID: \"000000B1-0000-1000-8000-0026BB765291\",\n                description: \"The Heater/Coolers  Current Operating State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetHeaterCoolerState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020\n                   {\"INACTIVE\": Characteristic.CurrentHeaterCoolerState.INACTIVE,\n                    \"IDLE\":     Characteristic.CurrentHeaterCoolerState.IDLE,\n                    \"HEATING\":  Characteristic.CurrentHeaterCoolerState.HEATING,\n                    \"COOLING\":  Characteristic.CurrentHeaterCoolerState.COOLING\n                   }\n              },\n         39:  { type: \"CurrentHeatingCoolingState\",\n                sche: \"currentHeatingCoolingState\",\n                characteristic: Characteristic.CurrentHeatingCoolingState,\n                deprecated: false,\n                UUID: \"0000000F-0000-1000-8000-0026BB765291\",\n                description: \"The Current Mode of the Heating/Cooling Device\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetHeatingCoolingState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked May/07/2021\n                   {\"OFF\":  Characteristic.CurrentHeatingCoolingState.OFF,\n                    \"HEAT\": Characteristic.CurrentHeatingCoolingState.HEAT,\n                    \"COOL\": Characteristic.CurrentHeatingCoolingState.COOL,\n                      // We fix this in checkCharacteristicNeedsFixing\n                    \"AUTO\": Characteristic.TargetHeatingCoolingState.AUTO\n                   }\n              },\n         40:  { type: \"CurrentHorizontalTiltAngle\",\n                sche: \"currentHorizontalTiltAngle\",\n                characteristic: Characteristic.CurrentHorizontalTiltAngle,\n                deprecated: false,\n                UUID: \"0000006C-0000-1000-8000-0026BB765291\",\n                description: \"The Current Horizontal Tilt Angle\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetHorizontalTiltAngle,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 90,\n                        minValue: -90,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         41:  { type: \"CurrentHumidifierDehumidifierState\",\n                sche: \"currentHumidifierDehumidifierState\",\n                characteristic: Characteristic.CurrentHumidifierDehumidifierState,\n                deprecated: false,\n                UUID: \"000000B3-0000-1000-8000-0026BB765291\",\n                description: \"The Humidifier or Dehumidifier Current State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetHumidifierDehumidifierState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"INACTIVE\":      Characteristic.CurrentHumidifierDehumidifierState.INACTIVE,\n                    \"IDLE\":          Characteristic.CurrentHumidifierDehumidifierState.IDLE,\n                    \"HUMIDIFYING\":   Characteristic.CurrentHumidifierDehumidifierState.HUMIDIFYING,\n                    \"DEHUMIDIFYING\": Characteristic.CurrentHumidifierDehumidifierState.DEHUMIDIFYING\n                }\n              },\n         42:  { type: \"CurrentMediaState\",   // HomKitTypes-Television\n                sche: \"currentMediaState\",   // HomKitTypes-Television\n                characteristic: Characteristic.CurrentMediaState,\n                deprecated: false,\n                UUID: \"000000E0-0000-1000-8000-0026BB765291\",\n                description: \"The Medias Current State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetMediaState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 5,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                // HomeKit forgets to define these\n                validValues: {\"PLAY\":        Characteristic.CurrentMediaState.PLAY,\n                              \"PAUSE\":       Characteristic.CurrentMediaState.PAUSE,\n                              \"STOP\":        Characteristic.CurrentMediaState.STOP,\n                              \"LOADING\":     Characteristic.CurrentMediaState.LOADING,\n                              \"INTERRUPTED\": Characteristic.CurrentMediaState.INTERRUPTED}\n              },\n         43:  { type: \"CurrentPosition\",\n                sche: \"currentPosition\",\n                characteristic: Characteristic.CurrentPosition,\n                deprecated: false,\n                UUID: \"0000006D-0000-1000-8000-0026BB765291\",\n                description: \"The devices Current Position\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetPosition,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         44:  { type: \"CurrentRelativeHumidity\",\n                sche: \"currentRelativeHumidity\",\n                characteristic: Characteristic.CurrentRelativeHumidity,\n                deprecated: false,\n                UUID: \"00000010-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Current Relative Humidity\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetRelativeHumidity,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         45:  { type: \"CurrentSlatState\",\n                sche: \"currentSlatState\",\n                characteristic: Characteristic.CurrentSlatState,\n                deprecated: false,\n                UUID: \"000000AA-0000-1000-8000-0026BB765291\",\n                description: \"The Slats Current State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex:\n                   // @deprecated Removed and not used anymore as of homebridge v2\n                   null,\n                   // CMD4_ACC_TYPE_ENUM.TargetSlatState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020  Note HomeKit Spec has \"Stationary\" not \"Jammed\"\n                   {\"FIXED\":    Characteristic.CurrentSlatState.FIXED,\n                    \"JAMMED\":   Characteristic.CurrentSlatState.JAMMED,\n                    \"SWINGING\": Characteristic.CurrentSlatState.SWINGING\n                   }\n              },\n         46:  { type: \"CurrentTemperature\",\n                sche: \"currentTemperature\",\n                characteristic: Characteristic.CurrentTemperature,\n                deprecated: false,\n                UUID: \"00000011-0000-1000-8000-0026BB765291\",\n                description: \"The Current Measured Temperature\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetTemperature,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                // Checked May 19, 2021\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.CELSIUS,\n                        maxValue: 100,\n                        minValue: -270,\n                        minStep: 0.1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         47:  { type: \"CurrentTiltAngle\",\n                sche: \"currentTiltAngle\",\n                characteristic: Characteristic.CurrentTiltAngle,\n                deprecated: false,\n                UUID: \"000000C1-0000-1000-8000-0026BB765291\",\n                description: \"The Current Measured Tilt Angle\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetTiltAngle,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 90,\n                        minValue: -90,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         48:  { type: \"CurrentTime\",   // HomeKitTypes-Bridge\n                sche: \"currentTime\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.CurrentTime,\n                deprecated: true,\n                UUID: \"0000009B-0000-1000-8000-0026BB765291\",\n                description: \"What Time it is Now\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         49:  { type: \"CurrentTransport\",   // HomeKit.d.ts\n                sche: \"currentTransport\",   // HomeKit.d.ts\n                characteristic: Characteristic.CurrentTransport,\n                deprecated: false,\n                UUID: \"0000022B-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Current Transport\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         50:  { type: \"CurrentVerticalTiltAngle\",\n                sche: \"currentVerticalTiltAngle\",\n                characteristic: Characteristic.CurrentVerticalTiltAngle,\n                deprecated: false,\n                UUID: \"0000006E-0000-1000-8000-0026BB765291\",\n                description: \"TheMeasured Current Vertical Tilt Angle\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetVerticalTiltAngle,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 90,\n                        minValue: -90,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         51:  { type: \"CurrentVisibilityState\",    // HomeKitTypes-Television\n                sche: \"currentVisibilityState\",    // HomeKitTypes-Television\n                characteristic: Characteristic.CurrentVisibilityState,\n                deprecated: false,\n                UUID: \"00000135-0000-1000-8000-0026BB765291\",\n                description: \"Is a Device Currently Being Shown or Hidden\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.TargetVisibilityState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                            },\n                validValues:\n                   {\"SHOWN\":    Characteristic.CurrentVisibilityState.SHOWN,\n                    \"HIDDEN\":   Characteristic.CurrentVisibilityState.HIDDEN\n                   }\n              },\n         52:  { type: \"DataStreamHAPTransport\",   // HomeKit.d.ts\n                sche: \"dataStreamHAPTransport\",   // HomeKit.d.ts\n                characteristic: Characteristic.DataStreamHAPTransport,\n                deprecated: false,\n                UUID: \"00000138-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Data Stream Transport\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         53:  { type: \"DataStreamHAPTransportInterrupt\",   // HomeKit.d.ts\n                sche: \"dataStreamHAPTransportInterrupt\",   // HomeKit.d.ts\n                characteristic: Characteristic.DataStreamHAPTransportInterrupt,\n                deprecated: false,\n                UUID: \"00000139-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Data Stream Transport Interrupt\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         54:  { type: \"DayoftheWeek\",    // HomeKitTypes-Bridge\n                sche: \"dayoftheWeek\",    // HomeKitTypes-Bridge\n                characteristic: Characteristic.DayoftheWeek,\n                deprecated: true,\n                UUID: \"00000098-0000-1000-8000-0026BB765291\",\n                description: \"The Current Numerical Day of the Week\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 7,\n                        minValue: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         55:  { type: \"DiagonalFieldOfView\",   // HomeKit.d.ts\n                sche: \"diagonalFieldOfView\",   // HomeKit.d.ts\n                characteristic: Characteristic.DiagonalFieldOfView,\n                deprecated: false,\n                UUID: \"00000224-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Diagonal Field of View\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 360,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         56:  { type: \"DigitalZoom\",\n                sche: \"digitalZoom\",\n                characteristic: Characteristic.DigitalZoom,\n                deprecated: false,\n                UUID: \"0000011D-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Digital Zoom\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        minStep: 0.1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         57:  { type: \"DiscoverBridgedAccessories\",   // HomKitTypes-Bridge\n                sche: \"discoverBridgedAccessories\",   // HomKitTypes-Bridge\n                characteristic: Characteristic.DiscoverBridgedAccessories,\n                deprecated: true,\n                UUID: \"0000009E-0000-1000-8000-0026BB765291\",\n                description: \"The Discovered Bridge Accessories\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:{}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         58:  { type: \"DiscoveredBridgedAccessories\",   // HomKitTypes-Bridge\n                sche: \"discoveredBridgedAccessories\",   // HomKitTypes-Bridge\n                characteristic: Characteristic.DiscoveredBridgedAccessories,\n                deprecated: true,\n                UUID: \"0000009F-0000-1000-8000-0026BB765291\",\n                description: \"The Discovered Bridged Accessories\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         59:  { type: \"DisplayOrder\",   // HomKitTypes-Television\n                sche: \"displayOrder\",   // HomKitTypes-Television\n                characteristic: Characteristic.DisplayOrder,\n                deprecated: false,\n                UUID: \"00000136-0000-1000-8000-0026BB765291\",\n                description: \"The Display Order\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         60:  { type: \"EventRetransmissionMaximum\",   // HomeKit.d.ts\n                sche: \"eventRetransmissionMaximum\",   // HomeKit.d.ts\n                characteristic: Characteristic.EventRetransmissionMaximum,\n                deprecated: false,\n                UUID: \"0000023D-0000-1000-8000-0026BB765291\",\n                description: \"The Event Retransmission Maximum Amount\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         61:  { type: \"EventSnapshotsActive\",   // HomeKit.d.ts\n                sche: \"eventSnapshotsActive\",   // HomeKit.d.ts\n                characteristic: Characteristic.EventSnapshotsActive,\n                deprecated: false,\n                UUID: \"00000223-0000-1000-8000-0026BB765291\",\n                description: \"Is the Event Snapshot Enabled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"DISABLE\":    Characteristic.EventSnapshotsActive.DISABLE,\n                    \"ENABLE\":     Characteristic.EventSnapshotsActive.ENABLE,\n                   }\n              },\n         62:  { type: \"EventTransmissionCounters\",   // HomeKit.d.ts\n                sche: \"eventTransmissionCounters\",   // HomeKit.d.ts\n                characteristic: Characteristic.EventTransmissionCounters,\n                deprecated: false,\n                UUID: \"0000023E-0000-1000-8000-0026BB765291\",\n                description: \"The Event Transmission Counters\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         63:  { type: \"FilterChangeIndication\",\n                sche: \"filterChangeIndication\",\n                characteristic: Characteristic.FilterChangeIndication,\n                deprecated: false,\n                UUID: \"000000AC-0000-1000-8000-0026BB765291\",\n                description: \"An Filters Current Quality\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020.  HomeKit Spec has these as \"notNeeded\" and \"needed\"\n                   {\"FILTER_OK\": Characteristic.FilterChangeIndication.FILTER_OK,\n                    \"CHANGE_FILTER\": Characteristic.FilterChangeIndication.CHANGE_FILTER\n                   }\n              },\n         64:  { type: \"FilterLifeLevel\",\n                sche: \"filterLifeLevel\",\n                characteristic: Characteristic.FilterLifeLevel,\n                deprecated: false,\n                UUID: \"000000AB-0000-1000-8000-0026BB765291\",\n                description: \"An Measurement of Filters Current Quality\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         65:  { type: \"FirmwareRevision\",\n                sche: \"firmwareRevision\",\n                characteristic: Characteristic.FirmwareRevision,\n                deprecated: false,\n                UUID: \"00000052-0000-1000-8000-0026BB765291\",\n                description: \"The Firmwares Revision String\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         66:  { type: \"HardwareRevision\",\n                sche: \"hardwareRevision\",\n                characteristic: Characteristic.HardwareRevision,\n                deprecated: false,\n                UUID: \"00000053-0000-1000-8000-0026BB765291\",\n                description: \"The Hardwares Revision String\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         67:  { type: \"HeartBeat\",\n                sche: \"heartBeat\",\n                characteristic: Characteristic.HeartBeat,\n                deprecated: false,\n                UUID: \"0000024A-0000-1000-8000-0026BB765291\",\n                description: \"The Current Heart Rate\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         68:  { type: \"HeatingThresholdTemperature\",\n                sche: \"heatingThresholdTemperature\",\n                characteristic: Characteristic.HeatingThresholdTemperature,\n                deprecated: false,\n                UUID: \"00000012-0000-1000-8000-0026BB765291\",\n                description: \"The Heating Threshold Temperature\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.CELSIUS,\n                        maxValue: 25,\n                        minValue: 0,\n                        minStep: 0.1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         69:  { type: \"HoldPosition\",\n                sche: \"holdPosition\",\n                characteristic: Characteristic.HoldPosition,\n                deprecated: false,\n                UUID: \"0000006F-0000-1000-8000-0026BB765291\",\n                description: \"If Position Should Be Held\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         70:  { type: \"HomeKitCameraActive\",\n                sche: \"homeKitCameraActive\",\n                characteristic: Characteristic.HomeKitCameraActive,\n                deprecated: false,\n                UUID: \"0000021B-0000-1000-8000-0026BB765291\",\n                description: \"Is the HomeKit Camera ON/OFF\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   { \"OFF\": 0,\n                     \"ON\":  1\n                   }\n              },\n         71:  { type: \"Hue\",\n                sche: \"hue\",\n                characteristic: Characteristic.Hue,\n                deprecated: false,\n                UUID: \"00000013-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Hue\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 360,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         72:  { type: \"Identifier\",   // HomeKitTypes-Television\n                sche: \"identifier\",   // HomeKitTypes-Television\n                characteristic: Characteristic.Identifier,\n                deprecated: false,\n                UUID: \"000000E6-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Identifier\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         73:  { type: \"Identify\",\n                sche: \"identify\",\n                characteristic: Characteristic.Identify,\n                deprecated: false,\n                UUID: \"00000014-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Identify Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         74:  { type: \"ImageMirroring\",\n                sche: \"imageMirroring\",\n                characteristic: Characteristic.ImageMirroring,\n                deprecated: false,\n                UUID: \"0000011F-0000-1000-8000-0026BB765291\",\n                description: \"Is Image Being Mirrored\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         75:  { type: \"ImageRotation\",\n                sche: \"imageRotation\",\n                characteristic: Characteristic.ImageRotation,\n                deprecated: false,\n                UUID: \"0000011E-0000-1000-8000-0026BB765291\",\n                description: \"The Images Degree of Rotation \",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 360,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         76:  { type: \"InUse\",\n                sche: \"inUse\",\n                characteristic: Characteristic.InUse,\n                deprecated: false,\n                UUID: \"000000D2-0000-1000-8000-0026BB765291\",\n                description: \"Is the Device In Use\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NOT_IN_USE\": Characteristic.InUse.NOT_IN_USE,\n                    \"IN_USE\":     Characteristic.InUse.IN_USE\n                   }\n              },\n         77:  { type: \"InputDeviceType\",   // HomeKitTypes-Television\n                sche: \"inputDeviceType\",   // HomeKitTypes-Television\n                characteristic: Characteristic.InputDeviceType,\n                deprecated: false,\n                UUID: \"000000DC-0000-1000-8000-0026BB765291\",\n                description: \"The Input Devices Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 6,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OTHER\":        Characteristic.InputDeviceType.OTHER,\n                    \"TV\":           Characteristic.InputDeviceType.TV,\n                    \"RECORDING\":    Characteristic.InputDeviceType.RECORDING,\n                    \"TUNER\":        Characteristic.InputDeviceType.TUNER,\n                    \"PLAYBACK\":     Characteristic.InputDeviceType.PLAYBACK,\n                    \"AUDIO_SYSTEM\": Characteristic.InputDeviceType.AUDIO_SYSTEM,\n                    \"UNKNOWN_6\":    Characteristic.InputDeviceType.UNKNOWN_6\n                   }\n              },\n         78:  { type: \"InputSourceType\",   // HomeKitTypes-Television\n                sche: \"inputSourceType\",   // HomeKitTypes-Television\n                characteristic: Characteristic.InputSourceType,\n                deprecated: false,\n                UUID: \"000000DB-0000-1000-8000-0026BB765291\",\n                description: \"The Input Devices Source Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 10,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OTHER\":           Characteristic.InputSourceType.OTHER,\n                    \"HOME_SCREEN\":     Characteristic.InputSourceType.HOME_SCREEN,\n                    \"TUNER\":           Characteristic.InputSourceType.TUNER,\n                    \"HDMI\":            Characteristic.InputSourceType.HDMI,\n                    \"COMPOSITE_VIDEO\": Characteristic.InputSourceType.COMPOSITE_VIDEO,\n                    \"S_VIDEO\":         Characteristic.InputSourceType.S_VIDEO,\n                    \"COMPONENT_VIDEO\": Characteristic.InputSourceType.COMPONENT_VIDEO,\n                    \"DVI\":             Characteristic.InputSourceType.DVI,\n                    \"AIRPLAY\":         Characteristic.InputSourceType.AIRPLAY,\n                    \"USB\":             Characteristic.InputSourceType.USB,\n                    \"APPLICATION\":     Characteristic.InputSourceType.APPLICATION\n                   }\n              },\n         79:  { type: \"IsConfigured\",\n                sche: \"isConfigured\",\n                characteristic: Characteristic.IsConfigured,\n                deprecated: false,\n                UUID: \"000000D6-0000-1000-8000-0026BB765291\",\n                description: \"Is the device Configured\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020\n                   {\"NOT_CONFIGURED\": Characteristic.IsConfigured.NOT_CONFIGURED,\n                    \"CONFIGURED\":     Characteristic.IsConfigured.CONFIGURED\n                    }\n              },\n         80:  { type: \"LeakDetected\",\n                sche: \"leakDetected\",\n                characteristic: Characteristic.LeakDetected,\n                deprecated: false,\n                UUID: \"00000070-0000-1000-8000-0026BB765291\",\n                description: \"Is There a Leak Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"LEAK_NOT_DETECTED\": Characteristic.LeakDetected.LEAK_NOT_DETECTED,\n                    \"LEAK_DETECTED\":     Characteristic.LeakDetected.LEAK_DETECTED\n                   }\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         81:  { type: \"LinkQuality\",   // HomeKitTypes-Bridge\n                sche: \"linkQuality\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.LinkQuality,\n                deprecated: true,\n                UUID: \"0000009C-0000-1000-8000-0026BB765291\",\n                description: \"The Links Quality\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 4,\n                        minValue: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         82:  { type: \"ListPairings\",   // HomeKitTypes-Bridge\n                sche: \"listPairings\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.ListPairings,\n                deprecated: false,\n                UUID: \"00000050-0000-1000-8000-0026BB765291\",\n                description: \"The Links Quality\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         83:  { type: \"LockControlPoint\",\n                sche: \"lockControlPoint\",\n                characteristic: Characteristic.LockControlPoint,\n                deprecated: false,\n                UUID: \"00000019-0000-1000-8000-0026BB765291\",\n                description: \"The Control Point of the Lock\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                   perms: [hapPerms.PAIRED_WRITE\n                          ]\n                       },\n                validValues: {}\n              },\n         84:  { type: \"LockCurrentState\",\n                sche: \"lockCurrentState\",\n                characteristic: Characteristic.LockCurrentState,\n                deprecated: false,\n                UUID: \"0000001D-0000-1000-8000-0026BB765291\",\n                description: \"The Locks Current State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.LockTargetState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"UNSECURED\": Characteristic.LockCurrentState.UNSECURED,\n                    \"SECURED\":   Characteristic.LockCurrentState.SECURED,\n                    \"JAMMED\":    Characteristic.LockCurrentState.JAMMED,\n                    \"UNKNOWN\":   Characteristic.LockCurrentState.UNKNOWN\n                   }\n              },\n         85:  { type: \"LockLastKnownAction\",\n                sche: \"lockLastKnownAction\",\n                characteristic: Characteristic.LockLastKnownAction,\n                deprecated: false,\n                UUID: \"0000001C-0000-1000-8000-0026BB765291\",\n                description: \"The Locks Last known Action\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 10,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"SECURED_PHYSICALLY_INTERIOR\":\n                     Characteristic.LockLastKnownAction.SECURED_PHYSICALLY_INTERIOR,\n                    \"UNSECURED_PHYSICALLY_INTERIOR\":\n                     Characteristic.LockLastKnownAction.UNSECURED_PHYSICALLY_INTERIOR,\n                    \"SECURED_PHYSICALLY_EXTERIOR\":\n                     Characteristic.LockLastKnownAction.SECURED_PHYSICALLY_EXTERIOR,\n                    \"UNSECURED_PHYSICALLY_EXTERIOR\":\n                     Characteristic.LockLastKnownAction.UNSECURED_PHYSICALLY_EXTERIOR,\n                    \"SECURED_BY_KEYPAD\":\n                     Characteristic.LockLastKnownAction.SECURED_BY_KEYPAD,\n                    \"UNSECURED_BY_KEYPAD\":\n                     Characteristic.LockLastKnownAction.UNSECURED_BY_KEYPAD,\n                    \"SECURED_REMOTELY\":\n                     Characteristic.LockLastKnownAction.SECURED_REMOTELY,\n                    \"UNSECURED_REMOTELY\":\n                     Characteristic.LockLastKnownAction.UNSECURED_REMOTELY,\n                    \"SECURED_BY_AUTO_SECURE_TIMEOUT\":\n                     Characteristic.LockLastKnownAction.SECURED_BY_AUTO_SECURE_TIMEOUT,\n                    \"SECURED_PHYSICALLY\":\n                     Characteristic.LockLastKnownAction.SECURED_PHYSICALLY,\n                    \"UNSECURED_PHYSICALLY\":\n                     Characteristic.LockLastKnownAction.UNSECURED_PHYSICALLY\n                   }\n              },\n         86:  { type: \"LockManagementAutoSecurityTimeout\",\n                sche: \"lockManagementAutoSecurityTimeout\",\n                characteristic: Characteristic.LockManagementAutoSecurityTimeout,\n                deprecated: false,\n                UUID: \"0000001A-0000-1000-8000-0026BB765291\",\n                description: \"The Locks Security Timeout Value\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        unit: hapUnits.SECONDS,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         87:  { type: \"LockPhysicalControls\",\n                sche: \"lockPhysicalControls\",\n                characteristic: Characteristic.LockPhysicalControls,\n                deprecated: false,\n                UUID: \"000000A7-0000-1000-8000-0026BB765291\",\n                description: \"Is the Lock Physically Enabled/Disabled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"CONTROL_LOCK_DISABLED\": Characteristic.LockPhysicalControls.CONTROL_LOCK_DISABLED,\n                    \"CONTROL_LOCK_ENABLED\":  Characteristic.LockPhysicalControls.CONTROL_LOCK_ENABLED\n                   }\n              },\n         88:  { type: \"LockTargetState\",\n                sche: \"lockTargetState\",\n                characteristic: Characteristic.LockTargetState,\n                deprecated: false,\n                UUID: \"0000001E-0000-1000-8000-0026BB765291\",\n                description: \"The Locks Requested State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.LockCurrentState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"UNSECURED\": Characteristic.LockTargetState.UNSECURED,\n                    \"SECURED\":   Characteristic.LockTargetState.SECURED\n                   }\n              },\n         89:  { type: \"Logs\",\n                sche: \"logs\",\n                characteristic: Characteristic.Logs,\n                deprecated: false,\n                UUID: \"0000001F-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Logs\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         90:  { type: \"MACRetransmissionMaximum\",  // HomekitTypes.d.ts\n                sche: \"macRetransmissionMaximum\",  // HomekitTypes.d.ts\n                characteristic: Characteristic.MACRetransmissionMaximum,\n                deprecated: false,\n                UUID: \"00000247-0000-1000-8000-0026BB765291\",\n                description: \"The Devices MAC Retransmission Maximum Amount\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         91:  { type: \"MACTransmissionCounters\",  // HomekitTypes.d.ts\n                sche: \"macTransmissionCounters\",  // HomekitTypes.d.ts\n                characteristic: Characteristic.MACTransmissionCounters,\n                deprecated: false,\n                UUID: \"00000248-0000-1000-8000-0026BB765291\",\n                description: \"The Devices MAC Transmission Counters\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringPassThru( str ); },\n                props: {format: hapFormats.DATA,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         92:  { type: \"ManagedNetworkEnable\",   // HomeKit\n                sche: \"managedNetworkEnable\",   // HomeKit\n                characteristic: Characteristic.ManagedNetworkEnable,\n                deprecated: false,\n                UUID: \"00000215-0000-1000-8000-0026BB765291\",\n                description: \"The Networks Current State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE\n                               ]\n                       },\n                validValues:\n                       { \"DISABLED\": Characteristic.ManagedNetworkEnable.DISABLED,\n                         \"ENABLED\":  Characteristic.ManagedNetworkEnable.ENABLED,\n                         \"UNKNOWN\":  2\n                       }\n              },\n         93:  { type: \"ManuallyDisabled\",\n                sche: \"manuallyDisabled\",\n                characteristic: Characteristic.ManuallyDisabled,\n                deprecated: false,\n                UUID: \"00000227-0000-1000-8000-0026BB765291\",\n                description: \"Is the Device Manually Enabled/Disabled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                       { \"ENABLED\":  Characteristic.ManuallyDisabled.ENABLED,\n                         \"DISABLED\": Characteristic.ManuallyDisabled.DISABLED\n                       }\n              },\n         94:  { type: \"Manufacturer\",\n                sche: \"manufacturer\",\n                characteristic: Characteristic.Manufacturer,\n                deprecated: false,\n                UUID: \"00000020-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Manufacturer\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         95:  { type: \"Model\",\n                sche: \"model\",\n                characteristic: Characteristic.Model,\n                deprecated: false,\n                UUID: \"00000021-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Model\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         96:  { type: \"MotionDetected\",\n                sche: \"motionDetected\",\n                characteristic: Characteristic.MotionDetected,\n                deprecated: false,\n                UUID: \"00000022-0000-1000-8000-0026BB765291\",\n                description: \"Is Motion Being Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         97:  { type: \"Mute\",\n                sche: \"mute\",\n                characteristic: Characteristic.Mute,\n                deprecated: false,\n                UUID: \"0000011A-0000-1000-8000-0026BB765291\",\n                description: \"Is the Device Currently Muted\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         98:  { type: \"Name\",\n                sche: \"name\",\n                characteristic: Characteristic.Name,\n                deprecated: false,\n                UUID: \"00000023-0000-1000-8000-0026BB765291\",\n                description: \"Name of accessory, as displayed in HomeKit\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         99:  { type: \"NetworkAccessViolationControl\",  // HomeKitTypes.d.ts\n                sche: \"networkAccessViolationControl\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.NetworkAccessViolationControl,\n                deprecated: false,\n                UUID: \"0000021F-0000-1000-8000-0026BB765291\",\n                description: \"The Network AccessViolation Control\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                          ]\n                       },\n                validValues: {}\n              },\n        100:  { type: \"NetworkClientProfileControl\",  // HomeKitTypes.d.ts\n                sche: \"networkClientProfileControl\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.NetworkClientProfileControl,\n                deprecated: false,\n                UUID: \"0000020C-0000-1000-8000-0026BB765291\",\n                description: \"The Network Client Profile Control\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         101: { type: \"NetworkClientStatusControl\",  // HomeKitTypes.d.ts\n                sche: \"networkClientStatusControl\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.NetworkClientStatusControl,\n                deprecated: false,\n                UUID: \"0000020D-0000-1000-8000-0026BB765291\",\n                description: \"The Network Client Status Control\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         102: { type: \"NightVision\",\n                sche: \"nightVision\",\n                characteristic: Characteristic.NightVision,\n                deprecated: false,\n                UUID: \"0000011B-0000-1000-8000-0026BB765291\",\n                description: \"Is Night Vision Available\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         103: { type: \"NitrogenDioxideDensity\",\n                sche: \"nitrogenDioxideDensity\",\n                characteristic: Characteristic.NitrogenDioxideDensity,\n                deprecated: false,\n                UUID: \"000000C4-0000-1000-8000-0026BB765291\",\n                description: \"The Measured NO2 Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         104: { type: \"ObstructionDetected\",\n                sche: \"obstructionDetected\",\n                characteristic: Characteristic.ObstructionDetected,\n                deprecated: false,\n                UUID: \"00000024-0000-1000-8000-0026BB765291\",\n                description: \"Is Obstruction Currently Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         105: { type: \"OccupancyDetected\",\n                sche: \"occupancyDetected\",\n                characteristic: Characteristic.OccupancyDetected,\n                deprecated: false,\n                UUID: \"00000071-0000-1000-8000-0026BB765291\",\n                description: \"Is Occupancy Currently Detected\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OCCUPANCY_NOT_DETECTED\":\n                       Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED,\n                    \"OCCUPANCY_DETECTED\":\n                        Characteristic.OccupancyDetected.OCCUPANCY_DETECTED\n                   }\n              },\n         106: { type: \"On\",\n                sche: \"on\",\n                characteristic: Characteristic.On,\n                deprecated: false,\n                UUID: \"00000025-0000-1000-8000-0026BB765291\",\n                description: \"Is the Device On\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         107: { type: \"OperatingStateResponse\",  // HomeKitTypes.d.ts\n                sche: \"operatingStateResponse\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.OperatingStateResponse,\n                deprecated: false,\n                UUID: \"00000232-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Operating State Response\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                          ]\n                       },\n                validValues: {}\n              },\n         108: { type: \"OpticalZoom\",\n                sche: \"opticalZoom\",\n                characteristic: Characteristic.OpticalZoom,\n                deprecated: false,\n                UUID: \"0000011C-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Optical Zoom Factor\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        minStep: .1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         109: { type: \"OutletInUse\",\n                sche: \"outletInUse\",\n                characteristic: Characteristic.OutletInUse,\n                deprecated: false,\n                UUID: \"00000026-0000-1000-8000-0026BB765291\",\n                description: \"Is the Outlet in Use\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         110: { type: \"OzoneDensity\",\n                sche: \"ozoneDensity\",\n                characteristic: Characteristic.OzoneDensity,\n                deprecated: false,\n                UUID: \"000000C3-0000-1000-8000-0026BB765291\",\n                description: \"The Ozones Current Measured Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         111: { type: \"PM10Density\",\n                sche: \"pm10Density\",\n                characteristic: Characteristic.PM10Density,\n                deprecated: false,\n                UUID: \"000000C7-0000-1000-8000-0026BB765291\",\n                description: \"The PM1O Current Measured Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         112: { type: \"PM2_5Density\",\n                sche: \"pm2_5Density\",\n                characteristic: Characteristic.PM2_5Density,\n                deprecated: false,\n                UUID: \"000000C6-0000-1000-8000-0026BB765291\",\n                description: \"The PM2_5 Current Measured Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         113: { type: \"PairSetup\",\n                sche: \"pairSetup\",\n                characteristic: Characteristic.PairSetup,\n                deprecated: false,\n                UUID: \"0000004C-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Pair Setup\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         114: { type: \"PairVerify\",\n                sche: \"pairVerify\",\n                characteristic: Characteristic.PairVerify,\n                deprecated: false,\n                UUID: \"0000004E-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Pair Verify\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         115: { type: \"PairingFeatures\",\n                sche: \"pairingFeatures\",\n                characteristic: Characteristic.PairingFeatures,\n                deprecated: false,\n                UUID: \"0000004F-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Pairing Features\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         116: { type: \"PairingPairings\",\n                sche: \"pairingPairings\",\n                characteristic: Characteristic.PairingPairings,\n                deprecated: false,\n                UUID: \"00000050-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Pairing Pairings\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         117: { type: \"PasswordSetting\",  // HomeKitTypes.d.ts\n                sche: \"passwordSetting\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.PasswordSetting,\n                deprecated: false,\n                UUID: \"000000E4-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Password Setting\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         118: { type: \"PeriodicSnapshotsActive\",  // HomeKitTypes.d.ts\n                sche: \"periodicSnapshotsActive\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.PeriodicSnapshotsActive,\n                deprecated: false,\n                UUID: \"00000225-0000-1000-8000-0026BB765291\",\n                description: \"Is the Periodic Snapshot Enabled/Disabled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"DISABLE\": Characteristic.PeriodicSnapshotsActive.DISABLE,          // 0\n                    \"ENABLE\":  Characteristic.PeriodicSnapshotsActive.ENABLE            // 1\n                   }\n              },\n         119: { type: \"PictureMode\",   // HomeKitTypes-Television\n                sche: \"pictureMode\",   // HomeKitTypes-Television\n                characteristic: Characteristic.PictureMode,\n                deprecated: false,\n                UUID: \"000000E2-0000-1000-8000-0026BB765291\",\n                description: \"The Current Picture Mode\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 13,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OTHER\":           Characteristic.PictureMode.OTHER,\n                    \"STANDARD\":        Characteristic.PictureMode.STANDARD,\n                    \"CALIBRATED\":      Characteristic.PictureMode.CALIBRATED,\n                    \"CALIBRATED_DARK\": Characteristic.PictureMode.CALIBRATED_DARK,\n                    \"VIVID\":           Characteristic.PictureMode.VIVID,\n                    \"GAME\":            Characteristic.PictureMode.GAME,\n                    \"COMPUTER\":        Characteristic.PictureMode.COMPUTER,\n                    \"CUSTOM\":          Characteristic.PictureMode.CUSTOM,\n                    \"UNKNOWN8\":        8,\n                    \"UNKNOWN9\":        9,\n                    \"UNKNOWN10\":       10,\n                    \"UNKNOWN11\":       11,\n                    \"UNKNOWN12\":       12,\n                    \"UNKNOWN13\":       13\n                   }\n              },\n         120: { type: \"Ping\",  // HomeKitTypes.d.ts\n                sche: \"ping\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.Ping,\n                deprecated: false,\n                UUID: \"0000023C-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Ping Characteristic\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringPassThru( str ); },\n                props: {format: hapFormats.DATA,\n                        allowedWordCount: 0,\n                         perms: [hapPerms.PAIRED_READ\n                                ]\n                       },\n                validValues: {}\n              },\n         121: { type: \"PositionState\",\n                sche: \"positionState\",\n                characteristic: Characteristic.PositionState,\n                deprecated: false,\n                UUID: \"00000072-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Position State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"DECREASING\": Characteristic.PositionState.DECREASING,\n                    \"INCREASING\": Characteristic.PositionState.INCREASING,\n                    \"STOPPED\":    Characteristic.PositionState.STOPPED\n                   }\n              },\n         122: { type: \"PowerModeSelection\",  // HomeKitTypes-Television\n                sche: \"powerModeSelection\",  // HomeKitTypes-Television\n                characteristic: Characteristic.PowerModeSelection,\n                deprecated: false,\n                UUID: \"000000DF-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Power Mode Selection\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"SHOW\": Characteristic.PowerModeSelection.SHOW,\n                    \"HIDE\": Characteristic.PowerModeSelection.HIDE\n                   }\n              },\n         123: { type: \"ProductData\",  // HomeKitTypes.d.ts\n                sche: \"productData\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.ProductData,\n                deprecated: false,\n                UUID: \"00000220-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Product Data\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringPassThru( str ); },\n                props: {format: hapFormats.DATA,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         124: { type: \"ProgramMode\",\n                sche: \"programMode\",\n                characteristic: Characteristic.ProgramMode,\n                deprecated: false,\n                UUID: \"000000D1-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Program Mode\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NO_PROGRAM_SCHEDULED\":\n                      Characteristic.ProgramMode.NO_PROGRAM_SCHEDULED,\n                    \"PROGRAM_SCHEDULED\":\n                       Characteristic.ProgramMode.PROGRAM_SCHEDULED,\n                    \"PROGRAM_SCHEDULED_MANUAL_MODE\":\n                        Characteristic.ProgramMode.PROGRAM_SCHEDULED_MANUAL_MODE\n                   }\n              },\n         125: { type: \"ProgrammableSwitchEvent\",\n                sche: \"programmableSwitchEvent\",\n                characteristic: Characteristic.ProgrammableSwitchEvent,\n                deprecated: false,\n                UUID: \"00000073-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Current Position State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"SINGLE_PRESS\": Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,\n                    \"DOUBLE_PRESS\": Characteristic.ProgrammableSwitchEvent.DOUBLE_PRESS,\n                    \"LONG_PRESS\":   Characteristic.ProgrammableSwitchEvent.LONG_PRESS\n                   }\n              },\n         126: { type: \"ProgrammableSwitchOutputState\",   // HomeKitTypes-Bridge\n                sche: \"programmableSwitchOutputState\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.ProgrammableSwitchOutputState,\n                deprecated: false,\n                UUID: \"00000074-0000-1000-8000-0026BB765291\",\n                description: \"The Programmable Switches Output State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         127: { type: \"Reachable\",   // HomeKitTypes-Bridge\n                sche: \"reachable\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.Reachable,\n                deprecated: true,\n                UUID: \"00000063-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is Reachable\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         128: { type: \"ReceivedSignalStrengthIndication\",  // HomeKit\n                sche: \"receivedSignalStrengthIndication\",  // HomeKit\n                characteristic: Characteristic.ReceivedSignalStrengthIndication,\n                deprecated: false,\n                UUID: \"0000023F-0000-1000-8000-0026BB765291\",\n                description: \"The Received Signal Strength Measurement\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         129: { type: \"ReceiverSensitivity\",  // HomeKitTypes.d.ts\n                sche: \"receiverSensitivity\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.ReceiverSensitivity,\n                deprecated: false,\n                UUID: \"00000244-0000-1000-8000-0026BB765291\",\n                description: \"The Amount of Receiver Sensitivity\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         130: { type: \"RecordingAudioActive\",  // HomeKitTypes.d.ts\n                sche: \"recordingAudioActive\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.RecordingAudioActive,\n                deprecated: false,\n                UUID: \"00000226-0000-1000-8000-0026BB765291\",\n                description: \"Is Recordding Audio Enabled/DisAbled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"DISABLE\": Characteristic.RecordingAudioActive.DISABLE,   // CHECK\n                    \"ENABLE\":  Characteristic.RecordingAudioActive.ENABLE\n                   }\n              },\n         131: { type: \"RelativeHumidityDehumidifierThreshold\",\n                sche: \"relativeHumidityDehumidifierThreshold\",\n                characteristic: Characteristic.RelativeHumidityDehumidifierThreshold,\n                deprecated: false,\n                UUID: \"000000C9-0000-1000-8000-0026BB765291\",\n                description: \"The Relative Humidity DeHumidifier Threshold\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         132: { type: \"RelativeHumidityHumidifierThreshold\",\n                sche: \"relativeHumidityHumidifierThreshold\",\n                characteristic: Characteristic.RelativeHumidityHumidifierThreshold,\n                deprecated: false,\n                UUID: \"000000CA-0000-1000-8000-0026BB765291\",\n                description: \"The Relative Humidity Humidifier Threshold\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         133: { type: \"RelayControlPoint\",   // HomeKitTypes-Bridge\n                sche: \"relayControlPoint\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.RelayControlPoint,\n                deprecated: false,\n                UUID: \"0000005E-0000-1000-8000-0026BB765291\",\n                description: \"The Relay Control Point\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         134: { type: \"RelayEnabled\",   // HomeKitTypes-Bridge\n                sche: \"relayEnabled\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.RelayEnabled,\n                deprecated: false,\n                UUID: \"0000005B-0000-1000-8000-0026BB765291\",\n                description: \"Is the Relay Currently Enabled\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         135: { type: \"RelayState\",   // HomeKitTypes-Bridge\n                sche: \"relayState\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.RelayState,\n                deprecated: false,\n                UUID: \"0000005C-0000-1000-8000-0026BB765291\",\n                description: \"The Relays Current State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 5,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         136: { type: \"RemainingDuration\",\n                sche: \"remainingDuration\",\n                characteristic: Characteristic.RemainingDuration,\n                deprecated: false,\n                UUID: \"000000D4-0000-1000-8000-0026BB765291\",\n                description: \"The Remaining Duration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        maxValue: 3600,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         137: { type: \"RemoteKey\",   // HomeKitTypes-Television\n                sche: \"remoteKey\",   // HomeKitTypes-Television\n                characteristic: Characteristic.RemoteKey,\n                deprecated: false,\n                UUID: \"000000E1-0000-1000-8000-0026BB765291\",\n                description: \"The Remote Key\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 16,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"REWIND\":         Characteristic.RemoteKey.REWIND,\n                    \"FAST_FORWARD\":   Characteristic.RemoteKey.FAST_FORWARD,\n                    \"NEXT_TRACK\":     Characteristic.RemoteKey.NEXT_TRACK,\n                    \"PREVIOUS_TRACK\": Characteristic.RemoteKey.PREVIOUS_TRACK,\n                    \"ARROW_UP\":       Characteristic.RemoteKey.ARROW_UP,\n                    \"ARROW_DOWN\":     Characteristic.RemoteKey.ARROW_DOWN,\n                    \"ARROW_LEFT\":     Characteristic.RemoteKey.ARROW_LEFT,\n                    \"ARROW_RIGHT\":    Characteristic.RemoteKey.ARROW_RIGHT,\n                    \"SELECT\":         Characteristic.RemoteKey.SELECT,\n                    \"BACK\":           Characteristic.RemoteKey.BACK,\n                    \"EXIT\":           Characteristic.RemoteKey.EXIT,\n                    \"PLAY_PAUSE\":     Characteristic.RemoteKey.PLAY_PAUSE,\n                    \"UNKNOWN12\":      12,  // HomeBridge does not have these defined for values\n                    \"UNKNOWN13\":      13,  // HomeBridge does not have these defined for values\n                    \"UNKNOWN14\":      14,  // HomeBridge does not have these defined for values\n                    \"INFORMATION\":    Characteristic.RemoteKey.INFORMATION,\n                    \"UNKNOWN16\":      16   // HomeBridge does not have these defined for values\n                   }\n              },\n         138: { type: \"ResetFilterIndication\",\n                sche: \"resetFilterIndication\",\n                characteristic: Characteristic.ResetFilterIndication,\n                deprecated: false,\n                UUID: \"000000AD-0000-1000-8000-0026BB765291\",\n                description: \"If Reset Filter Indication \",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 1,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         139: { type: \"RotationDirection\",\n                sche: \"rotationDirection\",\n                characteristic: Characteristic.RotationDirection,\n                deprecated: false,\n                UUID: \"00000028-0000-1000-8000-0026BB765291\",\n                description: \"The Current Direction of Rotation\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"CLOCKWISE\":\n                      Characteristic.RotationDirection.CLOCKWISE,\n                    \"COUNTER_CLOCKWISE\":\n                      Characteristic.RotationDirection.COUNTER_CLOCKWISE\n                   }\n              },\n         140: { type: \"RotationSpeed\",\n                sche: \"rotationSpeed\",\n                characteristic: Characteristic.RotationSpeed,\n                deprecated: false,\n                UUID: \"00000029-0000-1000-8000-0026BB765291\",\n                description: \"The Current Speed of Rotation\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         141: { type: \"RouterStatus\",  // HomeKitTypes.d.ts\n                sche: \"routerStatus\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.RouterStatus,\n                deprecated: false,\n                UUID: \"0000020E-0000-1000-8000-0026BB765291\",\n                description: \"The Current Router Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {\"READY\"     : Characteristic.RouterStatus.READY,     // 0\n                              \"NOT_READY\" : Characteristic.RouterStatus.NOT_READY  // 1\n                             }\n              },\n         142: { type: \"Saturation\",\n                sche: \"saturation\",\n                characteristic: Characteristic.Saturation,\n                deprecated: false,\n                UUID: \"0000002F-0000-1000-8000-0026BB765291\",\n                description: \"The Percentage of Color Saturation\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         143: { type: \"SecuritySystemAlarmType\",  // Checked 03/17/21\n                sche: \"securitySystemAlarmType\",  // Checked 03/17/21\n                characteristic: Characteristic.SecuritySystemAlarmType,\n                deprecated: false,\n                UUID: \"0000008E-0000-1000-8000-0026BB765291\",\n                description: \"The Security System Alarm Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         144: { type: \"SecuritySystemCurrentState\",\n                sche: \"securitySystemCurrentState\",\n                characteristic: Characteristic.SecuritySystemCurrentState,\n                deprecated: false,\n                UUID: \"00000066-0000-1000-8000-0026BB765291\",\n                description: \"The Security Systems Currently Armed State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.SecuritySystemTargetState,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 4,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"STAY_ARM\":\n                      Characteristic.SecuritySystemCurrentState.STAY_ARM,\n                    \"AWAY_ARM\":\n                       Characteristic.SecuritySystemCurrentState.AWAY_ARM,\n                    \"NIGHT_ARM\":\n                       Characteristic.SecuritySystemCurrentState.NIGHT_ARM,\n                    \"DISARMED\":\n                       Characteristic.SecuritySystemCurrentState.DISARMED,\n                    \"ALARM_TRIGGERED\":\n                       Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED\n                   }\n              },\n         145: { type: \"SecuritySystemTargetState\",\n                sche: \"securitySystemTargetState\",\n                characteristic: Characteristic.SecuritySystemTargetState,\n                deprecated: false,\n                UUID: \"00000067-0000-1000-8000-0026BB765291\",\n                description: \"The Target Armed State of the Security System\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.SecuritySystemCurrentState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                {\"STAY_ARM\":  Characteristic.SecuritySystemTargetState.STAY_ARM,\n                 \"AWAY_ARM\":  Characteristic.SecuritySystemTargetState.AWAY_ARM,\n                 \"NIGHT_ARM\": Characteristic.SecuritySystemTargetState.NIGHT_ARM,\n                 \"DISARM\":    Characteristic.SecuritySystemTargetState.DISARM\n                }\n              },\n         146: { type: \"SelectedAudioStreamConfiguration\",  // HomeKit-Remote\n                sche: \"selectedAudioStreamConfiguration\",  // HomeKit-Remote\n                characteristic: Characteristic.SelectedAudioStreamConfiguration,\n                deprecated: false,\n                UUID: \"00000128-0000-1000-8000-0026BB765291\",\n                description: \"The Selected Audio Stream Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         147: { type: \"SelectedCameraRecordingConfiguration\",  // HomeKitTypes.d.ts\n                sche: \"selectedCameraRecordingConfiguration\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.SelectedCameraRecordingConfiguration,\n                deprecated: false,\n                UUID: \"00000209-0000-1000-8000-0026BB765291\",\n                description: \"The Selected Cameras Recording Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         148: { type: \"SelectedRTPStreamConfiguration\",\n                sche: \"selectedRTPStreamConfiguration\",\n                characteristic: Characteristic.SelectedRTPStreamConfiguration,\n                deprecated: false,\n                UUID: \"00000117-0000-1000-8000-0026BB765291\",\n                description: \"The Selected RTP Stream Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         149: { type: \"SerialNumber\",\n                sche: \"serialNumber\",\n                characteristic: Characteristic.SerialNumber,\n                deprecated: false,\n                UUID: \"00000030-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Serial Number\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         150: { type: \"ServiceLabelIndex\",\n                sche: \"serviceLabelIndex\",\n                characteristic: Characteristic.ServiceLabelIndex,\n                deprecated: false,\n                UUID: \"000000CB-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Service Label Index\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 255,\n                        minValue: 1,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         151: { type: \"ServiceLabelNamespace\",\n                sche: \"serviceLabelNamespace\",\n                characteristic: Characteristic.ServiceLabelNamespace,\n                deprecated: false,\n                UUID: \"000000CD-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Service Label NameSpace\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                   {\"DOTS\":            Characteristic.ServiceLabelNamespace.DOTS,\n                    \"ARABIC_NUMERALS\": Characteristic.ServiceLabelNamespace.ARABIC_NUMERALS\n                   }\n              },\n         152: { type: \"SetDuration\",\n                sche: \"setDuration\",\n                characteristic: Characteristic.SetDuration,\n                deprecated: false,\n                UUID: \"000000D3-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Set Duration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        maxValue: 3600,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         153: { type: \"SetupDataStreamTransport\",  // HomeKit-DataStream\n                sche: \"setupDataStreamTransport\",  // HomeKit-DataStream\n                characteristic: Characteristic.SetupDataStreamTransport,\n                deprecated: false,\n                UUID: \"00000131-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Setup Stream Transport Value\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         154: { type: \"SetupEndpoints\",\n                sche: \"setupEndpoints\",\n                characteristic: Characteristic.SetupEndpoints,\n                deprecated: false,\n                UUID: \"00000118-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Setup End Points\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         155: { type: \"SetupTransferTransport\",  // HomeKitTypes.d.ts\n                sche: \"setupTransferTransport\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.SetupTransferTransport,\n                deprecated: false,\n                UUID: \"00000201-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Setup Transfer Transport\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         156: { type: \"SignalToNoiseRatio\",  // HomeKit\n                sche: \"signalToNoiseRatio\",  // HomeKit\n                characteristic: Characteristic.SignalToNoiseRatio,\n                deprecated: false,\n                UUID: \"00000241-0000-1000-8000-0026BB765291\",\n                description: \"The Measured Signal to Noise Ratio\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         157: { type: \"SiriInputType\",  // HomeKit-Remote\n                sche: \"siriInputType\",  // HomeKit-Remote\n                characteristic: Characteristic.SiriInputType,\n                deprecated: false,\n                UUID: \"00000132-0000-1000-8000-0026BB765291\",\n                description: \"siri's Input Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 0,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: { // Check\n                      \"PUSH_BUTTON_TRIGGERED_APPLE_TV\": Characteristic.SiriInputType.PUSH_BUTTON_TRIGGERED_APPLE_TV\n                }\n              },\n         158: { type: \"SlatType\",\n                sche: \"slatType\",\n                characteristic: Characteristic.SlatType,\n                deprecated: false,\n                UUID: \"000000C0-0000-1000-8000-0026BB765291\",\n                description: \"The Slat Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                   {\"HORIZONTAL\": Characteristic.SlatType.HORIZONTAL,\n                    \"VERTICAL\":   Characteristic.SlatType.VERTICAL\n                   }\n              },\n         159: { type: \"SleepDiscoveryMode\",   // HomeKitTypes-Television\n                sche: \"sleepDiscoveryMode\",   // HomeKitTypes-Television\n                characteristic: Characteristic.SleepDiscoveryMode,\n                deprecated: false,\n                UUID: \"000000E8-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Discoverable Sleep Mode\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NOT_DISCOVERABLE\":    Characteristic.SleepDiscoveryMode.NOT_DISCOVERABLE ,\n                    \"ALWAYS_DISCOVERABLE\": Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE\n                   }\n              },\n         160: { type: \"SleepInterval\",  // HomeKitTypes.d.ts\n                sche: \"sleepInterval\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.SleepInterval,\n                deprecated: false,\n                UUID: \"0000023A-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Sleep Interval\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         161: { type: \"SmokeDetected\",\n                sche: \"smokeDetected\",\n                characteristic: Characteristic.SmokeDetected,\n                deprecated: false,\n                UUID: \"00000076-0000-1000-8000-0026BB765291\",\n                description: \"If Smoke is Detected or Not\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"SMOKE_NOT_DETECTED\": Characteristic.SmokeDetected.SMOKE_NOT_DETECTED,\n                    \"SMOKE_DETECTED\":     Characteristic.SmokeDetected.SMOKE_DETECTED\n                   }\n              },\n         162: { type: \"SoftwareRevision\",  // HomeKit-Bridge\n                sche: \"softwareRevision\",  // HomeKit-Bridge\n                characteristic: Characteristic.SoftwareRevision,\n                deprecated: false,\n                UUID: \"00000054-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Software Revision String\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         163: { type: \"StatusActive\",\n                sche: \"statusActive\",\n                characteristic: Characteristic.StatusActive,\n                deprecated: false,\n                UUID: \"00000075-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is Active or Not\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                     \"TRUE\": 1\n                   }\n              },\n         164: { type: \"StatusFault\",\n                sche: \"statusFault\",\n                characteristic: Characteristic.StatusFault,\n                deprecated: false,\n                UUID: \"00000077-0000-1000-8000-0026BB765291\",\n                description: \"If the Device has a Status Fault\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NO_FAULT\":      Characteristic.StatusFault.NO_FAULT,\n                     \"GENERAL_FAULT\": Characteristic.StatusFault.GENERAL_FAULT\n                   }\n              },\n         165: { type: \"StatusJammed\",\n                sche: \"statusJammed\",\n                characteristic: Characteristic.StatusJammed,\n                deprecated: false,\n                UUID: \"00000078-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is in Jammed Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NOT_JAMMED\": Characteristic.StatusJammed.NOT_JAMMED,\n                    \"JAMMED\":     Characteristic.StatusJammed.JAMMED\n                   }\n              },\n         166: { type: \"StatusLowBattery\",\n                sche: \"statusLowBattery\",\n                characteristic: Characteristic.StatusLowBattery,\n                deprecated: false,\n                UUID: \"00000079-0000-1000-8000-0026BB765291\",\n                description: \"The Status of the Battery Level\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"BATTERY_LEVEL_NORMAL\":\n                      Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,\n                    \"BATTERY_LEVEL_LOW\":\n                      Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW\n                   }\n              },\n         167: { type: \"StatusTampered\",\n                sche: \"statusTampered\",\n                characteristic: Characteristic.StatusTampered,\n                deprecated: false,\n                UUID: \"0000007A-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is Tampered\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NOT_TAMPERED\": Characteristic.StatusTampered.NOT_TAMPERED,\n                    \"TAMPERED\":     Characteristic.StatusTampered.TAMPERED\n                   }\n              },\n         168: { type: \"StreamingStatus\",\n                sche: \"streamingStatus\",\n                characteristic: Characteristic.StreamingStatus,\n                deprecated: false,\n                UUID: \"00000120-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Streaming Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         169: { type: \"SulphurDioxideDensity\",\n                sche: \"sulphurDioxideDensity\",\n                characteristic: Characteristic.SulphurDioxideDensity,\n                deprecated: false,\n                UUID: \"000000C5-0000-1000-8000-0026BB765291\",\n                description: \"The measured Sulphur Dioxide Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         170: { type: \"SupportedAudioRecordingConfiguration\",\n                sche: \"supportedAudioRecordingConfiguration\",\n                characteristic: Characteristic.SupportedAudioRecordingConfiguration,\n                deprecated: false,\n                UUID: \"00000207-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Audio Recording Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         171: { type: \"SupportedAudioStreamConfiguration\",   // HomeKit\n                sche: \"supportedAudioStreamConfiguration\",   // HomeKit\n                characteristic: Characteristic.SupportedAudioStreamConfiguration,\n                deprecated: false,\n                UUID: \"00000115-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Audio Stream Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         172: { type: \"SupportedCameraRecordingConfiguration\",   // HomeKit\n                sche: \"supportedCameraRecordingConfiguration\",   // HomeKit\n                characteristic: Characteristic.SupportedCameraRecordingConfiguration,\n                deprecated: false,\n                UUID: \"00000205-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Audio Recording Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         173: { type: \"SupportedDataStreamTransportConfiguration\",   // HomeKit-DataStream\n                sche: \"supportedDataStreamTransportConfiguration\",   // HomeKit-DataStream\n                characteristic: Characteristic.SupportedDataStreamTransportConfiguration,\n                deprecated: false,\n                UUID: \"00000130-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Data Stream Transport Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         174: { type: \"SupportedCharacteristicValueTransitionConfiguration\",   // HomeKit\n                sche: \"supportedCharacteristicValueTransitionConfiguration\",   // HomeKit\n                characteristic: Characteristic.SupportedCharacteristicValueTransitionConfiguration,\n                deprecated: false,\n                UUID: \"00000144-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Characteristic Value Transition Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         175: { type: \"SupportedDiagnosticsSnapshot\",  // HomeKitTypes.d.ts\n                sche: \"supportedDiagnosticsSnapshot\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.SupportedDiagnosticsSnapshot,\n                deprecated: false,\n                UUID: \"00000238-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Diagnostic Snapshot\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         176: { type: \"SupportedRTPConfiguration\",\n                sche: \"supportedRTPConfiguration\",\n                characteristic: Characteristic.SupportedRTPConfiguration,\n                deprecated: false,\n                UUID: \"00000116-0000-1000-8000-0026BB765291\",\n                description: \"The Supported RTP Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         177: { type: \"SupportedRouterConfiguration\",  // HomeKitTypes.d.ts\n                sche: \"supportedRouterConfiguration\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.SupportedRouterConfiguration,\n                deprecated: false,\n                UUID: \"00000210-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Router Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         178: { type: \"SupportedTransferTransportConfiguration\",  // HomeKit\n                sche: \"supportedTransferTransportConfiguration\",  // HomeKit\n                characteristic: Characteristic.SupportedTransferTransportConfiguration,\n                deprecated: false,\n                UUID: \"00000202-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Transfer Transport Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         179: { type: \"SupportedVideoRecordingConfiguration\",\n                sche: \"supportedVideoRecordingConfiguration\",\n                characteristic: Characteristic.SupportedVideoRecordingConfiguration,\n                deprecated: false,\n                UUID: \"00000206-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Video Recording Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         180: { type: \"SupportedVideoStreamConfiguration\",\n                sche: \"supportedVideoStreamConfiguration\",\n                characteristic: Characteristic.SupportedVideoStreamConfiguration,\n                deprecated: false,\n                UUID: \"00000114-0000-1000-8000-0026BB765291\",\n                description: \"The Supported Video Stream Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         181: { type: \"SwingMode\",\n                sche: \"swingMode\",\n                characteristic: Characteristic.SwingMode,\n                deprecated: false,\n                UUID: \"000000B6-0000-1000-8000-0026BB765291\",\n                description: \"The DevicesnCurrent Swing Mode\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n               validValues:\n                  {\"SWING_DISABLED\": Characteristic.SwingMode.SWING_DISABLED,\n                   \"SWING_ENABLED\": Characteristic.SwingMode.SWING_ENABLED\n                  }\n              },\n         182: { type: \"TargetAirPurifierState\",\n                sche: \"targetAirPurifierState\",\n                characteristic: Characteristic.TargetAirPurifierState,\n                deprecated: false,\n                UUID: \"000000A8-0000-1000-8000-0026BB765291\",\n                description: \"The Requested Target Air Purification State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentAirPurifierState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:   // Checked 04/24/2020\n                   {\"MANUAL\": Characteristic.TargetAirPurifierState.MANUAL,\n                    \"AUTO\":   Characteristic.TargetAirPurifierState.AUTO\n                   }\n              },\n              // @deprecated Removed and not used anymore as of homebridge v2\n         183: { type: \"TargetAirQuality\",\n                sche: \"targetAirQuality\",\n                characteristic: Characteristic.TargetAirQuality,\n                deprecated: true,\n                UUID: \"000000AE-0000-1000-8000-0026BB765291\",\n                description: \"The Requested Target Air Quality\",\n                relatedCurrentAccTypeEnumIndex:\n                   // @deprecated Removed and not used anymore as of homebridge v2\n                   null,\n                   // CMD4_ACC_TYPE_ENUM.AirQuality,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\n                    // @deprecated Removed and not used anymore as of homebridge v2\n                    // \"EXCELLENT\": Characteristic.TargetAirQuality.EXCELLENT,\n                    // \"GOOD\":      Characteristic.TargetAirQuality.GOOD,\n                    // \"FAIR\":      Characteristic.TargetAirQuality.FAIR\n                   }\n              },\n         184: { type: \"TargetControlList\",   // Homekit-Remote\n                sche: \"targetControlList\",   // Homekit-Remote\n                characteristic: Characteristic.TargetControlList,\n                deprecated: false,\n                UUID: \"00000124-0000-1000-8000-0026BB765291\",\n                description: \"The Target Control List\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_WRITE,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         185: { type: \"TargetControlSupportedConfiguration\",   // Homekit-Remote\n                sche: \"targetControlSupportedConfiguration\",   // Homekit-Remote\n                characteristic: Characteristic.TargetControlSupportedConfiguration,\n                deprecated: false,\n                UUID: \"00000123-0000-1000-8000-0026BB765291\",\n                description: \"The Target Supported Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         186: { type: \"TargetDoorState\",\n                sche: \"targetDoorState\",\n                characteristic: Characteristic.TargetDoorState,\n                deprecated: false,\n                UUID: \"00000032-0000-1000-8000-0026BB765291\",\n                description: \"The Doors Requested State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentDoorState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OPEN\":   Characteristic.TargetDoorState.OPEN,\n                    \"CLOSED\": Characteristic.TargetDoorState.CLOSED\n                   }\n              },\n         187: { type: \"TargetFanState\",\n                sche: \"targetFanState\",\n                characteristic: Characteristic.TargetFanState,\n                deprecated: false,\n                UUID: \"000000BF-0000-1000-8000-0026BB765291\",\n                description: \"The Fans Requested State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentFanState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"MANUAL\": Characteristic.TargetFanState.MANUAL,\n                    \"AUTO\": Characteristic.TargetFanState.AUTO\n                   }\n              },\n         188: { type: \"TargetHeaterCoolerState\",\n                sche: \"targetHeaterCoolerState\",\n                characteristic: Characteristic.TargetHeaterCoolerState,\n                deprecated: false,\n                UUID: \"000000B2-0000-1000-8000-0026BB765291\",\n                description: \"The Heaters Requested Cooling State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentHeaterCoolerState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"AUTO\": Characteristic.TargetHeaterCoolerState.AUTO,\n                    \"HEAT\": Characteristic.TargetHeaterCoolerState.HEAT,\n                    \"COOL\": Characteristic.TargetHeaterCoolerState.COOL\n                   }\n              },\n         189: { type: \"TargetHeatingCoolingState\",\n                sche: \"targetHeatingCoolingState\",\n                characteristic: Characteristic.TargetHeatingCoolingState,\n                deprecated: false,\n                UUID: \"00000033-0000-1000-8000-0026BB765291\",\n                description: \"The Heaters Requested Heating State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentHeatingCoolingState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"OFF\": Characteristic.TargetHeatingCoolingState.OFF,\n                    \"HEAT\": Characteristic.TargetHeatingCoolingState.HEAT,\n                    \"COOL\": Characteristic.TargetHeatingCoolingState.COOL,\n                    \"AUTO\": Characteristic.TargetHeatingCoolingState.AUTO\n                   }\n              },\n         190: { type: \"TargetHorizontalTiltAngle\",\n                sche: \"targetHorizontalTiltAngle\",\n                characteristic: Characteristic.TargetHorizontalTiltAngle,\n                deprecated: false,\n                UUID: \"0000007B-0000-1000-8000-0026BB765291\",\n                description: \"The Requested Horizontal Tilt Angle\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentHorizontalTiltAngle,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 90,\n                        minValue: -90,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         191: { type: \"TargetHumidifierDehumidifierState\",\n                sche: \"targetHumidifierDehumidifierState\",\n                characteristic: Characteristic.TargetHumidifierDehumidifierState,\n                deprecated: false,\n                UUID: \"000000B4-0000-1000-8000-0026BB765291\",\n                description: \"The Requested Humidifier/DeHumidifier State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentHumidifierDehumidifierState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                  {\"HUMIDIFIER_OR_DEHUMIDIFIER\":\n                     Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER_OR_DEHUMIDIFIER,\n                   \"HUMIDIFIER\":\n                     Characteristic.TargetHumidifierDehumidifierState.HUMIDIFIER,\n                   \"DEHUMIDIFIER\":\n                     Characteristic.TargetHumidifierDehumidifierState.DEHUMIDIFIER\n                  }\n              },\n         192: { type: \"TargetMediaState\",   // HomeKitTypes-Television\n                sche: \"targetMediaState\",   // HomeKitTypes-Television\n                characteristic: Characteristic.TargetMediaState,\n                deprecated: false,\n                UUID: \"00000137-0000-1000-8000-0026BB765291\",\n                description: \"The Requested Media State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentMediaState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"PLAY\": Characteristic.TargetMediaState.PLAY,\n                    \"PAUSE\": Characteristic.TargetMediaState.PAUSE,\n                    \"STOP\": Characteristic.TargetMediaState.STOP\n                   }\n              },\n         193: { type: \"TargetPosition\",\n                sche: \"targetPosition\",\n                characteristic: Characteristic.TargetPosition,\n                deprecated: false,\n                UUID: \"0000007C-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Position\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         194: { type: \"TargetRelativeHumidity\",\n                sche: \"targetRelativeHumidity\",\n                characteristic: Characteristic.TargetRelativeHumidity,\n                deprecated: false,\n                UUID: \"00000034-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Relative Humidity Level\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentRelativeHumidity,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         195: { type: \"TargetSlatState\",\n                sche: \"targetSlatState\",\n                characteristic: Characteristic.TargetSlatState,\n                deprecated: true,\n                UUID: \"000000BE-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Slat State\",\n                relatedCurrentAccTypeEnumIndex:\n                   // @deprecated Removed and not used anymore as of homebridge v2\n                   null,\n                   // CMD4_ACC_TYPE_ENUM.CurrentSlatState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\n                    // @deprecated Removed and not used anymore as of homebridge v2\n                    // \"MANUAL\": Characteristic.TargetSlatState.MANUAL,\n                    // \"AUTO\":   Characteristic.TargetSlatState.AUTO\n                   }\n              },\n         196: { type: \"TargetTemperature\",\n                sche: \"targetTemperature\",\n                characteristic: Characteristic.TargetTemperature,\n                deprecated: false,\n                UUID: \"00000035-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Temperature\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentTemperature,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.CELSIUS,\n                        maxValue: 38,\n                        minValue: 10,\n                        minStep: 0.1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         197: { type: \"TargetTiltAngle\",\n                sche: \"targetTiltAngle\",\n                characteristic: Characteristic.TargetTiltAngle,\n                deprecated: false,\n                UUID: \"000000C2-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Tilt Angle\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentTiltAngle,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit:   hapUnits.ARC_DEGREE,\n                        maxValue:  90,\n                        minValue: -90,\n                        minStep:   1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         198: { type: \"TargetVerticalTiltAngle\",\n                sche: \"targetVerticalTiltAngle\",\n                characteristic: Characteristic.TargetVerticalTiltAngle,\n                deprecated: false,\n                UUID: \"0000007D-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Vertical Tilt Angle\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentVerticalTiltAngle,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        unit: hapUnits.ARC_DEGREE,\n                        maxValue: 90,\n                        minValue: -90,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         199: { type: \"TargetVisibilityState\",   // HomeKittypes-Television\n                sche: \"targetVisibilityState\",   // HomeKittypes-Television\n                characteristic: Characteristic.TargetVisibilityState,\n                deprecated: false,\n                UUID: \"00000134-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Requested Visibility State\",\n                relatedCurrentAccTypeEnumIndex: CMD4_ACC_TYPE_ENUM.CurrentVisibilityState,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"SHOWN\": Characteristic.TargetVisibilityState.SHOWN,\n                    \"HIDDEN\": Characteristic.TargetVisibilityState.HIDDEN\n                   }\n              },\n         200: { type: \"TemperatureDisplayUnits\",\n                sche: \"temperatureDisplayUnits\",\n                characteristic: Characteristic.TemperatureDisplayUnits,\n                deprecated: false,\n                UUID: \"00000036-0000-1000-8000-0026BB765291\",\n                description: \"The Units to Display the Temperature in\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"CELSIUS\":    Characteristic.TemperatureDisplayUnits.CELSIUS,\n                    \"FAHRENHEIT\": Characteristic.TemperatureDisplayUnits.FAHRENHEIT\n                    }\n              },\n         201: { type: \"ThirdPartyCameraActive\",  // HomeKitTypes.d.ts\n                sche: \"thirdPartyCameraActive\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.ThirdPartyCameraActive,\n                deprecated: false,\n                UUID: \"0000021C-0000-1000-8000-0026BB765291\",\n                description: \"The ON/OFF Auxiliary Camera State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   { \"OFF\" : Characteristic.ThirdPartyCameraActive.OFF,   // 0 \n                     \"ON\"  : Characteristic.ThirdPartyCameraActive.ON     // 1\n                   }\n              },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         202: { type: \"TimeUpdate\",   // HomeKitTypes-Bridge\n                sche: \"timeUpdate\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.TimeUpdate,\n                deprecated: true,\n                UUID: \"0000009A-0000-1000-8000-0026BB765291\",\n                description: \"Ifnthe Time Should be Updated\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         203: { type: \"TransmitPower\",   // HomeKitTypes\n                sche: \"transmitPower\",   // HomeKitTypes\n                characteristic: Characteristic.TransmitPower,\n                deprecated: false,\n                UUID: \"00000242-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Measured Transmit Power\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         204: { type: \"MaximumTransmitPower\",\n                sche: \"MaximumTransmitPower\",\n                characteristic: Characteristic.MaximumTransmitPower,\n                deprecated: false,\n                UUID: \"00000243-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Maximum Transmit Power\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         205: { type: \"TunnelConnectionTimeout\",   // HomeKitTypes-Bridge\n                sche: \"tunnelConnectionTimeout\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.TunnelConnectionTimeout,\n                deprecated: false,\n                UUID: \"00000061-0000-1000-8000-0026BB765291\",\n                description: \"The Timeout Value of the Tunnel Connection\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues: {}\n              },\n         206: { type: \"TunneledAccessoryAdvertising\",   // HomeKitTypes-Bridge\n                sche: \"tunneledAccessoryAdvertising\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.TunneledAccessoryAdvertising,\n                deprecated: false,\n                UUID: \"00000060-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is Currently Tunneled Advertising\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_WRITE,   // Reversed in HomeBridge\n                                hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         207: { type: \"TunneledAccessoryConnected\",   // HomeKitTypes-Bridge\n                sche: \"tunneledAccessoryConnected\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.TunneledAccessoryConnected,\n                deprecated: false,\n                UUID: \"00000059-0000-1000-8000-0026BB765291\",\n                description: \"If the Device is Tunneled Connected \",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"FALSE\": 0,\n                    \"TRUE\":  1\n                   }\n              },\n         208: { type: \"TunneledAccessoryStateNumber\",   // HomeKitTypes-Bridge\n                sche: \"tunneledAccessoryStateNumber\",   // HomeKitTypes-Bridge\n                characteristic: Characteristic.TunneledAccessoryStateNumber,\n                deprecated: false,\n                UUID: \"00000058-0000-1000-8000-0026BB765291\",\n                description: \"The Tunneled Accessorys State Number\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.INT,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         209: { type: \"VOCDensity\",\n                sche: \"vocDensity\",\n                characteristic: Characteristic.VOCDensity,\n                deprecated: false,\n                UUID: \"000000C8-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Measured VOC Density\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 1000,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         210: { type: \"ValveType\",\n                sche: \"valveType\",\n                characteristic: Characteristic.ValveType,\n                deprecated: false,\n                UUID: \"000000D5-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Valve Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"GENERIC_VALVE\": Characteristic.ValveType.GENERIC_VALVE,\n                    \"IRRIGATION\":    Characteristic.ValveType.IRRIGATION,\n                    \"SHOWER_HEAD\":   Characteristic.ValveType.SHOWER_HEAD,\n                    \"WATER_FAUCET\":  Characteristic.ValveType.WATER_FAUCET\n                   }\n              },\n         211: { type: \"Version\",\n                sche: \"version\",\n                characteristic: Characteristic.Version,\n                deprecated: false,\n                UUID: \"00000037-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Version String\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         212: { type: \"VideoAnalysisActive\",\n                sche: \"videoAnalysisActive\",\n                characteristic: Characteristic.VideoAnalysisActive,\n                deprecated: false,\n                UUID: \"00000229-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Video Analysis Active Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {}\n              },\n         213: { type: \"Volume\",\n                sche: \"volume\",\n                characteristic: Characteristic.Volume,\n                deprecated: false,\n                UUID: \"00000119-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Volume as a Percentage\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        unit: hapUnits.PERCENTAGE,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         214: { type: \"VolumeControlType\",   // HomeKitTypes-Television\n                sche: \"volumeControlType\",   // HomeKitTypes-Television\n                characteristic: Characteristic.VolumeControlType,\n                deprecated: false,\n                UUID: \"000000E9-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Volume Control Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 3,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                   {\"NONE\":\n                       Characteristic.VolumeControlType.NONE,\n                    \"RELATIVE\":\n                       Characteristic.VolumeControlType.RELATIVE,\n                    \"RELATIVE_WITH_CURRENT\":\n                       Characteristic.VolumeControlType.RELATIVE_WITH_CURRENT,\n                    \"ABSOLUTE\":\n                       Characteristic.VolumeControlType.ABSOLUTE\n                    }\n              },\n         215: { type: \"VolumeSelector\",   // HomeKitTypes-Television\n                sche: \"volumeSelector\",   // HomeKitTypes-Television\n                characteristic: Characteristic.VolumeSelector,\n                deprecated: false,\n                UUID: \"000000EA-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Volume Selector\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        minStep:  1,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                   {\"INCREMENT\": Characteristic.VolumeSelector.INCREMENT,\n                    \"DECREMENT\": Characteristic.VolumeSelector.DECREMENT\n                   }\n              },\n         216: { type: \"WANConfigurationList\",  // HomeKitTypes.d.ts\n                sche: \"wanConfigurationList\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.WANConfigurationList,\n                deprecated: false,\n                UUID: \"00000211-0000-1000-8000-0026BB765291\",\n                description: \"The Devices WAN Configuration List\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         217: { type: \"WANStatusList\",  // HomeKitTypes.d.ts\n                sche: \"wanStatusList\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.WANStatusList,\n                deprecated: false,\n                UUID: \"00000212-0000-1000-8000-0026BB765291\",\n                description: \"The Devices WAN Status List\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         218: { type: \"WakeConfiguration\",  // HomeKitTypes.d.ts\n                sche: \"wakeConfiguration\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.WakeConfiguration,\n                deprecated: false,\n                UUID: \"00000222-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Wake Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         219: { type: \"WaterLevel\",\n                sche: \"waterLevel\",\n                characteristic: Characteristic.WaterLevel,\n                deprecated: false,\n                UUID: \"000000B5-0000-1000-8000-0026BB765291\",\n                description: \"The Current Water Level Measurement\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToFloat( str ); },\n                props: {format: hapFormats.FLOAT,\n                        allowedWordCount: 1,\n                        maxValue: 100,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues: {}\n              },\n         220: { type: \"WiFiCapabilities\",   // HomeKit\n                sche: \"wifiCapabilities\",   // HomeKit\n                characteristic: Characteristic.WiFiCapabilities,\n                deprecated: false,\n                UUID: \"0000022C-0000-1000-8000-0026BB765291\",\n                description: \"The Devices WiFi Capabilities\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues: {}\n              },\n         221: { type: \"WiFiConfigurationControl\",   // HomeKit\n                sche: \"wifiConfigurationControl\",   // HomeKit\n                characteristic: Characteristic.WiFiConfigurationControl,\n                deprecated: false,\n                UUID: \"0000022D-0000-1000-8000-0026BB765291\",\n                description: \"The Devices WiFi Configuration Control\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.NOTIFY,\n                                hapPerms.TIMED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues: {}\n              },\n         222: { type: \"WiFiSatelliteStatus\",  // HomeKitTypes.d.ts\n                sche: \"wifiSatelliteStatus\",  // HomeKitTypes.d.ts\n                characteristic: Characteristic.WiFiSatelliteStatus,\n                deprecated: false,\n                UUID: \"0000021E-0000-1000-8000-0026BB765291\",\n                description: \"The Devices WiFi Satellite Status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 2,\n                        minValue: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                       { \"UNKNOWN\": Characteristic.WiFiSatelliteStatus.UNKNOWN,               // 0,   - Check\n                         \"CONNECTED\" : Characteristic.WiFiSatelliteStatus.CONNECTED,          // 1,\n                         \"NOT_CONNECTED\": Characteristic.WiFiSatelliteStatus.NOT_CONNECTED    // 2\n                       }\n              },\n\n         223: { type: \"AssetUpdateReadiness\",\n                sche: \"assetUpdateReadiness\",\n                characteristic: Characteristic.AssetUpdateReadiness,\n                deprecated: false,\n                UUID: \"00000269-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Asset Update Readiness\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         224: { type: \"SupportedAssetTypes\",\n                sche: \"supportedAssetTypes\", \n                characteristic: Characteristic.SupportedAssetTypes,\n                deprecated: false,\n                UUID: \"00000268-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Supported Asset types\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         225: { type: \"ConfigurationState\",\n                sche: \"configurationState\",\n                characteristic: Characteristic.ConfigurationState,\n                deprecated: false,\n                UUID: \"00000263-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Configuration State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         226: { type: \"NFCAccessControlPoint\",\n                sche: \"NFCAccessControlPoint\",\n                characteristic: Characteristic.NFCAccessControlPoint,\n                deprecated: false,\n                UUID: \"00000264-0000-1000-8000-0026BB765291\",\n                description: \"The NFC Access Point\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         227: { type: \"NFCAccessSupportedConfiguration\",\n                sche: \"NFCAccessSupportedConfiguration\",\n                characteristic: Characteristic.NFCAccessSupportedConfiguration,\n                deprecated: false,\n                UUID: \"00000265-0000-1000-8000-0026BB765291\",\n                description: \"The Devices NFC Access Support Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         228: { type: \"SiriEndpointSessionStatus\",\n                sche: \"SiriEndpointSessionStatus\",\n                characteristic: Characteristic.SiriEndpointSessionStatus,\n                deprecated: false,\n                UUID: \"00000254-0000-1000-8000-0026BB765291\",\n                description: \"The Devices Siri endpoint\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         229: { type: \"ThreadControlPoint\",\n                sche: \"threadControlPoint\",\n                characteristic: Characteristic.ThreadControlPoint,\n                deprecated: false,\n                UUID: \"00000704-0000-1000-8000-0026BB765291\",\n                description: \"The Devices thread control point\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         230: { type: \"ThreadNodeCapabilities\",\n                sche: \"threadNodeCapabilities\",\n                characteristic: Characteristic.ThreadNodeCapabilities,\n                deprecated: false,\n                UUID: \"00000702-0000-1000-8000-0026BB765291\",\n                description: \"The Devices thread node capabilities\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        maxValue: 31,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         231: { type: \"ThreadStatus\",\n                sche: \"threadStatus\",\n                characteristic: Characteristic.ThreadStatus,\n                deprecated: false,\n                UUID: \"00000703-0000-1000-8000-0026BB765291\",\n                description: \"The Devices thread status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        maxValue: 6,\n                        minValue: 0,\n                        minStep: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.NOTIFY\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         232: { type: \"ThreadOpenThreadVersion\",\n                sche: \"threadOpenThreadVersion\",\n                characteristic: Characteristic.ThreadOpenThreadVersion,\n                deprecated: false,\n                UUID: \"00000706-0000-1000-8000-0026BB765291\",\n                description: \"The Devices thread version\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         // Added Mar 2024\n         233: { type: \"AccessCodeControlPoint\",\n                sche: \"accessCodeControlPoint\",\n                characteristic: Characteristic.AccessCodeControlPoint,\n                deprecated: false,\n                UUID: \"00000262-0000-1000-8000-0026BB765291\",\n                description: \"Access Code Control Point\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         234: { type: \"AccessCodeSupportedConfiguration\",\n                sche: \"accessCodeSupportedConfiguration\",\n                characteristic: Characteristic.AccessCodeSupportedConfiguration,\n                deprecated: false,\n                UUID: \"00000261-0000-1000-8000-0026BB765291\",\n                description: \"Access Code Supported Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         235: { type: \"AirPlayEnable\",\n                sche: \"airPlayEnable\",\n                characteristic: Characteristic.AirPlayEnable,\n                deprecated: false,\n                UUID: \"0000025B-0000-1000-8000-0026BB765291\",\n                description: \"Airplay Enable\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         236: { type: \"CharacteristicValueActiveTransitionCount\",\n                sche: \"characteristicValueActiveTransitionCount\",\n                characteristic: Characteristic.CharacteristicValueActiveTransitionCount,\n                deprecated: false,\n                UUID: \"0000024B-0000-1000-8000-0026BB765291\",\n                description: \"Characteristic Value Active Transition Count\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         237: { type: \"CryptoHash\",\n                sche: \"cryptoHash\",\n                characteristic: Characteristic.CryptoHash,\n                deprecated: false,\n                UUID: \"00000250-0000-1000-8000-0026BB765291\",\n                description: \"Crypto Hash\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         238: { type: \"FirmwareUpdateReadiness\",\n                sche: \"firmwareUpdateReadiness\",\n                characteristic: Characteristic.FirmwareUpdateReadiness,\n                deprecated: false,\n                UUID: \"00000234-0000-1000-8000-0026BB765291\",\n                description: \"Firmware Update Readiness\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         239: { type: \"FirmwareUpdateStatus\",\n                sche: \"firmwareUpdateStatus\",\n                characteristic: Characteristic.FirmwareUpdateStatus,\n                deprecated: false,\n                UUID: \"00000235-0000-1000-8000-0026BB765291\",\n                description: \"The Devices firmware update status\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         240: { type: \"HardwareFinish\",\n                sche: \"hardwareFinish\",\n                characteristic: Characteristic.HardwareFinish,\n                deprecated: false,\n                UUID: \"0000026C-0000-1000-8000-0026BB765291\",\n                description: \"Hardware Finish\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         241: { type: \"MetricsBufferFullState\",\n                sche: \"MetricsBufferFullState\",\n                characteristic: Characteristic.MetricsBufferFullState,\n                deprecated: false,\n                UUID: \"00000272-0000-1000-8000-0026BB765291\",\n                description: \"Metrics Buffer Full State\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToBool( str ); },\n                props: {format: hapFormats.BOOL,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         242: { type: \"MultifunctionButton\",\n                sche: \"multiFunctionButton\",\n                characteristic: Characteristic.MultifunctionButton,\n                deprecated: false,\n                UUID: \"0000026B-0000-1000-8000-0026BB765291\",\n                description: \"Multifunction Button\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         243: { type: \"SelectedDiagnosticsModes\",\n                sche: \"selectedDiagnosticsModes\",\n                characteristic: Characteristic.SelectedDiagnosticsModes,\n                deprecated: false,\n                UUID: \"0000024D-0000-1000-8000-0026BB765291\",\n                description: \"Selected Diagnostics Modes\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT32,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         244: { type: \"SelectedSleepConfiguration\",\n                sche: \"selectedSleepConfiguration\",\n                characteristic: Characteristic.SelectedSleepConfiguration,\n                deprecated: false,\n                UUID: \"00000252-0000-1000-8000-0026BB765291\",\n                description: \"Selected Sleep Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE,\n                                hapPerms.WRITE_RESPONSE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         245: { type: \"SiriEnable\",\n                sche: \"siriEnable\",\n                characteristic: Characteristic.SiriEnable,\n                deprecated: false,\n                UUID: \"00000255-0000-1000-8000-0026BB765291\",\n                description: \"Siri Enable\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         246: { type: \"SiriEngineVersion\",\n                sche: \"siriEngineVersion\",\n                characteristic: Characteristic.SiriEngineVersion,\n                deprecated: false,\n                UUID: \"0000025A-0000-1000-8000-0026BB765291\",\n                description: \"Siri's engine version\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         247: { type: \"SiriLightOnUse\",\n                sche: \"siriLightOnUse\",\n                characteristic: Characteristic.SiriLightOnUse,\n                deprecated: false,\n                UUID: \"00000258-0000-1000-8000-0026BB765291\",\n                description: \"Siri Light on Use\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         248: { type: \"SiriListening\",\n                sche: \"siriListening\",\n                characteristic: Characteristic.SiriListening,\n                deprecated: false,\n                UUID: \"00000256-0000-1000-8000-0026BB765291\",\n                description: \"Siri Listening\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         249: { type: \"SiriTouchToUse\",\n                sche: \"siriTouchToUse\",\n                characteristic: Characteristic.SiriTouchToUse,\n                deprecated: false,\n                UUID: \"00000257-0000-1000-8000-0026BB765291\",\n                description: \"Siri Touch to use\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT8,\n                        allowedWordCount: 1,\n                        maxValue: 1,\n                        minValue: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         250: { type: \"StagedFirmwareVersion\",\n                sche: \"StagedFirmwareVersion\",\n                characteristic: Characteristic.StagedFirmwareVersion,\n                deprecated: false,\n                UUID: \"00000249-0000-1000-8000-0026BB765291\",\n                description: \"Staged Firmware Version\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToString( str ); },\n                props: {format: hapFormats.STRING,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.NOTIFY,\n                                hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n               },\n         251: { type: \"SupportedMetrics\",\n                sche: \"supportedMetrics\",\n                characteristic: Characteristic.SupportedMetrics,\n                deprecated: false,\n                UUID: \"00000271-0000-1000-8000-0026BB765291\",\n                description: \"Supported Metrics\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ,\n                                hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         252: { type: \"SupportedFirmwareUpdateConfiguration\",\n                sche: \"supportedFirmwareUpdateConfiguration\",\n                characteristic: Characteristic.SupportedFirmwareUpdateConfiguration,\n                deprecated: false,\n                UUID: \"00000233-0000-1000-8000-0026BB765291\",\n                description: \"Supported Firmware Update Configuration\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToTLV8( str ); },\n                props: {format: hapFormats.TLV8,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         253: { type: \"TapType\",\n                sche: \"tapType\",\n                characteristic: Characteristic.TapType,\n                deprecated: false,\n                UUID: \"0000022F-0000-1000-8000-0026BB765291\",\n                description: \"The devices Tap Type\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringToInt( str ); },\n                props: {format: hapFormats.UINT16,\n                        allowedWordCount: 1,\n                        perms: [hapPerms.PAIRED_READ\n                               ]\n                       },\n                validValues:\n                       { }\n              },\n         254: { type: \"Token\",\n                sche: \"token\",\n                characteristic: Characteristic.Token,\n                deprecated: false,\n                UUID: \"00000231-0000-1000-8000-0026BB765291\",\n                description: \"The devices Token\",\n                relatedCurrentAccTypeEnumIndex: null,\n                relatedTargetAccTypeEnumIndex: null,\n                stringConversionFunction: function ( str ){ return stringPassThru( str ); },\n                props: {format: hapFormats.DATA,\n                        allowedWordCount: 0,\n                        perms: [hapPerms.PAIRED_WRITE\n                               ]\n                       },\n                validValues:\n                       { }\n               }\n      };\n\n      return CMD4_ACC_TYPE_ENUM;\n   }, CMD4_ACC_TYPE_ENUM\n}\n"
  },
  {
    "path": "lib/CMD4_CHAR_TYPE_ENUMS.js",
    "content": "'use strict';\n\nvar CMD4_CHAR_TYPE_ENUMS =\n{\n   CMD4_FORMAT_TYPE_ENUM:\n   {\n      BOOL:                      0,\n      INT:                       1,\n      FLOAT:                     2,\n      STRING:                    3,\n      UINT8:                     4,\n      UINT16:                    5,\n      UINT32:                    6,\n      UINT64:                    7,\n      DATA:                      8,\n      TLV8:                      9,\n      DICTIONARY:                10,\n      EOL:                       11,\n      properties: { }\n   },\n\n   CMD4_UNITS_TYPE_ENUM:\n   {\n      CELSIUS:                   0,\n      PERCENTAGE:                1,\n      ARC_DEGREE:                2,\n      LUX:                       3,\n      SECONDS:                   4,\n      EOL:                       5,\n\n      properties: { }\n   },\n\n   CMD4_PERMS_TYPE_ENUM:\n   {\n      READ:                      0,\n      WRITE:                     1,\n      PAIRED_READ:               2,\n      PAIRED_WRITE:              3,\n      NOTIFY:                    4,\n      ADDITIONAL_AUTHORIZATION:  5,\n      TIMED_WRITE:               6,\n      HIDDEN:                    7,\n      WRITE_RESPONSE:            8,\n      EOL:                       9,\n      properties: { }\n   }\n}\n\n// Export both the init function and the uninitialized data for unit testing\nmodule.exports =\n{\n   init: function ( hapFormats, hapUnits, hapPerms )\n   {\n\n      // Fill in the properties of all possible characteristics\n      // props was added because calling getCharacteridtic().props.perms adds\n      // the characteristic in by default. This costs some lines, but is advantageous.\n      CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.properties =\n      {\n         0: { type: hapFormats.BOOL          // \"bool\"\n            },\n         1: { type: hapFormats.INT           // \"int\"\n            },\n         2: { type: hapFormats.FLOAT         // \"float\"\n            },\n         3: { type: hapFormats.STRING        // \"string\"\n            },\n         4: { type: hapFormats.UINT8         // \"uint8\"\n            },\n         5: { type: hapFormats.UINT16        // \"uint16\"\n            },\n         6: { type: hapFormats.UINT32        // \"uint32\"\n            },\n         7: { type: hapFormats.UINT64        // \"uint64\"\n            },\n         8: { type: hapFormats.DATA          // \"data\"\n            },\n         9: { type: hapFormats.TLV8          // \"tlv8\"\n            },\n        10: { type: hapFormats.ARRAY         // \"array\"\n            },\n        11: { type: hapFormats.DICTIONARY    // \"dict\"\n            }\n      };\n\n      CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.properties =\n      {\n         0: { type: hapUnits.CELSIUS         // \"celsius\"\n            },\n         1: { type: hapUnits.PERCENTAGE      // \"percentage\"\n            },\n         2: { type: hapUnits.ARC_DEGREE      // \"arcdegrees\"\n            },\n         3: { type: hapUnits.LUX             // \"lux\"\n               },\n         4: { type: hapUnits.SECONDS         // \"seconds\"\n            }\n      };\n\n      CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.properties =\n      {\n         0: { type: hapPerms.READ            // \"pr\"\n            },\n         1: { type: hapPerms.WRITE           // \"pw\"\n            },\n         2: { type: hapPerms.PAIRED_READ     // \"pr\"\n            },\n         3: { type: hapPerms.PAIRED_WRITE    // \"pw\"\n            },\n         4: { type: hapPerms.NOTIFY          // \"ev\"\n            },\n         5: { type: hapPerms.EVENTS          // \"ev\"\n            },\n         6: { type: hapPerms.ADDITIONAL_AUTHORIZATION         // \"aa\"\n            },\n         7: { type: hapPerms.TIMED_WRITE     // \"tw\"\n            },\n         8: { type: hapPerms.HIDDEN          // \"hd\"\n            },\n         9: { type: hapPerms.WRITE_RESPONSE  // \"wr\"\n            }\n      };\n\n      return CMD4_CHAR_TYPE_ENUMS;\n\n   }, CMD4_CHAR_TYPE_ENUMS\n}\n\n"
  },
  {
    "path": "lib/CMD4_DEVICE_TYPE_ENUM.js",
    "content": "'use strict';\n\nconst constants = require( \"../cmd4Constants\" );\n\n\n// The sObject.defineProperty is to resolve a lint issue.\n// See utils/indexOfEnumLintTest.js for further information.\nlet indexOfEnum = require( \"../utils/indexOfEnum\" );\nObject.defineProperty( exports, \"indexOfEnum\", { enumerable: true, get: function ( ){ return indexOfEnum.indexOfEnum; } });\n\n\n\nvar CMD4_DEVICE_TYPE_ENUM =\n{\n   AccessControl:                       0,\n   AccessoryRuntimeInformation:         1,\n   AccessoryInformation:                2,\n   AirPurifier:                         3,\n   AirQualitySensor:                    4,\n   BatteryService:                      5,\n   BridgeConfiguration:                 6,\n   BridgingState:                       7,\n   CamaeraEventRecordingManagement:     8,\n   CameraControl:                       9,\n   CameraRTPStreamManagement:           10,\n   CameraOperatingMode:                 11,\n   CarbonDioxideSensor:                 12,\n   CarbonMonoxideSensor:                13,\n   ContactSensor:                       14,\n   Diagnostics:                         15,\n   Door:                                16,\n   DoorBell:                            17,\n   Fan:                                 18,\n   Fanv1:                               19,\n   Fanv2:                               20,\n   Faucet:                              21,\n   FilterMaintenance:                   22,\n   GarageDoorOpener:                    23,\n   HeaterCooler:                        24,\n   HumidifierDehumidifier:              25,\n   HumiditySensor:                      26,\n   InputSource:                         27,\n   IrrigationSystem:                    28,\n   LeakSensor:                          29,\n   LightSensor:                         30,\n   Lightbulb:                           31,\n   LockManagement:                      32,\n   LockMechanism:                       33,\n   Microphone:                          34,\n   MotionSensor:                        35,\n   OccupancySensor:                     36,\n   Outlet:                              37,\n   Pairing:                             38,\n   PowerManagement:                     39,\n   ProtocolInformation:                 40,\n   Relay:                               41,\n   SecuritySystem:                      42,\n   ServiceLabel:                        43,\n   Siri:                                44,\n   Slats:                               45,\n   SmartSpeaker:                        46,\n   SmokeSensor:                         47,\n   Speaker:                             48,\n   StatefulProgrammableSwitch:          49,\n   StatelessProgrammableSwitch:         50,\n   Switch:                              51,\n   TargetControl:                       52,\n   TargetControlManagement:             53,\n   Television:                          54,\n   TelevisionSpeaker:                   55,\n   TemperatureSensor:                   56,\n   Thermostat:                          57,\n   TimeInformation:                     58,\n   TransferTransportManagement:         59,\n   Tunnel:                              60,\n   Valve:                               61,\n   WiFiRouter:                          62,\n   WiFiSatellite:                       63,\n   Window:                              64,\n   WindowCovering:                      65,\n   AccessoryMetrics:                    66,\n   AssetUpdate:                         67,\n   Assistant:                           68,\n   AudioStreamManagement:               69,\n   Battery:                             70,\n   CameraRecordingManagement:           71,\n   CloudRelay:                          72,\n   DataStreamTransportManagement:       73,\n   NFCAccess:                           74,\n   SiriEndpoint:                        75,\n   ThreadTransport:                     76,\n\n   // New Mar 2024\n   AccessCode:                          77,\n   FirmwareUpdate:                      78,\n   TapManagement:                       79,\n   WiFiTransport:                       80,\n\n   EOL:                                 81,\n\n   properties:{},\n\n   devEnumIndexToC: function( index )\n   {\n      return CMD4_DEVICE_TYPE_ENUM.properties[ index ].deviceName;\n   },\n\n   indexOfEnum: function( deviceName )\n   {\n      return CMD4_DEVICE_TYPE_ENUM.properties.indexOfEnum( i => i.deviceName === deviceName );\n   },\n\n\n};\n\n// Export both the init function and the uninitialized data for unit testing\nmodule.exports =\n{\n   init: function ( CMD4_ACC_TYPE_ENUM, Service, Characteristic, Categories )\n   {\n      // Fill in the properties of each device (Must be done at runtime)\n      CMD4_DEVICE_TYPE_ENUM.properties =\n      {\n         0:  { deviceName:'AccessControl',\n               deprecated: false,\n               UUID: \"000000DA-0000-1000-8000-0026BB765291\",\n               service: Service.AccessControl,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.AccessControlLevel,\n                     defaultValue:   0,        // min 0, max 2\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.PasswordSetting\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         1:  { deviceName:'AccessoryRuntimeInformation',\n               deprecated: false,\n               UUID: \"00000239-0000-1000-8000-0026BB765291\",\n               service: Service.AccessoryRuntimeInformation,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Ping,\n                     defaultValue:   0,        // Type is DATA, therefore Who Knows\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ActivityInterval,\n                    CMD4_ACC_TYPE_ENUM.HeartBeat,\n                    CMD4_ACC_TYPE_ENUM.SleepInterval\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         2:  { deviceName:'AccessoryInformation',\n               deprecated: false,\n               UUID: \"0000003E-0000-1000-8000-0026BB765291\",\n               service: Service.AccessoryInformation,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Identify,\n                     defaultValue:   1,                             // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Manufacturer,\n                     defaultValue:   'Cmd4',                       // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Model,\n                     defaultValue:   'Model',                      // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Name,\n                     defaultValue:   'My_AccessoryInformation',\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SerialNumber,\n                     defaultValue:   'ABC001',                   // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.FirmwareRevision,\n                     defaultValue:   '100.1.1',                 // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.HardwareRevision,\n                    CMD4_ACC_TYPE_ENUM.AccessoryFlags\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Identify\n                  ]\n             },\n         3:  { deviceName:'AirPurifier',\n               deprecated: false,\n               UUID: \"000000BB-0000-1000-8000-0026BB765291\",\n               service: Service.AirPurifier,\n               defaultCategory: Categories.AIR_PURIFIER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.SLOW_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentAirPurifierState,\n                     defaultValue:   Characteristic.CurrentAirPurifierState.PURIFYING_AIR,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetAirPurifierState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetAirPurifierState,\n                     defaultValue:   Characteristic.TargetAirPurifierState.AUTO,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentAirPurifierState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.LockPhysicalControls,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.SwingMode,\n                    CMD4_ACC_TYPE_ENUM.RotationSpeed\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         4:  { deviceName:'AirQualitySensor',\n               deprecated: false,\n               UUID: \"0000008D-0000-1000-8000-0026BB765291\",\n               service: Service.AirQualitySensor,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.FAST_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.AirQuality,\n                     defaultValue:   Characteristic.AirQuality.GOOD,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.OzoneDensity,\n                    CMD4_ACC_TYPE_ENUM.NitrogenDioxideDensity,\n                    CMD4_ACC_TYPE_ENUM.SulphurDioxideDensity,\n                    CMD4_ACC_TYPE_ENUM.PM2_5Density,\n                    CMD4_ACC_TYPE_ENUM.PM10Density,\n                    CMD4_ACC_TYPE_ENUM.VOCDensity,\n                    CMD4_ACC_TYPE_ENUM.CarbonMonoxideLevel,\n                    CMD4_ACC_TYPE_ENUM.CarbonDioxideLevel\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.AirQuality\n                  ]\n             },\n         5:  { deviceName:'BatteryService',  // Use Battery instead\n               deprecated: true,\n               UUID: \"00000096-0000-1000-8000-0026BB765291\",\n               //service: Service.Battery,\n               service: null,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ //{type:           CMD4_ACC_TYPE_ENUM.BatteryLevel,\n                    // defaultValue:   50,                             // Range 0-100\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.ChargingState,\n                    // defaultValue:   Characteristic.ChargingState.NOT_CHARGING,\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    // defaultValue:   Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //}\n                  ],\n               optionalCharacteristics:\n                  [ //CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ //CMD4_ACC_TYPE_ENUM.StatusLowBattery\n                  ]\n             },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         6:  { deviceName:'BridgeConfiguration',\n               deprecated: true,\n               UUID: \"000000A1-0000-1000-8000-0026BB765291\",\n               // service: Service.BridgeConfiguration,\n               service: null,\n               // defaultCategory: Categories.BRIDGE,\n               defaultCategory: null,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [\n                    //{type:           CMD4_ACC_TYPE_ENUM.ConfigureBridgedAccessoryStatus,\n                    // defaultValue:   0,                              // Format: TLV8\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //}\n                  ],\n               optionalCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.ConfigureBridgedAccessoryStatus,\n                    //CMD4_ACC_TYPE_ENUM.DiscoverBridgedAccessories,\n                    //CMD4_ACC_TYPE_ENUM.DiscoveredBridgedAccessories,\n                    //CMD4_ACC_TYPE_ENUM.ConfigureBridgedAccessory\n                  ],\n               defaultPollingCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.ConfigureBridgedAccessoryStatus\n                  ]\n             },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         7:  { deviceName:'BridgingState',\n               deprecated: true,\n               UUID: \"00000062-0000-1000-8000-0026BB765291\",\n               // @deprecated Removed and not used anymore as of homebridge v2\n               // service: Service.BridgingState,\n               service: null,\n               // defaultCategory: Categories.BRIDGE,\n               defaultCategory: null,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [\n                    //{type:           CMD4_ACC_TYPE_ENUM.Reachable,\n                    // defaultValue:   1,                           // Format: Bool\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.LinkQuality,\n                    // defaultValue:   1,                              // Format: Uint8\n                                                                     // Range: 1-4, Step: 1\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.AccessoryIdentifier,\n                    // defaultValue:   \"id999\",                        // Format: String\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.Category,\n                    // defaultValue:   16,                             // Format: Uint16\n                                                                     // Range: 1-16, Step 1\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //}\n                  ],\n               optionalCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.Reachable\n                  ]\n             },\n         8:  { deviceName:'CameraEventRecordingManagement', // Use CameraRecordingManagement\n               deprecated: true,\n               UUID: \"00000204-0000-1000-8000-0026BB765291\",\n               //service: Service.CameraRecordingManagement,\n               service: null,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ //{type:           CMD4_ACC_TYPE_ENUM.Active,\n                    // defaultValue:   Characteristic.Active.ACTIVE,\n                    // relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                    // relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.SupportedCameraRecordingConfiguration,\n                    // defaultValue:   0,                              // Format: TLV8\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.SupportedVideoRecordingConfiguration,\n                    // defaultValue:   0,                              // Format: TLV8\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.SupportedAudioRecordingConfiguration,\n                    // defaultValue:   0,                              // Format: TLV8\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.SelectedCameraRecordingConfiguration,\n                    // defaultValue:   0,                              // Format: TLV8\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                  ],\n               optionalCharacteristics:\n                  [ //CMD4_ACC_TYPE_ENUM.RecordingAudioActive\n                  ],\n               defaultPollingCharacteristics:\n                  [ //CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         9:  { deviceName:'CameraControl',\n               deprecated: true,\n               UUID: \"00000111-0000-1000-8000-0026BB765291\",\n               // service: Service.CameraControl,\n               service: null,\n               //defaultCategory: Categories.OTHER,\n               defaultCategory: null,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [\n                    //{type:           CMD4_ACC_TYPE_ENUM.On,\n                    // defaultValue:   1,                           // Format: Bool\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //}\n                  ],\n               optionalCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.CurrentHorizontalTiltAngle,\n                    //CMD4_ACC_TYPE_ENUM.CurrentVerticalTiltAngle,\n                    //CMD4_ACC_TYPE_ENUM.TargetHorizontalTiltAngle,\n                    //CMD4_ACC_TYPE_ENUM.TargetVerticalTiltAngle,\n                    //CMD4_ACC_TYPE_ENUM.NightVision,\n                    //CMD4_ACC_TYPE_ENUM.OpticalZoom,\n                    //CMD4_ACC_TYPE_ENUM.DigitalZoom,\n                    //CMD4_ACC_TYPE_ENUM.ImageRotation,\n                    //CMD4_ACC_TYPE_ENUM.ImageMirroring,\n                    //CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.On\n                  ]\n             },\n         10: { deviceName:'CameraRTPStreamManagement',\n               deprecated: false,\n               UUID: \"00000110-0000-1000-8000-0026BB765291\",\n               service: Service.CameraRTPStreamManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SupportedVideoStreamConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedAudioStreamConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedRTPConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SelectedRTPStreamConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.StreamingStatus,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SetupEndpoints,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [\n                  ]\n             },\n         11: { deviceName:'CameraOperatingMode',\n               deprecated: false,\n               UUID: \"0000021A-0000-1000-8000-0026BB765291\",\n               service: Service.CameraOperatingMode,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.EventSnapshotsActive,\n                     defaultValue:   Characteristic.EventSnapshotsActive.DISABLE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.HomeKitCameraActive,\n                     defaultValue:   Characteristic.HomeKitCameraActive.OFF,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CameraOperatingModeIndicator,\n                    CMD4_ACC_TYPE_ENUM.ManuallyDisabled,\n                    CMD4_ACC_TYPE_ENUM.NightVision,\n                    CMD4_ACC_TYPE_ENUM.PeriodicSnapshotsActive,\n                    CMD4_ACC_TYPE_ENUM.ThirdPartyCameraActive,\n                    CMD4_ACC_TYPE_ENUM.DiagonalFieldOfView\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         12: { deviceName:'CarbonDioxideSensor',\n               deprecated: false,\n               UUID: \"00000097-0000-1000-8000-0026BB765291\",\n               service: Service.CarbonDioxideSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CarbonDioxideDetected,\n                     defaultValue:   Characteristic.CarbonDioxideDetected.CO2_LEVELS_NORMAL,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.CarbonDioxideLevel,\n                    CMD4_ACC_TYPE_ENUM.CarbonDioxidePeakLevel,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CarbonDioxideDetected\n                  ]\n             },\n         13: { deviceName:'CarbonMonoxideSensor',\n               deprecated: false,\n               UUID: \"0000007F-0000-1000-8000-0026BB765291\",\n               service: Service.CarbonMonoxideSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CarbonMonoxideDetected,\n                     defaultValue:   Characteristic.CarbonMonoxideDetected.CO_LEVELS_NORMAL,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.CarbonMonoxideLevel,\n                    CMD4_ACC_TYPE_ENUM.CarbonMonoxidePeakLevel,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CarbonMonoxideDetected\n                  ]\n             },\n         14: { deviceName:'ContactSensor',\n               deprecated: false,\n               UUID: \"00000080-0000-1000-8000-0026BB765291\",\n               service: Service.ContactSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ContactSensorState,\n                     defaultValue:   Characteristic.ContactSensorState.CONTACT_NOT_DETECTED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ContactSensorState\n                  ]\n             },\n         15: { deviceName:'Diagnostics',\n               deprecated: false,\n               UUID: \"00000237-0000-1000-8000-0026BB765291\",\n               service: Service.Diagnostics,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SupportedDiagnosticsSnapshot,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         16: { deviceName:'Door',\n               deprecated: false,\n               UUID: \"00000081-0000-1000-8000-0026BB765291\",\n               service: Service.Door,\n               defaultCategory: Categories.DOOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                     defaultValue:   0,                            // Range 0 - 100\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetPosition ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.PositionState,\n                     defaultValue:   Characteristic.PositionState.STOPPED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetPosition,\n                     defaultValue:   0,                              // Range 0 - 100\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentPosition ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.HoldPosition,\n                    CMD4_ACC_TYPE_ENUM.ObstructionDetected,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                    CMD4_ACC_TYPE_ENUM.TargetPosition\n                  ]\n             },\n         17: { deviceName:'DoorBell',\n               deprecated: false,\n               UUID: \"00000121-0000-1000-8000-0026BB765291\",\n               service: Service.Doorbell,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ProgrammableSwitchEvent,\n                     defaultValue:   Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Brightness,\n                    CMD4_ACC_TYPE_ENUM.Mute,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.Volume,\n                    CMD4_ACC_TYPE_ENUM.OperatingStateResponse\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ProgrammableSwitchEvent\n                  ]\n             },\n         18: { deviceName:'Fan',\n               deprecated: false,\n               UUID: \"00000040-0000-1000-8000-0026BB765291\",\n               service: Service.Fan,\n               defaultCategory: Categories.FAN,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.On,\n                     defaultValue:   0,                          // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.RotationDirection,\n                    CMD4_ACC_TYPE_ENUM.RotationSpeed,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.On\n                  ]\n             },\n         19: { deviceName:'Fanv1',\n               deprecated: false,\n               UUID: \"00000040-0000-1000-8000-0026BB765291\",\n               service: Service.Fan,\n               defaultCategory: Categories.FAN,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.On,\n                     defaultValue:   0,                          // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.RotationDirection,\n                    CMD4_ACC_TYPE_ENUM.RotationSpeed,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.On\n                  ]\n             },\n         20: { deviceName:'Fanv2',\n               deprecated: false,\n               UUID: \"000000B7-0000-1000-8000-0026BB765291\",\n               service: Service.Fanv2,\n               defaultCategory: Categories.FAN,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentFanState,\n                    CMD4_ACC_TYPE_ENUM.TargetFanState,\n                    CMD4_ACC_TYPE_ENUM.LockPhysicalControls,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.RotationDirection,\n                    CMD4_ACC_TYPE_ENUM.RotationSpeed,\n                    CMD4_ACC_TYPE_ENUM.SwingMode\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         21: { deviceName:'Faucet',\n               deprecated: false,\n               UUID: \"000000D7-0000-1000-8000-0026BB765291\",\n               service: Service.Faucet,\n               defaultCategory: Categories.FAUCET,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.StatusFault\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         22: { deviceName:'FilterMaintenance',\n               deprecated: false,\n               UUID: \"000000BA-0000-1000-8000-0026BB765291\",\n               service: Service.FilterMaintenance,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.FilterChangeIndication,\n                     defaultValue:   Characteristic.FilterChangeIndication.FILTER_OK,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.FilterLifeLevel,\n                    CMD4_ACC_TYPE_ENUM.ResetFilterIndication,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.FilterChangeIndication\n                  ]\n             },\n         23: { deviceName:'GarageDoorOpener',\n               deprecated: false,\n               UUID: \"00000041-0000-1000-8000-0026BB765291\",\n               service: Service.GarageDoorOpener,\n               defaultCategory: Categories.GARAGE_DOOR_OPENER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.SLOW_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentDoorState,\n                     defaultValue:   Characteristic.CurrentDoorState.OPEN,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetDoorState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetDoorState,\n                     defaultValue:   Characteristic.TargetDoorState.OPEN,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentDoorState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ObstructionDetected,\n                     defaultValue:   1,                           // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.LockCurrentState,\n                    CMD4_ACC_TYPE_ENUM.LockTargetState,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentDoorState,\n                    CMD4_ACC_TYPE_ENUM.TargetDoorState\n                  ]\n             },\n         24: { deviceName:'HeaterCooler',\n               deprecated: false,\n               UUID: \"000000BC-0000-1000-8000-0026BB765291\",\n               service: Service.HeaterCooler,\n               defaultCategory: Categories.AIR_HEATER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentHeaterCoolerState,\n                     defaultValue:   Characteristic.CurrentHeaterCoolerState.INACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetHeaterCoolerState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetHeaterCoolerState,\n                     defaultValue:   Characteristic.TargetHeaterCoolerState.HEAT,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentHeaterCoolerState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentTemperature,\n                     defaultValue:   22.2,                           // Range:  0 - 100, Step: 0.1\n                                                                     // Format: float\n                                                                     // Units:  CELSIUS\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.LockPhysicalControls,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.RotationSpeed,\n                    CMD4_ACC_TYPE_ENUM.SwingMode,\n                    CMD4_ACC_TYPE_ENUM.CoolingThresholdTemperature,\n                    CMD4_ACC_TYPE_ENUM.HeatingThresholdTemperature,\n                    CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         25: { deviceName:'HumidifierDehumidifier',\n               deprecated: false,\n               UUID: \"000000BD-0000-1000-8000-0026BB765291\",\n               service: Service.HumidifierDehumidifier,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentRelativeHumidity,\n                     defaultValue:   60,                             // Range:  0 - 100, Step: 1\n                                                                     // Format: float\n                                                                     // Units:  CELSIUS\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentHumidifierDehumidifierState,\n                     defaultValue:   Characteristic.CurrentHumidifierDehumidifierState.IDLE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetHumidifierDehumidifierState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetHumidifierDehumidifierState,\n                     defaultValue:   Characteristic.TargetHumidifierDehumidifierState.DEHUMIDIFIER,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentHumidifierDehumidifierState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.LockPhysicalControls,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.RelativeHumidityDehumidifierThreshold,\n                    CMD4_ACC_TYPE_ENUM.RelativeHumidityHumidifierThreshold,\n                    CMD4_ACC_TYPE_ENUM.RotationSpeed,\n                    CMD4_ACC_TYPE_ENUM.SwingMode,\n                    CMD4_ACC_TYPE_ENUM.WaterLevel\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         26: { deviceName:'HumiditySensor',\n               deprecated: false,\n               UUID: \"00000082-0000-1000-8000-0026BB765291\",\n               service: Service.HumiditySensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentRelativeHumidity,\n                     defaultValue:   60,                             // Range:  0 - 100, Step: 1\n                                                                     // Format: float\n                                                                     // Units:  CELSIUS\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentRelativeHumidity\n                  ]\n             },\n         27: { deviceName:'InputSource',\n               deprecated: false,\n               UUID: \"000000D9-0000-1000-8000-0026BB765291\",\n               service: Service.InputSource,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ConfiguredName,\n                     defaultValue:   \"My_InputSource\",               // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.InputSourceType,\n                     defaultValue:   Characteristic.InputSourceType.HOME_SCREEN,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.IsConfigured,\n                     defaultValue:   Characteristic.IsConfigured.CONFIGURED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentVisibilityState,\n                     defaultValue:   Characteristic.CurrentVisibilityState.SHOWN,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Identifier,\n                    CMD4_ACC_TYPE_ENUM.InputDeviceType,\n                    CMD4_ACC_TYPE_ENUM.TargetVisibilityState,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentVisibilityState\n                  ]\n             },\n         28: { deviceName:'IrrigationSystem',\n               deprecated: false,\n               UUID: \"000000CF-0000-1000-8000-0026BB765291\",\n               service: Service.IrrigationSystem,\n               defaultCategory: Categories.SPRINKLER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ProgramMode,\n                      defaultValue:  Characteristic.ProgramMode.NO_PROGRAM_SCHEDULED ,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.InUse,\n                     defaultValue:   Characteristic.InUse.IN_USE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.RemainingDuration,\n                    CMD4_ACC_TYPE_ENUM.StatusFault\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         29: { deviceName:'LeakSensor',\n               deprecated: false,\n               UUID: \"00000083-0000-1000-8000-0026BB765291\",\n               service: Service.LeakSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.LeakDetected,\n                     defaultValue:   Characteristic.LeakDetected.LEAK_NOT_DETECTED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.LeakDetected\n                  ]\n             },\n         30: { deviceName:'LightSensor',\n               deprecated: false,\n               UUID: \"00000084-0000-1000-8000-0026BB765291\",\n               service: Service.LightSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentAmbientLightLevel,\n                     defaultValue:   1,                              // Range:  0.0001 - 100000\n                                                                     // Format: float\n                                                                     // Units:  lux\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentAmbientLightLevel\n                  ]\n             },\n         31: { deviceName:'Lightbulb',\n               deprecated: false,\n               UUID: \"00000043-0000-1000-8000-0026BB765291\",\n               service: Service.Lightbulb,\n               defaultCategory: Categories.LIGHTBULB,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.On,\n                     defaultValue:   0,                          // Format: float\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Brightness,\n                    CMD4_ACC_TYPE_ENUM.Hue,\n                    CMD4_ACC_TYPE_ENUM.Saturation,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.ColorTemperature\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.On\n                  ]\n             },\n         32: { deviceName:'LockManagement',\n               deprecated: false,\n               UUID: \"00000044-0000-1000-8000-0026BB765291\",\n               service: Service.LockManagement,\n               defaultCategory: Categories.ALARM_SYSTEM,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.LockControlPoint,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Version,\n                     defaultValue:   '0.0.0',                        // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [\n                    CMD4_ACC_TYPE_ENUM.AdministratorOnlyAccess,\n                    CMD4_ACC_TYPE_ENUM.AudioFeedback,\n                    CMD4_ACC_TYPE_ENUM.CurrentDoorState,\n                    CMD4_ACC_TYPE_ENUM.LockManagementAutoSecurityTimeout,\n                    CMD4_ACC_TYPE_ENUM.LockLastKnownAction,\n                    CMD4_ACC_TYPE_ENUM.Logs,\n                    CMD4_ACC_TYPE_ENUM.MotionDetected,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [\n                  ]\n             },\n         33: { deviceName:'LockMechanism',\n               deprecated: false,\n               UUID: \"00000045-0000-1000-8000-0026BB765291\",\n               service: Service.LockMechanism,\n               defaultCategory: Categories.DOOR_LOCK,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.LockCurrentState,\n                     defaultValue:   Characteristic.LockCurrentState.UNSECURED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.LockTargetState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.LockTargetState,\n                     defaultValue:   Characteristic.LockTargetState.UNSECURED,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.LockCurrentState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.LockCurrentState,\n                    CMD4_ACC_TYPE_ENUM.LockTargetState\n                  ]\n             },\n         34: { deviceName:'Microphone',\n               deprecated: false,\n               UUID: \"00000112-0000-1000-8000-0026BB765291\",\n               service: Service.Microphone,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Mute,\n                     defaultValue:   0,                          // Format: Bool,\n                                                                 // 0 - Mute is off\n                                                                 // 1 - Mute is on\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Volume,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Mute\n                  ]\n             },\n         35: { deviceName:'MotionSensor',\n               deprecated: false,\n               UUID: \"00000085-0000-1000-8000-0026BB765291\",\n               service: Service.MotionSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.MotionDetected,\n                     defaultValue:   1,                           // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.MotionDetected\n                  ]\n             },\n         36: { deviceName:'OccupancySensor',\n               deprecated: false,\n               UUID: \"00000086-0000-1000-8000-0026BB765291\",\n               service: Service.OccupancySensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.OccupancyDetected,\n                     defaultValue:   Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.OccupancyDetected\n                  ]\n             },\n         37: { deviceName:'Outlet',\n               deprecated: false,\n               UUID: \"00000047-0000-1000-8000-0026BB765291\",\n               service: Service.Outlet,\n               defaultCategory: Categories.OUTLET,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.On,\n                     defaultValue:   0,                          // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.OutletInUse,\n                     defaultValue:   0,                          // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.On\n                  ]\n             },\n         38: { deviceName:'Pairing',\n               deprecated: false,\n               UUID: \"00000055-0000-1000-8000-0026BB765291\",\n               service: Service.Pairing,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ListPairings,\n                     defaultValue:   1,                              // Format: Uint8. Values ???\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.PairSetup,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.PairVerify,\n                     defaultValue:   0,                              // Format: Uint8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.PairingFeatures,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.PairingFeatures\n                  ]\n             },\n         39: { deviceName:'PowerManagement',\n               deprecated: false,\n               UUID: \"00000221-0000-1000-8000-0026BB765291\",\n               service: Service.PowerManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.WakeConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         40: { deviceName:'ProtocolInformation',\n               deprecated: false,\n               UUID: \"000000A2-0000-1000-8000-0026BB765291\",\n               service: Service.ProtocolInformation,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Version,\n                     defaultValue:   '1.2.3',                      // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Version\n                  ]\n             },\n         41: { deviceName:'Relay', // Use CloudRelay\n               deprecated: true,\n               UUID: \"0000005A-0000-1000-8000-0026BB765291\",\n               //service: Service.CloudRelay,\n               service: null ,\n               defaultCategory: Categories.SWITCH,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ //{type:           CMD4_ACC_TYPE_ENUM.RelayEnabled,\n                    // defaultValue:   1,                           // Format: Bool\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.RelayState,\n                    // defaultValue:   1,                              // Format: uint8, Values ???\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.RelayControlPoint,\n                    // defaultValue:   0,                              // Format: TLV8\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //}\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  [ //CMD4_ACC_TYPE_ENUM.RelayEnabled,\n                    //CMD4_ACC_TYPE_ENUM.RelayState,\n                  ]\n             },\n         42: { deviceName:'SecuritySystem',\n               deprecated: false,\n               UUID: \"0000007E-0000-1000-8000-0026BB765291\",\n               service: Service.SecuritySystem,\n               defaultCategory: Categories.SECURITY_SYSTEM,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SecuritySystemCurrentState,\n                     defaultValue:   Characteristic.SecuritySystemCurrentState.DISARMED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.SecuritySystemTargetState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SecuritySystemTargetState,\n                     defaultValue:   Characteristic.SecuritySystemTargetState.DISARM,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.SecuritySystemCurrentState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.SecuritySystemAlarmType,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.SecuritySystemCurrentState,\n                    CMD4_ACC_TYPE_ENUM.SecuritySystemTargetState\n                  ]\n             },\n         43: { deviceName:'ServiceLabel',\n               deprecated: false,\n               UUID: \"000000CC-0000-1000-8000-0026BB765291\",\n               service: Service.ServiceLabel,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ServiceLabelNamespace,\n                     defaultValue:   Characteristic.ServiceLabelNamespace.DOTS,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ServiceLabelNamespace\n                  ]\n             },\n         44: { deviceName:'Siri',\n               deprecated: false,\n               UUID: \"00000133-0000-1000-8000-0026BB765291\",\n               service: Service.Siri,\n               defaultCategory: Categories.HOMEPOD,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SiriInputType,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.MultifunctionButton,\n                    CMD4_ACC_TYPE_ENUM.SiriEnable,\n                    CMD4_ACC_TYPE_ENUM.SiriEngineVersion,\n                    CMD4_ACC_TYPE_ENUM.SiriLightOnUse,\n                    CMD4_ACC_TYPE_ENUM.SiriListening,\n                    CMD4_ACC_TYPE_ENUM.SiriTouchToUse\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         45: { deviceName:'Slats',\n               deprecated: false,\n               UUID: \"000000B9-0000-1000-8000-0026BB765291\",\n               service: Service.Slats,\n               defaultCategory: Categories.WINDOW_COVERING,\n               publishExternally: false,\n               devicesStateChangeDefaultTimeb: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentSlatState,\n                     defaultValue:   Characteristic.CurrentSlatState.FIXED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SlatType,\n                     defaultValue:   Characteristic.SlatType.HORIZONTAL,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.SwingMode,\n                    CMD4_ACC_TYPE_ENUM.CurrentTiltAngle,\n                    CMD4_ACC_TYPE_ENUM.TargetTiltAngle\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentSlatState\n                  ]\n             },\n         46: { deviceName:'SmartSpeaker',\n               deprecated: false,\n               UUID: \"00000228-0000-1000-8000-0026BB765291\",\n               service: Service.SmartSpeaker,\n               defaultCategory: Categories.HOMEPOD,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentMediaState,\n                     defaultValue:   Characteristic.CurrentMediaState.STOP,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetMediaState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetMediaState,\n                     defaultValue:   Characteristic.CurrentMediaState.STOP,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentMediaState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.AirPlayEnable,\n                    CMD4_ACC_TYPE_ENUM.ConfiguredName,\n                    CMD4_ACC_TYPE_ENUM.Mute,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.Volume\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         47: { deviceName:'SmokeSensor',\n               deprecated: false,\n               UUID: \"00000087-0000-1000-8000-0026BB765291\",\n               service: Service.SmokeSensor,\n               defaultCategory: Categories.SENSOR,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SmokeDetected,\n                     defaultValue:   Characteristic.SmokeDetected.SMOKE_NOT_DETECTED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.SmokeDetected\n                  ]\n             },\n         48: { deviceName:'Speaker',\n               deprecated: false,\n               UUID: \"00000113-0000-1000-8000-0026BB765291\",\n               service: Service.Speaker,\n               defaultCategory: Categories.SPEAKER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Mute,\n                     defaultValue:   0,                           // Format: Bool\n                                                                  // 0 - Mute is off\n                                                                  // 1 - Mute is on\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active,\n                    CMD4_ACC_TYPE_ENUM.Volume,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Mute\n                  ]\n             },\n         49: { deviceName:'StatefulProgrammableSwitch',\n               deprecated: false,\n               UUID: \"00000088-0000-1000-8000-0026BB765291\",\n               service: Service.StatefulProgrammableSwitch,\n               defaultCategory: Categories.SWITCH,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ProgrammableSwitchEvent,\n                     defaultValue:   Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ProgrammableSwitchOutputState,\n                     defaultValue:   0,                              // Range: 0 - 1. Step: 1\n                                                                     // Format: Uint8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ProgrammableSwitchEvent\n                  ]\n             },\n         50: { deviceName:'StatelessProgrammableSwitch',\n               deprecated: false,\n               UUID: \"00000089-0000-1000-8000-0026BB765291\",\n               service: Service.StatelessProgrammableSwitch,\n               defaultCategory: Categories.SWITCH,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ProgrammableSwitchEvent,\n                     defaultValue:   Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.ServiceLabelIndex\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ProgrammableSwitchEvent\n                  ]\n             },\n         51: { deviceName:'Switch',\n               deprecated: false,\n               UUID: \"00000049-0000-1000-8000-0026BB765291\",\n               service: Service.Switch,\n               defaultCategory: Categories.SWITCH,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.FAST_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.On,\n                     defaultValue:   0,                          // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.On\n                  ]\n             },\n         52: { deviceName:'TargetControl',\n               deprecated: false,\n               UUID: \"00000125-0000-1000-8000-0026BB765291\",\n               service: Service.TargetControl,\n               defaultCategory: Categories.TARGET_CONTROLLER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [\n                    {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ActiveIdentifier,\n                     defaultValue:   7,                              // Format: UINT32\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ButtonEvent,\n                     defaultValue:   0,     // TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         53: { deviceName:'TargetControlManagement',\n               deprecated: false,\n               UUID: \"00000122-0000-1000-8000-0026BB765291\",\n               service: Service.TargetControlManagement,\n               defaultCategory: Categories.TARGET_CONTROLLER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.TargetControlSupportedConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetControlList,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ] \n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         54: { deviceName:'Television',\n               deprecated: false,\n               UUID: \"000000D8-0000-1000-8000-0026BB765291\",\n               service: Service.Television,\n               defaultCategory: Categories.TELEVISION,\n               publishExternally: true,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ActiveIdentifier,\n                     defaultValue:   123,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },                                              // Format: Uint32\n                    {type:           CMD4_ACC_TYPE_ENUM.ConfiguredName,\n                     defaultValue:   'My_Tv',\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },                                              // Format: String\n                    {type:           CMD4_ACC_TYPE_ENUM.RemoteKey,\n                     defaultValue:   Characteristic.RemoteKey.SELECT,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },                                             // Format: uint8\n                    {type:           CMD4_ACC_TYPE_ENUM.SleepDiscoveryMode,\n                     defaultValue:   Characteristic.SleepDiscoveryMode.ALWAYS_DISCOVERABLE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Brightness,\n                    CMD4_ACC_TYPE_ENUM.ClosedCaptions,\n                    CMD4_ACC_TYPE_ENUM.DisplayOrder,\n                    CMD4_ACC_TYPE_ENUM.CurrentMediaState,\n                    CMD4_ACC_TYPE_ENUM.TargetMediaState,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.PictureMode,\n                    CMD4_ACC_TYPE_ENUM.PowerModeSelection\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         55: { deviceName:'TelevisionSpeaker',\n               deprecated: false,\n               UUID: \"00000113-0000-1000-8000-0026BB765291\",\n               service: Service.TelevisionSpeaker,\n               defaultCategory: Categories.AUDIO_RECEIVER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Mute,\n                     defaultValue:   0,                          // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active,\n                    CMD4_ACC_TYPE_ENUM.Volume,\n                    CMD4_ACC_TYPE_ENUM.VolumeControlType,\n                    CMD4_ACC_TYPE_ENUM.VolumeSelector,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Mute\n                  ]\n             },\n         56: { deviceName:'TemperatureSensor',\n               deprecated: false,\n               UUID: \"0000008A-0000-1000-8000-0026BB765291\",\n               service: Service.TemperatureSensor,\n               defaultCategory: Categories.SWITCH,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentTemperature,\n                     defaultValue:   50.0,                        // Range:  0 - 100\n                                                                  // Step: 0.1\n                                                                  // Format: float\n                                                                  // Units:  CELSIUS\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.StatusActive,\n                    CMD4_ACC_TYPE_ENUM.StatusFault,\n                    CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                    CMD4_ACC_TYPE_ENUM.StatusTampered\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentTemperature\n                  ]\n             },\n         57: { deviceName:'Thermostat',\n               deprecated: false,\n               UUID: \"0000004A-0000-1000-8000-0026BB765291\",\n               service: Service.Thermostat,\n               defaultCategory: Categories.THERMOSTAT,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentHeatingCoolingState,\n                     defaultValue:   Characteristic.CurrentHeatingCoolingState.OFF,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetHeatingCoolingState ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetHeatingCoolingState,\n                     defaultValue:   Characteristic.TargetHeatingCoolingState.OFF,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentHeatingCoolingState ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CurrentTemperature,\n                     defaultValue:   50.0,                       // Range:  0 - 100, Step: 0.1\n                                                                 // Format: float\n                                                                 // Units:  CELSIUS\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetTemperature ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetTemperature,\n                     defaultValue:   50.0,                        // Range:  0 - 100\n                                                                  // Step: 0.1\n                                                                  // Format: float\n                                                                  // Units:  CELSIUS\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentTemperature ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits,\n                     defaultValue:   Characteristic.TemperatureDisplayUnits.CELSIUS,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.CurrentRelativeHumidity,\n                    CMD4_ACC_TYPE_ENUM.TargetRelativeHumidity,\n                    CMD4_ACC_TYPE_ENUM.CoolingThresholdTemperature,\n                    CMD4_ACC_TYPE_ENUM.HeatingThresholdTemperature\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentTemperature,\n                    CMD4_ACC_TYPE_ENUM.TargetTemperature\n                  ]\n             },\n         // @deprecated Removed and not used anymore as of homebridge v2\n         58: { deviceName:'TimeInformation',\n               deprecated: true,\n               UUID: \"00000099-0000-1000-8000-0026BB765291\",\n               //service: Service.TimeInformation,\n               service: null,\n               //defaultCategory: Categories.OTHER,\n               defaultCategory: null,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [\n                    //{type:           CMD4_ACC_TYPE_ENUM.CurrentTime,\n                    // defaultValue:   '11:15',                      // Format: String\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.DayoftheWeek,\n                    // defaultValue:   1,                           // Range:  1 - 7\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //},\n                    //{type:           CMD4_ACC_TYPE_ENUM.TimeUpdate,\n                    // defaultValue:   0,                          // Format: Bool\n                    // relatedCurrentAccTypeEnumArray: [ ],\n                    // relatedTargetAccTypeEnumArray: [ ]\n                    //}\n                  ],\n               optionalCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  [\n                    //CMD4_ACC_TYPE_ENUM.CurrentTime\n                  ]\n             },\n         59: { deviceName:'TransferTransportManagement',\n               deprecated: false,\n               UUID: \"00000203-0000-1000-8000-0026BB765291\",\n               service: Service.TransferTransportManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SupportedTransferTransportConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SetupTransferTransport,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         60: { deviceName:'Tunnel',\n               deprecated: false,\n               UUID: \"00000056-0000-1000-8000-0026BB765291\",\n               service: Service.Tunnel,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Name,\n                     defaultValue:  'My_TunnelB',                  // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.AccessoryIdentifier,\n                     defaultValue:  'TLB',                        // Format: String\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TunneledAccessoryStateNumber,\n                     defaultValue:   0.0,                        // Format: float\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ] },\n                    {type:           CMD4_ACC_TYPE_ENUM.TunneledAccessoryConnected,\n                     defaultValue:   0,                         // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ] },\n                    {type:           CMD4_ACC_TYPE_ENUM.TunneledAccessoryAdvertising,\n                     defaultValue:   0,                         // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TunnelConnectionTimeout,\n                     defaultValue:   5000,                     // Format: Uint32\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.TunneledAccessoryConnected\n                  ]\n             },\n         61: { deviceName:'Valve',\n               deprecated: false,\n               UUID: \"000000D0-0000-1000-8000-0026BB765291\",\n               service: Service.Valve,\n               defaultCategory: Categories.FAUCET,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.InUse,\n                     defaultValue:   Characteristic.InUse.IN_USE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ValveType,\n                     defaultValue:   Characteristic.ValveType.GENERIC_VALVE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.IsConfigured,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.RemainingDuration,\n                    CMD4_ACC_TYPE_ENUM.ServiceLabelIndex,\n                    CMD4_ACC_TYPE_ENUM.SetDuration,\n                    CMD4_ACC_TYPE_ENUM.StatusFault\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active\n                  ]\n             },\n         62: { deviceName:'WiFiRouter',\n               deprecated: false,\n               UUID: \"0000020A-0000-1000-8000-0026BB765291\",\n               service: Service.WiFiRouter,\n               defaultCategory: Categories.AIRPORT,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ConfiguredName,\n                     defaultValue:   \"My_WiFiRouter\",\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ManagedNetworkEnable,\n                     defaultValue:   0,                              // DISABLE\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.NetworkAccessViolationControl,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.NetworkClientProfileControl,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.NetworkClientStatusControl,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.RouterStatus,\n                     defaultValue:   0,                              // READY\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedRouterConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.WANConfigurationList,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.WANStatusList,\n                     defaultValue:   0,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         63: { deviceName:'WiFiSatellite',\n               deprecated: false,\n               UUID: \"0000020F-0000-1000-8000-0026BB765291\",\n               service: Service.WiFiSatellite,\n               defaultCategory: Categories.TV_SET_TOP_BOX,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:            CMD4_ACC_TYPE_ENUM.WiFiSatelliteStatus,\n                     defaultValue:    2,                    // NOT_CONNECTED\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ // None\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         64: { deviceName:'Window',\n               deprecated: false,\n               UUID: \"0000008B-0000-1000-8000-0026BB765291\",\n               service: Service.Window,\n               defaultCategory: Categories.WINDOW,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                     defaultValue:   0,                          // Range: 0 - 100\n                                                                 // Step: 1\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetPosition ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.PositionState,\n                     defaultValue:  Characteristic.PositionState.STOPPED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetPosition,\n                     defaultValue:   0,                           // Range: 0 - 100\n                                                                  // Step: 1\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentPosition ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.ObstructionDetected,\n                    CMD4_ACC_TYPE_ENUM.HoldPosition\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                    CMD4_ACC_TYPE_ENUM.TargetPosition\n                  ]\n             },\n         65: { deviceName:'WindowCovering',\n               deprecated: false,\n               UUID: \"0000008C-0000-1000-8000-0026BB765291\",\n               service: Service.WindowCovering,\n               defaultCategory: Categories.WINDOW_COVERING,\n               publishExternally: false,\n               devicesStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                     defaultValue:   0,                           // Range: 0 - 100\n                                                                  // Step: 1\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.TargetPosition ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.PositionState,\n                     defaultValue:  Characteristic.PositionState.STOPPED,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TargetPosition,\n                     defaultValue:   0,                           // Range: 0 - 100\n                                                                  // Step: 1\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.CurrentPosition ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentHorizontalTiltAngle,\n                    CMD4_ACC_TYPE_ENUM.TargetHorizontalTiltAngle,\n                    CMD4_ACC_TYPE_ENUM.Name,\n                    CMD4_ACC_TYPE_ENUM.ObstructionDetected,\n                    CMD4_ACC_TYPE_ENUM.HoldPosition,\n                    CMD4_ACC_TYPE_ENUM.CurrentVerticalTiltAngle,\n                    CMD4_ACC_TYPE_ENUM.TargetVerticalTiltAngle\n                  ],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CurrentPosition,\n                    CMD4_ACC_TYPE_ENUM.TargetPosition\n                  ]\n             },\n         66: { deviceName:'AccessoryMetrics',\n               deprecated: false,\n               UUID: \"00000270-0000-1000-8000-0026BB765291\",\n               service: Service.AccessoryMetrics,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.MetricsBufferFullState,\n                     defaultValue:   1,                             // Format: Bool\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedMetrics,\n                     defaultValue:   \"\",                           // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.Active ]\n             },\n         67: { deviceName:'AssetUpdate',\n               deprecated: false,\n               UUID: \"00000267-0000-1000-8000-0026BB765291\",\n               service: Service.AssetUpdate,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.AssetUpdateReadiness,\n                     defaultValue:   0,        // Int\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedAssetTypes,\n                     defaultValue:   0,        // UINT32\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         68: { deviceName:'Assistant',\n               deprecated: false,\n               UUID: \"0000026A-0000-1000-8000-0026BB765291\",\n               service: Service.Assistant,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Identifier,\n                     defaultValue:   \"Some Identifier\",               // Format: STRING\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Name,\n                     defaultValue:   \"Unnamed Assistant\",\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         69: { deviceName:'AudioStreamManagement',\n               deprecated: false,\n               UUID: \"00000127-0000-1000-8000-0026BB765291\",\n               service: Service.AudioStreamManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SupportedAudioStreamConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SelectedAudioStreamConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         70: { deviceName:'Battery',\n               deprecated: false,\n               UUID: \"00000096-0000-1000-8000-0026BB765291\",\n               service: Service.Battery,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.StatusLowBattery,\n                     defaultValue:   Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.BatteryLevel,\n                    CMD4_ACC_TYPE_ENUM.ChargingState,\n                    CMD4_ACC_TYPE_ENUM.Name\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         71: { deviceName:'CameraRecordingManagement',\n               deprecated: false,\n               UUID: \"00000204-0000-1000-8000-0026BB765291\",\n               service: Service.CameraRecordingManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedCameraRecordingConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedVideoRecordingConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedAudioRecordingConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SelectedCameraRecordingConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.RecordingAudioActive\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         72: { deviceName:'CloudRelay',\n               deprecated: false,\n               UUID: \"0000005A-0000-1000-8000-0026BB765291\",\n               service: Service.CloudRelay,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.RelayControlPoint,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.RelayState,\n                     defaultValue:   1,                              // Format: uint8, Values ???\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.RelayEnabled,\n                     defaultValue:   false,\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         73: { deviceName:'DataStreamTransportManagement',\n               deprecated: false,\n               UUID: \"00000129-0000-1000-8000-0026BB765291\",\n               service: Service.DataStreamTransportManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SetupDataStreamTransport,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.SupportedDataStreamTransportConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Version,\n                     defaultValue:   \"Unknown version\",\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         74: { deviceName:'NFCAccess',\n               deprecated: false,\n               UUID: \"00000266-0000-1000-8000-0026BB765291\",\n               service: Service.NFCAccess,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.ConfigurationState,\n                     defaultValue:   0,                              // Format: UINT16 values?\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.NFCAccessControlPoint,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.NFCAccessSupportedConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         75: { deviceName:'SiriEndpoint',\n               deprecated: false,\n               UUID: \"00000253-0000-1000-8000-0026BB765291\",\n               service: Service.SiriEndpoint,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.SiriEndpointSessionStatus,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Version,\n                     defaultValue:   \"Unknown version\",\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.ActiveIdentifier,\n                    CMD4_ACC_TYPE_ENUM.ManuallyDisabled\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         76: { deviceName:'ThreadTransport',\n               deprecated: false,\n               UUID: \"00000701-0000-1000-8000-0026BB765291\",\n               service: Service.ThreadTransport,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentTransport,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ThreadControlPoint,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ThreadNodeCapabilities,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ThreadStatus,\n                     defaultValue:   0,        // min 0, max 6 values?\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [ CMD4_ACC_TYPE_ENUM.CCAEnergyDetectThreshold,\n                    CMD4_ACC_TYPE_ENUM.CCASignalDetectThreshold,\n                    CMD4_ACC_TYPE_ENUM.EventRetransmissionMaximum,\n                    CMD4_ACC_TYPE_ENUM.EventTransmissionCounters,\n                    CMD4_ACC_TYPE_ENUM.MACRetransmissionMaximum,\n                    CMD4_ACC_TYPE_ENUM.MACTransmissionCounters,\n                    CMD4_ACC_TYPE_ENUM.ReceiverSensitivity,\n                    CMD4_ACC_TYPE_ENUM.ReceivedSignalStrengthIndication,\n                    CMD4_ACC_TYPE_ENUM.SignalToNoiseRatio,\n                    CMD4_ACC_TYPE_ENUM.ThreadOpenThreadVersion,\n                    CMD4_ACC_TYPE_ENUM.TransmitPower,\n                    CMD4_ACC_TYPE_ENUM.MaximumTransmitPower\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n\n             // New Mar 2024\n         77: { deviceName:'AccessCode',\n               deprecated: false,\n               UUID: \"00000260-0000-1000-8000-0026BB765291\",\n               service: Service.AccessCode,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.AccessCodeControlPoint,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.AccessCodeSupportedConfiguration,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.ConfigurationState,\n                     defaultValue:   0,                              // Format: Uint16\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         78: { deviceName:'FirmwareUpdate',\n               deprecated: false,\n               UUID: \"00000236-0000-1000-8000-0026BB765291\",\n               service: Service.FirmwareUpdate,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.FirmwareUpdateReadiness,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.FirmwareUpdateStatus,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [CMD4_ACC_TYPE_ENUM.StagedFirmwareVersion,\n                   CMD4_ACC_TYPE_ENUM.SupportedFirmwareUpdateConfiguration\n                  ],\n               defaultPollingCharacteristics:\n                  []\n             },\n         79: { deviceName:'TapManagement',\n               deprecated: false,\n               UUID: \"0000022E-0000-1000-8000-0026BB765291\",\n               service: Service.TapManagement,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.Active,\n                     defaultValue:   Characteristic.Active.ACTIVE,\n                     relatedCurrentAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ],\n                     relatedTargetAccTypeEnumArray: [ CMD4_ACC_TYPE_ENUM.Active ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.CryptoHash,\n                     defaultValue:   0,                 // Format TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.TapType,\n                     defaultValue:   0,                 // Format UINT16\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.Token,\n                     defaultValue:   \"\",                // Format DATA\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [],\n               defaultPollingCharacteristics:\n                  []\n             },\n         80: { deviceName:'WiFiTransport',\n               deprecated: false,\n               UUID: \"0000022A-0000-1000-8000-0026BB765291\",\n               service: Service.WiFiTransport,\n               defaultCategory: Categories.OTHER,\n               publishExternally: false,\n               deviceStateChangeDefaultTime: constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME,\n               requiredCharacteristics:\n                  [ {type:           CMD4_ACC_TYPE_ENUM.CurrentTransport,\n                     defaultValue:   0,                              // Format: TLV8\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    },\n                    {type:           CMD4_ACC_TYPE_ENUM.WiFiCapabilities,\n                     defaultValue:   0,                              // Format: UINT32\n                     relatedCurrentAccTypeEnumArray: [ ],\n                     relatedTargetAccTypeEnumArray: [ ]\n                    }\n                  ],\n               optionalCharacteristics:\n                  [CMD4_ACC_TYPE_ENUM.WiFiConfigurationControl],\n               defaultPollingCharacteristics:\n                  []\n             }\n      };\n\n      return CMD4_DEVICE_TYPE_ENUM;\n   }, CMD4_DEVICE_TYPE_ENUM\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n   \"name\": \"homebridge-cmd4\",\n   \"description\": \"Exec Plugin for Homebridge supporting all accessorys and characteristics\",\n   \"version\": \"8.0.4\",\n   \"license\": \"MIT\",\n   \"author\": {\n      \"name\": \"John Talbot\"\n   },\n   \"repository\": {\n      \"type\": \"git\",\n      \"url\": \"git://github.com/ztalbot2000/homebridge-cmd4.git\"\n   },\n   \"homepage\": \"https://github.com/ztalbot2000/homebridge-cmd4#readme\",\n   \"changelog\": \"https://github.com/ztalbot2000/homebridge-cmd4/blob/master/ChangeLog.md\",\n   \"bugs\": {\n      \"url\": \"https://github.com/ztalbot2000/homebridge-cmd4/issues\",\n      \"email\": \"ztalbot2000@gmail.com\"\n   },\n   \"dependencies\": {\n      \"chalk\": \"^4.1.0\",\n      \"command-exists\": \"^1.2.9\",\n      \"fakegato-history\": \">=0.6.5\",\n      \"latest-version\": \"^5.1.0\",\n      \"moment\": \"*\"\n   },\n   \"devDependencies\": {\n      \"@commitlint/cli\": \"^11.0.0\",\n      \"@commitlint/config-conventional\": \"^11.0.0\",\n      \"chai\": \"^4.2.0\",\n      \"commander\": \"^8.2.0\",\n      \"commitlint-plugin-function-rules\": \"^1.1.20\",\n      \"eslint\": \"^7.17.0\",\n      \"generate-changelog\": \"^1.8.0\",\n      \"husky\": \"^4.3.8\",\n      \"link-checker\": \"^1.4.2\",\n      \"markdown-link-check\": \"^3.8.6\",\n      \"mocha\": \"^8.0.1\",\n      \"node-persist\": \"^0.0.11\",\n      \"sinon\": \"^9.2.4\",\n      \"which\": \"^2.0.2\"\n   },\n   \"directories\": {\n      \"test\": \"test\",\n      \"lib\": \"lib\",\n      \"utils\": \"utils\",\n      \"docs\": \"docs\"\n   },\n   \"engines\": {\n      \"node\": \"^18.20.4 || ^20.18.0 || ^22.10.0 || ^24.0.0\",\n      \"homebridge\": \"^1.8.0 || ^2.0.0-beta.0\"\n   },\n   \"keywords\": [\n      \"homebridge-plugin\",\n      \"homebridge\",\n      \"exec\",\n      \"command\",\n      \"switch\",\n      \"light\",\n      \"door\",\n      \"thermostat\",\n      \"security\",\n      \"temperature\",\n      \"virtual\",\n      \"Eve\",\n      \"Homekit\",\n      \"siri\",\n      \"home\",\n      \"Eve\"\n   ],\n   \"husky\": {\n      \"hooks\": {\n         \"pre-commit\": \"npm run lint && npm run test test/cmd4Constants\",\n         \"commit-msg\": \"commitlint -E HUSKY_GIT_PARAMS\"\n      }\n   },\n   \"scripts\": {\n      \"debug\": \"DEBUG=* homebridge --debug --plugin-path .\",\n      \"pretest\": \"printf ' test is only done in a development environment\\n';sleep 2 \",\n      \"testDebug\": \"node_modules/.bin/mocha --require async-dump.js --file test/mocha-setup --ignore test/versionChecker.js\",\n      \"test\": \"node_modules/.bin/mocha --file test/mocha-setup --ignore test/versionChecker.js\",\n      \"singleTest\": \"node_modules/.bin/mocha --bail --file test/mocha-setup --ignore test/versionChecker.js\",\n      \"allTests\": \"node_modules/.bin/mocha --bail --file test/mocha-setup $( cat test/allTests )\",\n      \"sanityTests\": \"node_modules/.bin/mocha --bail --file test/mocha-setup $( cat test/sanityTests )\",\n      \"_Note0\": \"Excluded from commit as may fail for probing GitHub to much\",\n      \"testMarkDown\": \"markdown-link-check ./README.md && markdown-link-check ./CHANGELOG.md && markdown-link-check ./docs/AdvancedTroubleShooting.md && markdown-link-check ./docs/Developers.md\",\n      \"testAutoGeneratedDocLinks\": \"link-checker docs/autoGenerated/CMD4_AccessoryDescriptions.html\",\n      \"commitTests\": \"npm run test && npm run testMarkDown\",\n      \"_Note\": \"Excluded only because they sometimes fail, but pass alone.    \",\n      \"testCmd4Accessory\": \"node_modules/.bin/mocha --file test/mocha-setup test/Cmd4Accessory.js\",\n      \"testVersionChecker\": \"node_modules/.bin/mocha --file test/mocha-setup test/versionChecker.js\",\n      \"lint\": \"eslint --ext .js *.js utils/*.js lib/*.js tools/* test/*.js\",\n      \"postinstall\": \"node postinstall.js\",\n      \"_Note01\": \"Auto change the version based on the commit history.        \",\n      \"_Note02\": \"Where:                                                      \",\n      \"_Note03\": \"To trigger a version update                                 \",\n      \"_Note04\": \"    npm run release                                         \",\n      \"_Note05\": \"                                                            \",\n      \"_Note06\": \"To trigger a patch update (1.0.0 → 1.0.1)                   \",\n      \"_Note07\": \"    git commit -m 'fix: …'                                  \",\n      \"_Note08\": \"To trigger a minor update (1.0.0 → 1.1.0)                   \",\n      \"_Note09\": \"    git commit -m 'feat: …'                                 \",\n      \"_Note10\": \"To trigger a major update (1.0.0 → 2.0.0)                   \",\n      \"_Note11\": \"    A BREAKING CHANGE: in the commit body                   \",\n      \"_Note12\": \"                                                            \",\n      \"_Note13\": \"As a summary, generate-changelog will do                    \",\n      \"_Note14\": \"   * Bumps the version in package.json                      \",\n      \"_Note15\": \"   * Updates CHANGELOG.md                                   \",\n      \"_Note16\": \"                                                            \",\n      \"release\": \"tools/generateChangeLog\",\n      \"_Note17\": \"                                                            \",\n      \"_Note18\": \"Overide default behaviour with:                             \",\n      \"release:patch\": \"tools/generateChangeLog --type patch --cleanup\",\n      \"release:minor\": \"tools/generateChangeLog --type minor --cleanup\",\n      \"release:major\": \"tools/generateChangeLog --type major --cleanup\"\n   }\n}"
  },
  {
    "path": "postinstall.js",
    "content": "// Post install notes\n\n\n// Fun colour stuff\nconst chalk = require( \"chalk\" );\n\nconst myPkg = require( \"./package.json\" );\n\nconst { isUpgrade }  = require( \"./utils/versionChecker\" );\n\n// To use await you must be in an async function, so put it in one.\n( async( ) =>\n{\n      // Wait for the Promise of isUpgrade to complete.\n      let lv = await isUpgrade( );\n\n      if ( lv == true )\n      {\n         console.log( chalk.green( `[UPDATE AVAILABLE] ` ) + `Version ${lv} of ${myPkg.name} is available. Any release notes can be found here: ` + chalk.underline( `${myPkg.changelog}` ) );\n      }\n      console.log( chalk.yellow( `HomeBridge-Cmd4 5.0.0+ Important Notice:\\n` ) );\n      console.log( `Cmd4 has been optimized for simplification and best practices. Its configuration has changed to what is recommended by Homebridge. See https://git.io/JtMGR.\\n` );\n      console.log( `Gone are the are the very confusing Cmd4_Mode and RestartRecovery. The only changes you will see are the warnings that these options are no longer required.` );\n      console.log( chalk.red( `* ` ) + `RestartRecovery is now automatic; which not enabling could cause your device to turn on/off over a restart.` );\n      console.log( chalk.red( `* ` ) + `Cmd4_Mode is as per https://git.io/JtMGR where the callback is immediate to homebridge with the data from your device to follow.` );\n      console.log( chalk.red( `* ` ) + `Demo mode is still available by not defining any polling.\\n` );\n\n      console.log( chalk.underline( `Cmd4 New Users` ) );\n      console.log( chalk.green( `* ` ) + `You will need to follow the README to continue the configuration of HomeBridge-CMD4.\\n` );\n\n      console.log(`\\n   As always, if you like this plugin, don't forget to star it on GitHub.\\n`);\n      console.log(`\\n   Enjoy`);\n      console.log(`      John Talbot\\n`);\n})( );\n\n"
  },
  {
    "path": "test/CMD4_ACC_TYPE_ENUM.js",
    "content": "'use strict';\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\nvar Service = _api.hap.Service;\n\n\ndescribe( `Testing require of CMD4_ACC_TYPE_ENUM.js`, ( ) =>\n{\n   it( `CMD4_ACC_TYPE_ENUM should be defined ( required correctly )`, ( ) =>\n   {\n      assert.isNotNull( ACC_DATA, `CMD4_ACC_TYPE_ENUM is null` );\n   });\n\n   it( `ACC_DATA.init should be a function`, ( ) =>\n   {\n      assert.isFunction( ACC_DATA.init, `.init is not a function` );\n   });\n\n   // ************ TEST UNINITIALIZED CMD4_ACC_TYPE_ENUM EOL **************\n   describe( `Testing CMD4_ACC_TYPE_ENUM.EOL`, ( ) =>\n   {\n      it( `CMD4_ACC_TYPE_ENUM has EOL`, ( ) =>\n      {\n         assert.isNotNull( CMD4_ACC_TYPE_ENUM.EOL, `EOL is null` );\n      });\n\n      it( `CMD4_ACC_TYPE_ENUM.EOL =  ${ ACC_EOL }`, ( ) =>\n      {\n         assert.equal( CMD4_ACC_TYPE_ENUM.EOL, ACC_EOL, `CMD4_ACC_TYPE_ENUM.EOL FOUND: ${ CMD4_ACC_TYPE_ENUM.EOL }` );\n      });\n\n      it( `CMD4_ACC_TYPE_ENUM[ 0-${ CMD4_ACC_TYPE_ENUM.EOL } ] should equal value at index`, ( ) =>\n      {\n         for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n         {\n            assert.notEqual( CMD4_ACC_TYPE_ENUM[index], index );\n         }\n      });\n   });\n})\n\ndescribe( `Testing INITIALIZED CMD4_ACC_TYPE_ENUM`, ( ) =>\n{\n   // Init the library for all to use\n   let CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n\n   describe(`Testing Initialized CMD4_ACC_TYPE_ENUM.properties[]`, ( ) =>\n   {\n      it('CMD4_ACC_TYPE_ENUM.properties should be an object', ( ) =>\n      {\n         assert.isObject(CMD4_ACC_TYPE_ENUM.properties, `CMD4_DEVICE_TYPE_ENUM.properties is not an object` );\n      });\n\n      it(`Testing CMD4_ACC_TYPE_ENUM.properties[]`, ( ) =>\n      {\n         for (let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n         {\n            let result = CMD4_ACC_TYPE_ENUM.properties[ index ];\n\n            // Make sure our properties are defined\n            assert.isNotNull( result, `CMD4_ACC_TYPE_ENUM.properties[${ index }] is null. result: ${ result }` );\n\n            for (let jIndex=0; jIndex < CMD4_ACC_TYPE_ENUM.EOL; jIndex ++ )\n            {\n               if ( index == jIndex) continue;\n\n               it( `CMD4_ACC_TYPE_ENUM.properties[ ${ index } ].type should not be duplicated`, ( ) =>\n               {\n                  assert.equal( CMD4_ACC_TYPE_ENUM.properties[ index ].type,\n                                CMD4_ACC_TYPE_ENUM.properties[ jIndex ].type, ` Duplicate ACC type ${ CMD4_ACC_TYPE_ENUM.properties[ index ].type }` );\n               });\n            }\n         }\n      });\n   });\n\n\n   // TJOS STIFF ADDED\n\n   // ** TEST ACC_TYPE_ENUM.properties[].props  **\n   describe('Testing CMD4_ACC_TYPE_ENUM.properties[].props', ( ) =>\n   {\n      for ( let accTypeEnumIndex=0; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex++ )\n      {\n          if ( accTypeEnumIndex == CMD4_ACC_TYPE_ENUM.Name )\n             continue;\n\n          // Do not understand why Charateristic.PairingPairings is\n          // undefined, but is okay in Cmd4\n          // Problem occured with hap-nodejs 0.9.2, but not 0.8.5 &&\n          //                      homebridge 1.3.1, but not 1.1.7\n          if ( accTypeEnumIndex == CMD4_ACC_TYPE_ENUM.PairingPairings )\n             continue;\n\n          if ( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].deprecated == true )\n             continue;\n\n          it( `CMD4_ACC_TYPE_ENUM.properties[ ${ accTypeEnumIndex } ].type should be a string`, ( ) =>\n          {\n             assert.isString( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type, ` type is not a string at index ${ accTypeEnumIndex }` );\n          });\n\n          let characteristic = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].characteristic;\n          // *** TEST CMD4_ACC_TYPE_ENUM.properties[].characteristic *******\n          // Make sure our characteristic is defined\n          assert.isNotNull( characteristic, `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].characteristic is null` );\n\n          assert.isFunction( characteristic, `characteristic is not a function at accTypeEnumIndex: ${ accTypeEnumIndex } result: ${ characteristic }` );\n\n          it(`Testing CMD4_ACC_TYPE_ENUM.properties[].UUID is same as in hap string `, ( ) =>\n          {\n\n             // Make sure that the UUID we defined is valid.\n             assert.equal(  CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].UUID,\n                            characteristic.UUID,\n                           ` Our UUID is not the same at index: ${ accTypeEnumIndex }` );\n          });\n\n          it(`Testing CMD4_ACC_TYPE_ENUM.properties[].description is a string `, ( ) =>\n          {\n\n             assert.isString(  CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].description,\n                           ` description is not a string at index: ${ accTypeEnumIndex }` );\n          });\n\n          it(`Testing CMD4_ACC_TYPE_ENUM.properties[].description String length > 10 `, ( ) =>\n          {\n\n             assert.isAtLeast(  CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].description.length, 10,\n                           ` description is is very short at index: ${ accTypeEnumIndex }` );\n          });\n\n          // Get the properties for this characteristic type\n          let accProperties = CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex];\n          // Characteristics dont seem to get removed and homebridge put a limit\n          // of 100 Characteristics per service, so just create a new service\n          // per characteristic.  This is unit testing anyway, so not an issue.\n          let serviceName = `Service${ accTypeEnumIndex }`;\n          let service = new _api.hap.Service(serviceName, _api.hap.uuid.generate(serviceName ), serviceName );\n\n          it('Creating service to test Characteristic', ( ) =>\n          {\n             assert.isNotNull(service, `Service is null at accTypeEnumIndex: ${ accTypeEnumIndex }` );\n          });\n\n          describe(`Testing CMD4_ACC_TYPE_ENUM.properties[ ${ accTypeEnumIndex } ]: ${ accProperties.type }`, ( ) =>\n          {\n             var characteristicString = CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].type;\n\n             // Check relatedCurrentAccTypeEnumIndex property\n             it( `CMD4_ACC_TYPE_ENUM.properties[ ${ accTypeEnumIndex } ].relatedCurrentAccTypeEnumIndex`, ( ) =>\n             {\n                assert.isDefined( CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].relatedCurrentAccTypeEnumIndex, 'relatedCurrentAccTypeEnumIndex is not defined' );\n\n                let relatedCurrentAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].relatedCurrentAccTypeEnumIndex;\n\n                if ( relatedCurrentAccTypeEnumIndex != null )\n                {\n                   assert.isNumber( relatedCurrentAccTypeEnumIndex, `${ characteristicString } relatedCurrentAccTypeEnumIndex is not a number: ${ typeof relatedCurrentAccTypeEnumIndex }` );\n                   assert.isAbove( relatedCurrentAccTypeEnumIndex, 0, `${ characteristicString } relatedCurrentAccTypeEnumIndex < 0: ${ relatedCurrentAccTypeEnumIndex }` );\n                   assert.isBelow( relatedCurrentAccTypeEnumIndex, ACC_EOL, `${ characteristicString } relatedCurrentAccTypeEnumIndex is < ACC_EOL: ${ relatedCurrentAccTypeEnumIndex }` );\n\n                   // Make sure they point to each other.\n                   assert.equal( accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.properties[relatedCurrentAccTypeEnumIndex].relatedTargetAccTypeEnumIndex, `${ characteristicString } relatedCurrentAccTypeEnumIndex (${ relatedCurrentAccTypeEnumIndex }) not matching releatedTargetAccTypeEnumIndex` );\n                }\n             });\n\n             // Check relatedTargetAccTypeEnumIndex property\n             it( `CMD4_ACC_TYPE_ENUM.properties[ ${ accTypeEnumIndex } ].relatedTargetAccTypeEnumIndex`, ( ) =>\n             {\n                assert.isDefined( CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].relatedTargetAccTypeEnumIndex, 'relatedTargetAccTypeEnumIndex is not defined' );\n\n                let relatedTargetAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].relatedTargetAccTypeEnumIndex;\n\n                if ( relatedTargetAccTypeEnumIndex != null )\n                {\n                   assert.isNumber( relatedTargetAccTypeEnumIndex, `${ characteristicString } relatedTargetAccTypeEnumIndex is not a number: ${ typeof relatedTargetAccTypeEnumIndex }` );\n                   assert.isAbove( relatedTargetAccTypeEnumIndex, 0, `${ characteristicString } relatedTargetAccTypeEnumIndex < 0: ${ relatedTargetAccTypeEnumIndex }` );\n                   assert.isBelow( relatedTargetAccTypeEnumIndex, ACC_EOL, `${ characteristicString } relatedTargetAccTypeEnumIndex is < ACC_EOL: ${ relatedTargetAccTypeEnumIndex }` );\n\n                   // Make sure they point to each other.\n                   assert.equal( accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.properties[relatedTargetAccTypeEnumIndex].relatedCurrentAccTypeEnumIndex, `${ characteristicString } relatedTargetAccTypeEnumIndex (${ relatedTargetAccTypeEnumIndex }) not matching relatedCurrentAccTypeEnumIndex` );\n                }\n             });\n\n             // We need to add the characteristic to the service so we can get its Hap properties\n             service.addCharacteristic( characteristic );\n\n             let hapProps = service.getCharacteristic(characteristic ).props;\n             service.removeCharacteristic( characteristic );\n\n             it( `HAP props for HomeBridge Characteristic: ${ accProperties.type }`, ( ) =>\n             {\n                assert.isNotNull( hapProps, `perms for Characteristic type: ${ accProperties.type } is null` );\n             });\n\n             let hapFormat = hapProps.format;\n\n             // Test both Formats\n             it(`CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.format should be the same`, ( ) =>\n             {\n                assert.equal( hapFormat, accProperties.props.format, `format:${ accProperties.props.format } not equal to expected ${ hapFormat }` );\n             });\n\n             // Test cFormat\n             it(`CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.cFormat should not be null`, ( ) =>\n             {\n                assert.isNumber( accProperties.props.allowedWordCount, `allowedWordCount is not a Number at accTypeEnumIndex:${ accTypeEnumIndex }` );\n\n                switch( hapFormat )\n                {\n                   case _api.hap.Formats.STRING:\n                   case _api.hap.Formats.TLV8:\n                   case _api.hap.Formats.DATA:\n                      assert.equal( 0, accProperties.props.allowedWordCount, `allowedWordCount not 0 at accTypeEnumIndex: ${ accTypeEnumIndex }` );\n\n                      break;\n                   case _api.hap.Formats.INT:\n                   case _api.hap.Formats.UINT8:\n                   case _api.hap.Formats.UINT16:\n                   case _api.hap.Formats.UINT32:\n                   case _api.hap.Formats.BOOL:\n                   case _api.hap.Formats.FLOAT:\n                      assert.equal( 1, accProperties.props.allowedWordCount, `allowedWordCount not 1 at accTypeEnumIndex: ${ accTypeEnumIndex }` );\n                      break;\n                   default:\n                      assert( `allowedWordCount unknown at accTypeEnumIndex: ${ accTypeEnumIndex }` );\n                }\n\n             });\n\n\n             // Test units\n             let hapUnits = hapProps.units;\n\n             it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.units should be the same`, ( ) =>\n             {\n                assert.equal(hapUnits, accProperties.props.units, `units: ${ accProperties.props.units } not equal to expected: ${ hapUnits }` );\n             });\n\n             // test minValue\n             let hapMinValue = hapProps.minValue;\n\n             it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.minValue should be the same`, ( ) =>\n             {\n                 assert.equal( hapMinValue, accProperties.props.minValue, `minValue: ${ accProperties.props.minValue } not equal to expected: ${ hapMinValue }` );\n             });\n\n             // test maxValue\n             let hapMaxValue = hapProps.maxValue;\n\n             // They are missing AUTO\n             if ( accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.CurrentHeatingCoolingState )\n             {\n\n                it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.maxValue should be the same`, ( ) =>\n                {\n                   assert.equal( hapMaxValue, accProperties.props.maxValue, `maxValue: ${ accProperties.props.maxValue } not equal to expected: ${ hapMaxValue }` );\n                });\n             } else {\n                //console.log(`Homebridge is wrong, skipping` );\n             }\n\n             // test minStep\n             let hapMinStep = hapProps.minStep;\n\n             it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.minStep should be the same`, ( ) =>\n             {\n                assert.equal( hapMinStep, accProperties.props.minStep, `minStep: ${ accProperties.props.minStep } not equal to expected: ${ hapMinStep }` );\n             });\n\n             // Test if correct perms ( both ways )\n             it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].props.perms are the same`, ( ) =>\n             {\n                let hapPerms = hapProps.perms;\n                accProperties.props.perms.forEach( perm => assert.include( hapPerms, perm, ` ${ characteristicString } ( ${ accTypeEnumIndex } ) missing perm: ${ perm } in Hap Perm` ) );\n                hapPerms.forEach( perm => assert.include( accProperties.props.perms, perm, ` ${ characteristicString } ( ${ accTypeEnumIndex } ) missing perm: ${ perm } in accProperties.props.perms` ) );\n             });\n\n             // Our validValues should not be null\n             it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].validValues should not be null`, ( ) =>\n             {\n                assert.isNotNull(accProperties.validValues, 'validValues is Null' );\n             });\n\n             // test all validValues\n             let hapValidValues = hapProps.validValues;\n\n             if ( ! hapValidValues )\n             {\n                // We defined what valid values are for BOOL\n                // so TRUE/FALSE can be a constant.\n                if (hapFormat != _api.hap.Formats.BOOL )\n                {\n                   // Hap has values defined, but not in valid values. We added them in ours\n                   if ( accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.CameraOperatingModeIndicator &&\n                        accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.ThirdPartyCameraActive &&\n                        accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.RecordingAudioActive &&\n                        accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.PeriodicSnapshotsActive &&\n                        accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.HomeKitCameraActive &&\n                        accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.EventSnapshotsActive )\n                   {\n                      // Test if our validValues is empty\n                      it( `Our CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].validValues.length should be 0`, ( ) =>\n                      {\n                         assert.equal(Object.keys(accProperties.validValues ).length, 0, `validValuesh for: ${ accTypeEnumIndex } is not empty` );\n                      });\n                   } else {\n                      // console.log(`Homebridge is wrong, skipping` );\n                   }\n                }\n             } else\n             {\n                // For InputDeviceType, we define the UNKNOWN_6 they do not. its okay\n                // For ManagedNetworkEnable, we define the UNKNOWN they do not. its okay\n                if ( accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.CurrentHeatingCoolingState &&\n                     accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.InputDeviceType &&\n                     accTypeEnumIndex != CMD4_ACC_TYPE_ENUM.ManagedNetworkEnable )\n                {\n                   // Test if same number of validValues\n                   it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].perms.length should be the same`, ( ) =>\n                   {\n                      assert.equal( hapValidValues.length, Object.keys(accProperties.validValues ).length, `validValues.length(${ Object.keys(accProperties.validValues ).length }) for: ${ accTypeEnumIndex } is not: ${ hapValidValues.length }` );\n                   });\n\n                   // test all validValues against hapValidValues\n                   for ( let valuesIndex = 0; valuesIndex < hapValidValues.length; valuesIndex++ )\n                   {\n                       let hapValue = hapValidValues[valuesIndex];\n\n                       it( `CMD4_ACC_TYPE_ENUM.properties[${ accTypeEnumIndex }].validValues[${ valuesIndex }] should be the same`, ( ) =>\n                       {\n                             let cmd4Key = Object.keys(accProperties.validValues )[valuesIndex];\n                             let cmd4Value = accProperties.validValues[cmd4Key];\n                             assert.equal( hapValue, cmd4Value, `validValues[${ valuesIndex }]: ${ cmd4Value } not equal to expected: ${ hapValue }` );\n                       });\n                   }\n                } else {\n                   // console.log(`Homebridge is wrong, skipping` );\n                }\n             }\n             service.removeCharacteristic(characteristic );\n\n          });\n       }\n   });\n});\n\ndescribe( `Testing CMD4_ACC_TYPE_ENUM.indexOfEnum`, ( ) =>\n{\n   // Init the library for all to use\n   let CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n\n   it('CMD4_ACC_TYPE_ENUM.indexOfEnum should be a function', ( ) =>\n   {\n      assert.isFunction(CMD4_ACC_TYPE_ENUM.indexOfEnum, `CMD4_DEVICE_TYPE_ENUM.indexOfEnum is not a function` );\n   });\n\n   it(`Testing CMD4_ACC_TYPE_ENUM.indexOfEnum( \"On\" )`, ( ) =>\n   {\n      let result = CMD4_ACC_TYPE_ENUM.indexOfEnum( \"On\" );\n\n      assert.equal( result, CMD4_ACC_TYPE_ENUM.On,`Index is incorrect for \"On\"` );\n   });\n\n   it(`Testing CMD4_ACC_TYPE_ENUM.indexOfEnum( \"on\" )`, ( ) =>\n   {\n      let result = CMD4_ACC_TYPE_ENUM.indexOfEnum( \"on\" );\n\n      assert.equal( result, CMD4_ACC_TYPE_ENUM.On,`Index is incorrect for \"on\"` );\n   });\n\n});\n\n\n\ndescribe( `Testing CMD4_ACC_TYPE_ENUM stringConversionFunction`, ( ) =>\n{\n   // Init the library for all to use\n   let CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n   describe( `Testing CMD4_ACC_TYPE_ENUM.properties[].stringConversionFunction`, ( ) =>\n   {\n      it( 'CMD4_ACC_TYPE_ENUM[ 0 - ${ ACC_EOL } ].stringConversionFunction should be a function', ( ) =>\n      {\n         for ( let index = 0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n         {\n            assert.isFunction( CMD4_ACC_TYPE_ENUM.properties[ index ].stringConversionFunction, `Missing conversion function at index: ${ index }` );\n         }\n      });\n   });\n\n   it(`stringConversionFunction of AirParticulateSize of UINT8 Number should be Number.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AirParticulateSize;\n      let value = 60;\n      let expectedResult = 60;\n\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of AirParticulateSize of UINT8 String should be Number.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AirParticulateSize;\n      let value = \"60\";\n      let expectedResult = 60;\n\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of TargetTemperature of Float should be Float.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = 60.2;\n      let expectedResult = 60.2;\n\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of TargetTemperature of Float String should be Float.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = \"60.2\";\n      let expectedResult = 60.2;\n\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of TargetTemperature of Float \"0.0\" should be 0.0`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = \"0.0\";\n      let expectedResult = 0.0;\n      let expectedResultType = \"number\";  // There is no float type\n\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n\n      let resultType = typeof result;\n\n      assert.equal( resultType, expectedResultType, `stringConversionFunction of valid data with full properties returned incorrect result. Expected: ${ expectedResultType } received: ${ result }` );\n   });\n\n   it(`stringConversionFunction of TargetTemperature of Float \"0\" should be float`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = \"0\";\n      let expectedResult = 0;\n      let expectedResultType = \"number\";  // There is no float type\n\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n\n      let resultType = typeof result;\n\n      assert.equal( resultType, expectedResultType, `stringConversionFunction of valid data with full properties returned incorrect result. Expected: ${ expectedResultType } received: ${ result }` );\n   });\n\n\n   it(`stringConversionFunction of Name of string1 should be String.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Name;\n      let value = \"Device\";\n      let expectedResult = \"Device\";\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Name of number should be String.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Name;\n      let value = 123;\n      let expectedResult = \"123\";\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of FAlse should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"FAlse\";\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of \"FAlse\" should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"FAlse\";\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of \"True\" should be true.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"true\";\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of false should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = false;\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of true should be true.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = true;\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of 0 should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = 0;\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of 1 should be true (On).`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = 1;\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of BOOL of 0 should be false (Off) .`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.On;\n      let value = 0;\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of BOOL of 1 should be True (On).`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.On;\n      let value = 1;\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of 1 should be true .`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = 1;\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n\n   it(`stringConversionFunction of Mute of \"1\" should be True (On).`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"1\";\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n   it(`stringConversionFunction of Mute of 0 should be false (off).`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = 0;\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n   it(`stringConversionFunction of Mute of \"0\" should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"0\";\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n   it(`stringConversionFunction of Mute of true should be true.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = true;\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n   it(`stringConversionFunction of Mute of false should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = false;\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n   it(`stringConversionFunction of Mute of \"false\" should be false.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"false\";\n      let expectedResult = false;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n   it(`stringConversionFunction of Mute of \"true\" should be true.`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = \"true\";\n      let expectedResult = true;\n\n      let result = CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].stringConversionFunction( value  );\n\n      assert.equal( result, expectedResult, `stringConversionFunction of valid data with full properties returned incorrect result: ${ result }` );\n   });\n});\n\n\ndescribe( `Testing CMD4_ACC_TYPE_ENUM Add Characteristic`, ( ) =>\n{\n   // Init the library for all to use\n   let CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n   it( `ACC_DATA.add should be a function`, ( ) =>\n   {\n      assert.isFunction( CMD4_ACC_TYPE_ENUM.add, `.add is not a function` );\n   });\n   it( `CMD4_ACC_TYPE_ENUM.EOL = ${ ACC_EOL }`, ( ) =>\n   {\n      assert.equal( CMD4_ACC_TYPE_ENUM.EOL, ACC_EOL, `CMD4_ACC_TYPE_ENUM.EOL FOUND: ${ CMD4_ACC_TYPE_ENUM.EOL }` );\n   });\n\n   // Changing the number of characteristics screws up other tests.\n   it.skip( `CMD4_ACC_TYPE_ENUM.add creates new characteristic, incrementing EOL`, ( ) =>\n   {\n      let definition = { };\n          definition.type = \"PointX\";\n          definition.description = \"An X Coordinate\";\n          definition.props = { };\n          definition.props.format = \"uint32\";\n          definition.props.minValue = 0;\n          definition.props.minStep = 1;\n          definition.props.perms = [ \"pr\", \"pw\", \"ev\" ];\n          definition.validValues = { };\n\n      let characteristic = CMD4_ACC_TYPE_ENUM.add( _api, definition.type, definition.description, definition.props, definition.validValues );\n\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.PointX;\n      assert.equal( accTypeEnumIndex, ACC_EOL, `ACC_TYPE_ENUM_INDEX.PointX not defined` );\n\n      assert.equal( CMD4_ACC_TYPE_ENUM.EOL, ACC_EOL +1, `CMD4_ACC_TYPE_ENUM not incremented` );\n\n\n      assert.isNotNull( characteristic, `New characteristic was is null ` );\n\n   });\n\n   // Changing the number of characteristics screws up other tests.\n   it.skip( `CMD4_ACC_TYPE_ENUM.add creates new characteristic compatible with service`, ( ) =>\n   {\n      let definition = { };\n          definition.type = \"PointX\";\n          definition.description = \"An X Coordinate\";\n          definition.props = { };\n          definition.props.format = \"uint32\";\n          definition.props.minValue = 0;\n          definition.props.minStep = 1;\n          definition.props.perms = [ \"pr\", \"pw\", \"ev\" ];\n          definition.validValues = { };\n\n      // Create the new characteristic.\n      CMD4_ACC_TYPE_ENUM.add( _api, definition.type, definition.description, definition.props, definition.validValues );\n\n      // Create a service to add the new characteristic.\n      let switchService = new Service.Switch();\n      assert.instanceOf( switchService , Service, \"Expected switchService to be instance of Service. Found %s\" , switchService );\n\n      // Add the new characteristic to the test service.\n      switchService.addCharacteristic( CMD4_ACC_TYPE_ENUM.properties[CMD4_ACC_TYPE_ENUM.PointX].characteristic );\n\n      // Check to see if the characteristic was accepted by the service\n      let result = switchService.testCharacteristic( CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.PointX ].characteristic );\n\n      assert.isTrue( result, `New characteristic not added to service. result: ${ result }` );\n   });\n\n});\n\n"
  },
  {
    "path": "test/CMD4_CHAR_TYPE_ENUMS.js",
    "content": "'use strict';\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\nlet { indexOfEnum } = require( \"../utils/indexOfEnum\" );\nObject.defineProperty(exports, \"indexOfEnum\", { enumerable: true, get: function () { return indexOfEnum.indexOfEnum; } });\n\n\ndescribe( \"Testing require of CMD4_CHAR_TYPE_ENUMS.js\", ( ) =>\n{\n   it( \"CMD4_CHAR_TYPE_ENUMS should be defined ( required correctly )\", ( ) =>\n   {\n      assert.isNotNull( CMD4_CHAR_TYPE_ENUMS, \"CMD4_CHAR_TYPE_ENUMS is null\" );\n   });\n\n   // ************ TEST UNINITIALIZED CMD4_FORMAT_TYPE_ENUM EOL **************\n   describe( \"Testing CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL\", ( ) =>\n   {\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM has EOL\", ( ) =>\n      {\n         assert.isNotNull( CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL, \"EOL is null\" );\n      });\n\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL = \" + FORMAT_EOL, ( ) =>\n      {\n         assert.equal( CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL, FORMAT_EOL, \"CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL FOUND: \" + CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL );\n      });\n\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM[ 0-\" + CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL + \" ] should equal value at index\", ( ) =>\n      {\n         for ( let index=0; index < CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.EOL; index ++ )\n         {\n            assert.notEqual( CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM[index], index );\n         }\n      });\n\n   });\n\n   // ************ TEST UNINITIALIZED CMD4_UNITS_TYPE_ENUM EOL **************\n   describe( \"Testing CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL\", ( ) =>\n   {\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM has EOL\", ( ) =>\n      {\n         assert.isNotNull( CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL, \"EOL is null\" );\n      });\n\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL = \" + UNITS_EOL, ( ) =>\n      {\n         assert.equal( CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL, UNITS_EOL, \"CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL FOUND: \" + CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL );\n      });\n\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM[ 0-\" + CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL + \" ] should equal value at index\", ( ) =>\n      {\n         for ( let index=0; index < CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.EOL; index ++ )\n         {\n            assert.notEqual( CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM[index], index );\n         }\n      });\n\n   });\n\n\n   // ************ TEST UNINITIALIZED CMD4_PERMS_TYPE_ENUM EOL **************\n   describe( \"Testing CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL\", ( ) =>\n   {\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM has EOL\", ( ) =>\n      {\n         assert.isNotNull( CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL, \"EOL is null\" );\n      });\n\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL = \" + PERMS_EOL, ( ) =>\n      {\n         assert.equal( CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL, PERMS_EOL, \"CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL FOUND: \" + CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL );\n      });\n\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM[ 0-\" + CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL + \" ] should equal value at index\", ( ) =>\n      {\n         for ( let index=0; index < CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.EOL; index ++ )\n         {\n            assert.notEqual( CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM[index], index );\n         }\n      });\n\n   });\n})\n\n\n\n\n\ndescribe( \"Testing INITIALIZED CMD4_CHAR_TYPE_ENUMS\", ( ) =>\n{\n   // Init the library for all to use\n   let CMD4_CHAR_TYPE_ENUMS = CHAR_DATA.init( _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n\n   describe(\"Testing Initialized CMD4_CHAR_TYPE_ENUMS.\", ( ) =>\n   {\n      // Test a format type\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.float should equal expected value\", ( ) =>\n      {\n         let formatIndex = CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM.properties.indexOfEnum( i => i.type === \"float\" );\n         assert.equal( formatIndex, 2, `CMD4_CHAR_TYPE_ENUMS.CMD4_FORMAT_TYPE_ENUM \"float\" not equal to expected index`);\n      });\n\n      // Test a units type\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.lux should equal expected value\", ( ) =>\n      {\n         let unitsIndex = CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM.properties.indexOfEnum( i => i.type === \"lux\" );\n         assert.equal( unitsIndex, 3, `CMD4_CHAR_TYPE_ENUMS.CMD4_UNITS_TYPE_ENUM \"lux\" not equal to expected index`);\n      });\n\n      // Test a perms type\n      it( \"CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.ev should equal expected value\", ( ) =>\n      {\n         let permsIndex = CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM.properties.indexOfEnum( i => i.type === \"ev\" );\n         assert.equal( permsIndex, 4, `CMD4_CHAR_TYPE_ENUMS.CMD4_PERMS_TYPE_ENUM \"ev\" not equal to expected index`);\n      });\n   });\n});\n"
  },
  {
    "path": "test/CMD4_DEVICE_TYPE_ENUM.js",
    "content": "'use strict';\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\n\ndescribe( \"Testing require of CMD4_DEVICE_TYPE_ENUM.js\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM should be defined ( required correctly)\", ( ) =>\n   {\n      assert.isNotNull( DEVICE_DATA, \"CMD4_DEVICE_TYPE_ENUM is null\" );\n   });\n\n   it( \"DEVICE_DATA.init should be a function\", ( ) =>\n   {\n      assert.isFunction( DEVICE_DATA.init, \".init is not a function\" );\n   });\n\n   // ************ TEST UNINITIALIZED CMD4_DEVICE_TYPE_ENUM EOL **************\n   describe( \"Testing CMD4_DEVICE_TYPE_ENUM.EOL\", ( ) =>\n   {\n      it( \"CMD4_DEVICE_TYPE_ENUM has EOL\", ( ) =>\n      {\n         assert.isNotNull( CMD4_DEVICE_TYPE_ENUM.EOL, \"EOL is null\" );\n      });\n\n      it( \"CMD4_DEVICE_TYPE_ENUM.EOL = \" + DEVICE_EOL, ( ) =>\n      {\n         assert.equal( CMD4_DEVICE_TYPE_ENUM.EOL, DEVICE_EOL, \"CMD4_DEVICE_TYPE_ENUM.EOL FOUND: \" + CMD4_DEVICE_TYPE_ENUM.EOL );\n      });\n\n      it( \"CMD4_DEVICE_TYPE_ENUM[ 0-\" + CMD4_DEVICE_TYPE_ENUM.EOL + \" ] should equal value at index\", ( ) =>\n      {\n         for ( let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n         {\n            assert.notEqual( CMD4_DEVICE_TYPE_ENUM[index], index );\n         }\n      });\n   });\n})\n\n// ************ TEST INITIALIZED CMD4_DEVICE_TYPE_ENUM **************\ndescribe( \"Testing INITIALIZED CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   // Init the library for all to use\n   let CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n   let CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].UUID *******\n   describe('Testing Initialized CMD4_DEVICE_TYPE_ENUM.properties[].UUID', ( ) =>\n   {\n      it('Testing CMD4_DEVICE_TYPE_ENUM.properties[].UUID is a string ', ( ) =>\n      {\n         for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n         {\n            if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n               continue;\n\n            let result = CMD4_DEVICE_TYPE_ENUM.properties[ index ].UUID;\n\n            // Make sure that the UUID we defined is valid.\n            expect(result).to.be.a( \"string\", \" result is not a string. result:\" + result + \" at index: \" + index );\n\n         }\n      });\n\n      it('Testing CMD4_DEVICE_TYPE_ENUM.properties[].UUID is same as in hap string ', ( ) =>\n      {\n         for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n         {\n            if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n               continue;\n\n            let service = CMD4_DEVICE_TYPE_ENUM.properties[ index ].service;\n            assert.isNotNull( service, ` CMD4_DEVICE_TYPE_ENUM.properties[${ index } ].service is null` );\n            let hapUUID = service.UUID;\n            let result = CMD4_DEVICE_TYPE_ENUM.properties[ index ].UUID;\n\n            // Make sure that the UUID we defined is valid.\n            expect(result).to.equal( hapUUID, \" Our UUID is not the same at index: \" + index + \". result:\" + result );\n         }\n      });\n   });\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].service *******\n   describe('Testing Initialized CMD4_DEVICE_TYPE_ENUM.properties[].service', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].service ', ( ) =>\n         {\n            // Make sure our service is defined\n            let service = CMD4_DEVICE_TYPE_ENUM.properties[ index ].service;\n            assert.isNotNull( service, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].service is null:\" );\n         });\n      }\n   });\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].defaultCategory *******\n   describe('Testing Initialized CMD4_DEVICE_TYPE_ENUM.properties[].defaultCategory', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].defaultCategory ', ( ) =>\n         {\n            // Make sure our defaultCategory is defined\n            let defaultCategory = CMD4_DEVICE_TYPE_ENUM.properties[ index ].defaultCategory;\n            assert.isNumber(defaultCategory, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].defaultCategory is not a number. category:\" + defaultCategory );\n            let result = _api.hap.Categories[ defaultCategory ];\n\n            // Make sure that the default category we defined is valid.\n            assert.isString(result, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].defaultCategory is not a string. result:\" + result );\n\n         });\n      }\n   });\n\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].publishExternally *******\n   describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[].publishExternally', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].publishExternally ', ( ) =>\n         {\n\n            assert.isBoolean(CMD4_DEVICE_TYPE_ENUM.properties[ index ].publishExternally, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].publishExternally is not a true|false\" );\n\n         });\n      }\n   });\n\n   describe('Testing Initialized CMD4_DEVICE_TYPE_ENUM.properties[].defaultCategory', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].defaultCategory ', ( ) =>\n         {\n            // Make sure our defaultCategory is defined\n            let defaultCategory = CMD4_DEVICE_TYPE_ENUM.properties[ index ].defaultCategory;\n            assert.isNumber(defaultCategory, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].defaultCategory is not a number. category:\" + defaultCategory );\n            let result = _api.hap.Categories[ defaultCategory ];\n\n            // Make sure that the default category we defined is valid.\n            assert.isString(result, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].defaultCategory is not a string. result:\" + result );\n\n         });\n      }\n   });\n\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].publishExternally *******\n   describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[].publishExternally', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].publishExternally ', ( ) =>\n         {\n\n            assert.isBoolean(CMD4_DEVICE_TYPE_ENUM.properties[ index ].publishExternally, \"CMD4_DEVICE_TYPE_ENUM.properties[\" + index + \"].publishExternally is not a true|false\" );\n\n         });\n      }\n   });\n\n   // ******** TEST CMD4_DEVICE_TYPE_ENUM.properties *************\n   describe('Testing CMD4_DEVICE_TYPE_ENUM.properties', ( ) =>\n   {\n      it('CMD4_DEVICE_TYPE_ENUM.properties should be an array', ( ) =>\n      {\n         assert.isObject(CMD4_DEVICE_TYPE_ENUM.properties, \"CMD4_DEVICE_TYPE_ENUM.properties is not an object\" );\n      });\n\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '] should not be null ', ( ) =>\n         {\n             assert.isNotNull(CMD4_DEVICE_TYPE_ENUM.properties[index], 'properties[' +  index + '] is null' );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].deviceName should not be null ', ( ) =>\n         {\n             assert.isNotNull(CMD4_DEVICE_TYPE_ENUM.properties[index].deviceName, 'deviceName is null at index:' + index );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].service should not be null ', ( ) =>\n         {\n             assert.isNotNull(CMD4_DEVICE_TYPE_ENUM.properties[index].service, 'service is null at index:' + index );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].defaultCategory should not be null ', ( ) =>\n         {\n             assert.isNotNull(CMD4_DEVICE_TYPE_ENUM.properties[index].defaultCategory, 'defaultCategory is null at index:' + index );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].publishExternally should not be null ', ( ) =>\n         {\n             assert.isNotNull(CMD4_DEVICE_TYPE_ENUM.properties[index].publishExternally, 'publishExternally is null at index:' + index );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].devicesStateChangeDefaultTime should not be null ', ( ) =>\n         {\n            assert.isNotNull(CMD4_DEVICE_TYPE_ENUM.properties[index].devicesStateChangeDefaultTime, 'devicesStateChangeDefaultTime is null at index:' + index );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics should be an array ', ( ) =>\n         {\n             assert.isArray(CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics, 'requiredCharacteristics is not an array at index:' + index );\n         });\n\n         it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].defaultPollingCharacteristics should be an array ', ( ) =>\n         {\n             assert.isArray(CMD4_DEVICE_TYPE_ENUM.properties[index].defaultPollingCharacteristics, 'defaultPollingCharacteristics is not an array at index:' + index );\n         });\n      }\n   });\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].requiredCharacteristics *******\n   describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[].requiredCharacteristics', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '] ', ( ) =>\n         {\n            let length = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics.length;\n            for (let rindex=0; rindex < length; rindex ++ )\n            {\n               describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics[' + rindex + ']', ( ) =>\n               {\n                  let allRequiredCharacteristics = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics;\n\n                  let accTypeEnumIndex = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics[rindex].type;\n\n                  let defaultValue = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics[rindex].defaultValue;\n\n                  let relatedCurrentAccTypeEnumArray = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics[rindex].relatedCurrentAccTypeEnumArray;\n                  let relatedTargetAccTypeEnumArray = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics[rindex].relatedTargetAccTypeEnumArray;\n\n                  testCharacteristicIndex( accTypeEnumIndex );\n\n                  it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics[' + rindex + '].defaultValue must not be null', ( ) =>\n                  {\n                     assert.isNotNull( defaultValue, 'defaultValue is null at index:' + index );\n                  });\n\n                  it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics[' + rindex + '].relatedCurrentAccTypeEnumArray must be an Array', ( ) =>\n                  {\n                     assert.isArray( relatedCurrentAccTypeEnumArray, 'relatedCurrentAccTypeEnumArray is not an Array at index:' + index );\n                  });\n                  it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics[' + rindex + '].relatedTargetAccTypeEnumArray must be an Array', ( ) =>\n                  {\n                     assert.isArray( relatedTargetAccTypeEnumArray, 'relatedTargetAccTypeEnumArray is nat an Array at index:' + index );\n                  });\n                  if ( relatedCurrentAccTypeEnumArray.length > 0 )\n                  {\n                     relatedCurrentAccTypeEnumArray.forEach( ( relatedCurrentAccTypeEnumIndex ) =>\n                     {\n                        it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics[' + rindex + '].relatedTargetAccTypeEnumArray must have Current Defined', ( ) =>\n                        {\n                        console.log(\"looking for %s at index: %s rindex: %s\", relatedCurrentAccTypeEnumIndex, index, rindex );\n                           let foundEntry = allRequiredCharacteristics.find( entry => entry.type == relatedCurrentAccTypeEnumIndex );\n                           //console.log(\"accTypeEnumIndex = %s\", accTypeEnumIndex );\n                           //console.log(\"relatedCurrentAccTypeEnumIndex = %s\", relatedCurrentAccTypeEnumIndex );\n                           //console.log(\"foundEntry = %s\", foundEntry );\n                           //console.log(\"relatedTargetAccTypeEnumArray = %s\", relatedTargetAccTypeEnumArray );\n\n                           assert.isNotNull( foundEntry, ' No relatedCurrentAccTypeEnumIndex is null at index:' + index );\n                           let foundRelatedEntry = foundEntry.relatedTargetAccTypeEnumArray.includes(  accTypeEnumIndex );\n                           //console.log(\"foundRelatedEntry = %s\", foundRelatedEntry );\n                           assert.isTrue( foundRelatedEntry, ' Current pointers do not match at index:' + index );\n                        });\n                     });\n                  }\n                  if ( relatedTargetAccTypeEnumArray.length > 0 )\n                  {\n                     relatedTargetAccTypeEnumArray.forEach ( ( relatedTargetAccTypeEnumIndex ) =>\n                     {\n                        it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].requiredCharacteristics[' + rindex + '].relatedCurrentAccTypeEnumIndex must have Current Defined', ( ) =>\n                        {\n                           let foundEntry = allRequiredCharacteristics.find( entry => entry.type == relatedTargetAccTypeEnumIndex );\n\n                           assert.isNotNull( foundEntry, ' No relatedTargetAccTypeEnumIndex is null at index:' + index );\n                           let foundRelated = foundEntry.relatedCurrentAccTypeEnumArray.includes( accTypeEnumIndex );\n                           assert.isTrue( foundRelated, ' Current Target do not match at index:' + index );\n                        });\n                     });\n                  }\n               });\n            }\n         });\n      }\n   });\n\n   // *** TEST CMD4_DEVICE_TYPE_ENUM.properties[].optionalCharacteristics *******\n   describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[].optionalCharacteristics', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].optionalCharacteristics ', ( ) =>\n         {\n            let length = CMD4_DEVICE_TYPE_ENUM.properties[index].optionalCharacteristics.length;\n            for (let rindex=0; rindex < length; rindex ++ )\n            {\n\n               let accTypeEnumIndex = CMD4_DEVICE_TYPE_ENUM.properties[index].optionalCharacteristics[rindex];\n\n               testCharacteristicIndex(accTypeEnumIndex, rindex );\n            }\n         });\n      }\n   });\n\n   // ** TEST CMD4_DEVICE_TYPE_ENUM.properties[].defaultPollingCharacteristic  **\n   describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[].defaultPollingCharacteristics', ( ) =>\n   {\n      for (let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++ )\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n            continue;\n\n         describe('Testing CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].defaultPollingCharacteristics ', ( ) =>\n         {\n            let length = CMD4_DEVICE_TYPE_ENUM.properties[index].defaultPollingCharacteristics.length;\n            for (let rindex=0; rindex < length; rindex ++ )\n            {\n\n               let defaultPollingAccTypeEnumIndex = CMD4_DEVICE_TYPE_ENUM.properties[index].defaultPollingCharacteristics[rindex];\n\n               testCharacteristicIndex(defaultPollingAccTypeEnumIndex, rindex );\n\n\n               // Check that polled characteristic is in required characteristics\n               let foundInRequiredCharacteristics = false;\n               let dLength = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics.length;\n               for (let dindex=0; dindex < dLength; dindex ++ )\n               {\n                   let rCharacteristic = CMD4_DEVICE_TYPE_ENUM.properties[index].requiredCharacteristics[dindex].type;\n                   if (defaultPollingAccTypeEnumIndex == rCharacteristic )\n                   {\n                      foundInRequiredCharacteristics = true;\n                      break;\n                   }\n               }\n               it('CMD4_DEVICE_TYPE_ENUM.properties[' + index + '].defaultPollingCharacteristics[' + rindex + '] is in requiredCharacteristics', ( ) =>\n               {\n                   assert.isTrue(foundInRequiredCharacteristics, 'Polling characteristic is not in required Characteristics at accTypeEnumIndex:' + index );\n               });\n            }\n         });\n      }\n   });\n});\n\nfunction testCharacteristicIndex ( accTypeEnumIndex, rindex )\n{\n   describe('Testing accTypeEnumIndex:' + accTypeEnumIndex, () =>\n   {\n      it('rindex should be valid', ( ) =>\n      {\n          assert.isNotNull(rindex, `rindex must not be null accTypeEnumIndex: ${accTypeEnumIndex}` );\n      });\n\n      it('accTypeEnumIndex should be valid', ( ) =>\n      {\n          assert.isNotNull(accTypeEnumIndex, `accTypeEnumIndex must not be null rindex: ${rindex}` );\n      });\n\n\n      // AccessoryFlags is enum 0. However node.js inerpets 0 as false\n      // So if it is a number or a bool, then it is okay.\n      it('accTypeEnumIndex is a number', ( ) =>\n      {\n         assert.isFalse(typeof accTypeEnumIndex != 'boolean' && typeof accTypeEnumIndex != 'number', 'accTypeEnumIndex is not a number' );\n      });\n\n      // Test the range\n      it('accTypeEnumIndexs is within range', ( ) =>\n      {\n          assert.isTrue(0 <= accTypeEnumIndex && accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL, 'accTypeEnumIndex is not >= 0 && < ' + CMD4_ACC_TYPE_ENUM.EOL + ' accTypeEnumIndex:' + accTypeEnumIndex );\n      });\n   });\n}\n"
  },
  {
    "path": "test/Cmd4Accessory.js",
    "content": "\"use strict\";\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\nconst constants = require( \"../cmd4Constants\" );\n\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\nvar Cmd4Accessory = require( \"../Cmd4Accessory\" ).Cmd4Accessory;\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\nlet Cmd4Storage = require( \"../utils/Cmd4Storage\" );\n\n// Unfortunately this test never exits, because polling will start.\n// Warn the user of such\n// Note: Not true anymore as polling moved to Platform.\n//function abort()\n//{\n//   console.log(\"Test of Cmd4Accessory requires CTRL-c as polling was backgrounded\");\n//   setTimeout( abort, 1800 );\n//}\n//setTimeout( ( ) => { abort(); }, 1800 );\n\n// The State_cmd is called from $HOME\nconst home = require( \"os\" ).homedir();\n// THIS IS WHAT SCREWS UP THE THE UNIT TEST CASES IN Cmd4AccessoryGetValues! !!!\n//process.chdir( home );\n//\n\n\n// ******** QUICK TEST of SETUP *************\ndescribe('Quick Test of Setup', ( ) =>\n{\n\n   it('Plugin Characteristic should be a function', ( ) =>\n   {\n      assert.isFunction(_api.hap.Characteristic, `Characteristic is not an function` );\n   });\n\n   it('Plugin Accessory should be a function', ( ) =>\n   {\n      assert.isFunction(_api.hap.Accessory, `Accessory is not an function` );\n   });\n   it('Plugin Service should be a function', ( ) =>\n   {\n      assert.isFunction(_api.hap.Service, `_api.hap.Service is not an function` );\n   });\n\n   it( `CMD4_ACC_TYPE_ENUM.EOL = ${ ACC_EOL }`, ( ) =>\n   {\n      expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n\n   it( `CMD4_DEVICE_TYPE_ENUM.EOL = ${ DEVICE_EOL }`, ( ) =>\n   {\n      expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n})\n\n// ******** TEST Cmd4Accessory *************\ndescribe('A simple Cmd4Accessory Test', ( ) =>\n{\n   it( `Test can create an instance of Cmd4Accessory`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.instanceOf( accessory , Cmd4Accessory, `Expected accessory to be instance of Cmd4Accessory.` );\n\n   });\n});\n\ndescribe('A simple Cmd4Accessory Test Debbuging enabled', ( ) =>\n{\n   it( `Test can create an instance of Cmd4Accessory with Debug Enabled`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.instanceOf( accessory , Cmd4Accessory, `Expected accessory to be instance of Cmd4Accessory.` );\n\n\n   });\n});\n\n\ndescribe('Test Cmd4Accessory variables ', ( ) =>\n{\n   it( `Test typeIndex of a Switch set correctly`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.instanceOf( accessory , Cmd4Accessory, `Expected accessory to be instance of Cmd4Accessory.` );\n\n      assert.equal( accessory.typeIndex , CMD4_DEVICE_TYPE_ENUM.Switch, \"Expected typeIndex: %s Found: %s\" , CMD4_DEVICE_TYPE_ENUM.Switch, accessory.typeIndex );\n      assert.equal( accessory.typeIndex , CMD4_DEVICE_TYPE_ENUM.Switch, `Unexpected matching typeIndex` );\n   });\n\n   it( `Test typeIndex of all possible devices`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n\n      let parentInfo = undefined;\n      for ( let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true )\n               continue;\n\n         // Cannot create an accessory information of an accessory information\n         if ( index == CMD4_DEVICE_TYPE_ENUM.AccessoryInformation )\n         {\n            continue;\n         }\n\n         //config.name = `MY_${ CMD4_DEVICE_TYPE_ENUM.properties[index].deviceName }`;\n         config.name = devEnumIndexToC( index );\n         config.type = CMD4_DEVICE_TYPE_ENUM.properties[index].deviceName;\n\n\n         let log = new Logger( );\n         log.setOutputEnabled( false );\n         log.setBufferEnabled( true );\n         log.setDebugEnabled( false );\n\n         let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n         assert.instanceOf( accessory , Cmd4Accessory, `Expected accessory to be instance of Cmd4Accessory using index ${ index}` );\n\n         assert.equal( accessory.typeIndex , index, `Unexpected typeIndex: at ${ index }` );\n\n      }\n   });\n});\n\ndescribe('Cmd4Accessory Test get/test/set storedValues', ( ) =>\n{\n   it( `Check that STORED_DATA_ARRAY is created`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.isArray( accessory.STORED_DATA_ARRAY, `Expected accessory.STORED_DATA_ARRAY to be an Array. Found ${ typeof accessory.STORED_DATA_ARRAY }` );\n\n   });\n\n   it( `Check that Array STORED_DATA_ARRAY.cmd4Storage is created`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.instanceOf( accessory.STORED_DATA_ARRAY[0].cmd4Storage, Cmd4Storage, `Expected accessory.STORED_DATA_ARRAY[0].cmd4Storage to be an instance of Cmd4Storage. Found ${ typeof accessory.STORED_DATA_ARRAY[0].cmd4Storage }` );\n\n   });\n\n   it( `Check that cmd4Storage Array size is: ${ ACC_EOL }`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.equal( Object.keys(accessory.STORED_DATA_ARRAY[0].cmd4Storage.DATA).length, ACC_EOL, `Expected cmd4Storage to be of size: ${ ACC_EOL }` );\n\n   });\n\n   it( \"Check that getStoredValueForCharacteristic UC is set correctly for a Switch\", ( ) =>\n   {\n      let config =\n      {\n         displayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let characteristicString;\n      let cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_ACC_TYPE_ENUM.properties[ index ].deprecated == true )\n             continue;\n\n         characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( index );\n\n         let value = cmd4Accessory.cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n         if ( index == CMD4_ACC_TYPE_ENUM.On )\n         {\n            assert.isFalse( value, `Expected accessory.getStoredValueForCharacteristic( ${ characteristicString } ) to be False using index ${ index}` );\n         }\n         else\n         {\n            assert.isNull( value, `Expected accessory.getStoredValueForCharacteristic( ${ characteristicString } ) to be null using index ${ index}` );\n         }\n      }\n\n   });\n\n   it( \"Check that getStoredValueForCharacteristic LC is set correctly for a Switch\", ( ) =>\n   {\n      let config =\n      {\n         displayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let characteristicString;\n      let cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_ACC_TYPE_ENUM.properties[ index ].deprecated == true )\n             continue;\n\n         characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( index );\n\n         let value = cmd4Accessory.cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n         if ( index == CMD4_ACC_TYPE_ENUM.On )\n         {\n            assert.isFalse( value, `Expected accessory.getStoredValueForCharacteristic( ${ characteristicString } ) to be False using index ${ index}` );\n         }\n         else\n         {\n            assert.isNull( value, `Expected accessory.getStoredValueForCharacteristic( ${ characteristicString } ) to be null using index ${ index}` );\n         }\n      }\n\n   });\n\n   it( \"Check that getStoredValueForIndex is set correctly for a Switch\", ( ) =>\n   {\n      let config =\n      {\n         displayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_ACC_TYPE_ENUM.properties[ index ].deprecated == true )\n             continue;\n\n         let value = cmd4Accessory.cmd4Storage.getStoredValueForIndex( index );\n         if ( index == CMD4_ACC_TYPE_ENUM.On )\n         {\n            assert.isFalse( value, `Expected accessory.getStoredValueForIndex( ${ index } ) to be False using index ${ index}` );\n         }\n         else\n         {\n            assert.isNull( value, `Expected accessory.getStoredValueForIndex( ${ index } ) to be null using index ${ index}` );\n         }\n      }\n\n   });\n\n\n   it( `Check setStoredValueForIndex throws error with accTypeEnumIndex < 0`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      let errMsg=`setStoredValue - Characteristic index: -1 not between 0 and ${ ACC_EOL }\\nCheck your config.json file for unknown characteristic.`;\n      expect ( ( ) => accessory.cmd4Storage.setStoredValueForIndex( -1, 0 ) ).to.throw(errMsg);\n\n   });\n\n   it( `Check setStoredValueForIndex throws error with accTypeEnumIndex >= EOL`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      let errMsg=`setStoredValue - Characteristic index: ${ ACC_EOL } not between 0 and ${ ACC_EOL }\\nCheck your config.json file for unknown characteristic.`;\n      expect ( ( ) => accessory.cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.EOL, 0 ) ).to.throw(errMsg);\n\n   });\n\n   it( `Check getStoredValue works correctly for a Switch`, ( ) =>\n   {\n      let config =\n      {\n         displayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      let STORED_DATA_ARRAY = [ ];\n      let accessory = new Cmd4Accessory( log, config, _api, STORED_DATA_ARRAY );\n\n\n      let newValue = true;\n      let value;\n      let characteristicString;\n\n      accessory.cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, newValue );\n\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_ACC_TYPE_ENUM.properties[ index ].deprecated == true )\n             continue;\n\n         characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( index );\n         value = STORED_DATA_ARRAY[0].cmd4Storage.DATA[ index ];\n         if ( index == CMD4_ACC_TYPE_ENUM.On )\n            assert.isTrue( value, `Expected accessory.STORED_DATA_ARRAY( ${ index } ) to be False using index ${ index}` );\n         else\n            assert.isNull( value, `Expected accessory.STORED_DATA_ARRAY( ${ index } ) to be null using index ${ index}` );\n      }\n      let result = accessory.cmd4Storage.getStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On );\n      assert.equal( result, newValue, `Unexpected getStoredValueForIndex( ${ CMD4_ACC_TYPE_ENUM.On }` );\n\n      characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n      result = accessory.cmd4Storage.getStoredValueForCharacteristic( characteristicString);\n      assert.equal( result, newValue, `Unexpected getStoredValueForCharacteristic( ${ characteristicString }` );\n\n\n   });\n\n   it( `Check getStoredValueForIndex throws error with accTypeEnumIndex < 0`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      let errMsg=`getStoredValue - Characteristic index: -1 not between 0 and ${ ACC_EOL }\\nCheck your config.json file for unknown characteristic.`;\n      expect ( ( ) => accessory.cmd4Storage.getStoredValueForIndex( -1 ) ).to.throw(errMsg);\n\n   });\n\n   it( `Check getStoredValueForIndex throws error with accTypeEnumIndex >= EOL`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      let errMsg=`setStoredValue - Characteristic index: ${ ACC_EOL } not between 0 and ${ ACC_EOL }\\nCheck your config.json file for unknown characteristic.`;\n      expect ( ( ) => accessory.cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.EOL, 0 ) ).to.throw(errMsg);\n\n   });\n\n   it( `Check testStoredValue works correctly for a Switch`, ( ) =>\n   {\n      let config =\n      {\n         displayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n      log.setBufferEnabled( );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      let characteristicString = accEnumIndexToC( CMD4_ACC_TYPE_ENUM.On );\n\n      config.On = true;\n      let newValue = true;\n      accessory.cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, newValue );\n\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_ACC_TYPE_ENUM.properties[ index ].deprecated == true )\n             continue;\n\n         characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( index );\n         let value = accessory.cmd4Storage.testStoredValueForIndex( index );\n\n         let cvalue = accessory.cmd4Storage.testStoredValueForCharacteristic( characteristicString );\n         if ( index == CMD4_ACC_TYPE_ENUM.On )\n         {\n            assert.equal( value, newValue, `Unexpected return value for accessory.testStoredValueForIndex( ${ index } ) using index ${ index}` );\n            assert.equal( cvalue, newValue, `Unexpected return value for accessory.testStoredValueForCharacteristic( ${ characteristicString } ) using index ${ index}` );\n         }\n         else\n         {\n            assert.isNull( value, `Expected return value for accessory.testStoredValueForIndex( ${ index } ) to be null using index ${ index}` );\n            assert.isNull( cvalue, `Expected return value for accessory.testStoredValueForCharacteristic( ${ characteristicString } ) to be null using index ${ index}` );\n         }\n      }\n\n   });\n\n   it( `Check testStoredValue limits returns undefined`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      let value, index;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n\n      // Test below zero\n      index = -1;\n      value = accessory.cmd4Storage.testStoredValueForIndex( index );\n      assert.isUndefined( value, `Expected accessory.testStoredValueForIndex( ${ index } ) to return undefind` );\n\n      // Test not given\n      value = accessory.cmd4Storage.testStoredValueForCharacteristic( );\n      assert.isUndefined( value, `Expected accessory.testStoredValueForCharacteristic() to return undefined` );\n\n\n      // Test above EOL\n      index = ACC_EOL + 1;\n      value = accessory.cmd4Storage.testStoredValueForIndex( index );\n      assert.isUndefined( value, `Expected accessory.testStoredValueForIndex( ${ index } ) to return undefined` );\n\n      // Test not given\n      value = accessory.cmd4Storage.testStoredValueForCharacteristic( \"Does not exist\" );\n      assert.isUndefined( value, `Expected accessory.testStoredValueForCharacteristic() to return undefined` );\n\n\n\n   });\n\n   it( `Check that Array STORED_DATA_ARRAY.cmd4Storage is created`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.instanceOf( accessory.STORED_DATA_ARRAY[0].cmd4Storage, Cmd4Storage, `Expected accessory.STORED_DATA_ARRAY[0].cmd4Storage to be an instance of Cmd4Storage. Found ${ typeof accessory.STORED_DATA_ARRAY[0].cmd4Storage }` );\n\n   });\n\n});\n\ndescribe('Cmd4Accessory Test parseConfig', ( ) =>\n{\n   it( \"Check that invalid category throws an error\", ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         category:                        \"Bad\"\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Category specified: \"Bad\" is not a valid homebridge category for: \"Test Switch\"./);\n   });\n\n   it( `Check that queue is already defined before use throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         queue:                            \"A\"\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/\"QueueType\" must be defined first for queue \"A\" in: \"Test Switch\"/);\n   });\n\n   it( `Check that type is defined for an accessory throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Unknown device type: \"undefined\" given in: \"Test Switch\"./);\n   });\n\n   it( `Check that unknown type is defined for an accessory throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Sink\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Unknown device type: \"Sink\" given in: \"Test Switch\"./);\n   });\n\n   it( `Check that lower case type gives a warning and continues`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n      log.setDebugEnabled( false );\n\n      new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.include( log.logBuf, `[34mCmd4 is running in Demo Mode for Test Switch`, `Incorrect stdout: ${ log.logBuf }` );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for Test Switch\", `Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mThe config.json Cmd4 device type: switch is lowerCase.  It should be: Switch. In the near future this will be an error for homebridge-UI integration`, ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n\n      assert.equal( 1, log.logLineCount, ` To many logged lines: ${ log.logBuf }` );\n      assert.equal( 1, log.errLineCount, ` To many logged lines: ${ log.errBuf }` );\n   });\n\n   it( `Check that upper case Cmd4 directive gives a warning and continues`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         DisplayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n      log.setDebugEnabled( false );\n\n      let cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.instanceOf( cmd4Accessory , Cmd4Accessory, `Expected cmd4Accessory to be instance of Cmd4Accessory.` );\n\n      assert.include( log.logBuf, `[34mCmd4 is running in Demo Mode for Test Switch`, `Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mThe config.json Cmd4 Directive: DisplayName is Capitalized.  It should be: displayName. In the near future this will be an error for homebridge-ui integration`, ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n\n      assert.equal( 1, log.logLineCount, ` To many logged lines: ${ log.logBuf }` );\n      assert.equal( 1, log.errLineCount, ` To many logged lines: ${ log.errBuf }` );\n   });\n\n   it( `Check that upper case Cmd4 Characteristic gives a warning and continues`, ( ) =>\n   {\n      let config =\n      {\n         Name:                            \"Test Switch\",\n         displayName:                     \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( );\n      log.setDebugEnabled( false );\n\n      let cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.instanceOf( cmd4Accessory , Cmd4Accessory, `Expected cmd4Accessory to be instance of Cmd4Accessory.` );\n\n      assert.include( log.logBuf, `[34mCmd4 is running in Demo Mode for Test Switch`, `Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mThe config.json characteristic key: Name is Capitalized.  It should be: name. In the near future this will be an error for homebridge-ui integration`, ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n\n      assert.equal( 1, log.logLineCount, ` To many logged lines: ${ log.logBuf }` );\n      assert.equal( 1, log.errLineCount, ` To many logged lines: ${ log.errBuf }` );\n   });\n\n   it( `Check that empty state_cmd for an accessory throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                          true,\n         state_cmd:                       false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/No state_cmd for: \"Test Switch\"./);\n   });\n\n   it( `Check that invalid characteristic for an accessory throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         Xon:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/OOPS: \"Xon\" not found for parsing characteristics in: \"Test Switch\"./);\n   });\n\n   it( `Check that upper case characteristic for an accessory generates a warning`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",  // Should be  lower case name\n         type:                            \"Switch\",\n         on:                               false\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n      log.setDebugEnabled( false );\n\n\n      new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for Test Switch\", `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n\n      assert.equal( 1, log.logLineCount, ` To many logged lines: ${ log.logBuf }` );\n      assert.equal( 0, log.errLineCount, ` To many logged lines: ${ log.errBuf }` );\n   });\n\n   it( `Check that invalid polling type (string throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                   \"Test Switch\",\n         type:                   \"Switch\",\n         on:                     false,\n         polling:                \"yes\",\n         state_cmd:              `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Unknown type for Polling \"yes\" given in: \"Test Switch\"./);\n   });\n\n   it( `Check that invalid polling characteristic for an accessory throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         [{ characteristic: \"XOn\"}],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/No such polling characteristic: \"XOn\" for: \"Test Switch\"./);\n   });\n\n   it( `Check that polling characteristic is also defined throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         [{ characteristic: \"active\"}],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Polling for: \"active\" requested, but characteristic is not in your config.json file for: \"Test Switch\"./);\n   });\n\n   it( `Check that polling characteristic is invalid throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         [{ \"XOn\": 15 }],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( true );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/OOPS: \"XOn\" not found while parsing for characteristic polling of \"Test Switch\". There something wrong with your config.json file?/);\n\n   });\n\n   it( `Check that no polling characteristic defined throws an error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         [{ interval: 15 }],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setOutputEnabled( false );\n      log.setBufferEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/No characteristic found while parsing for characteristic polling of: \"Test Switch\". There something wrong with your config.json file?/);\n   });\n\n   it( `Check that Constant definitions work`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let parentInfo={ \"CMD4\": constants.PLATFORM,\n                       \"LEVEL\": -1,\n                       \"globalConstants\": [\n                          { \"key\": \"${psk}\", \"value\": \"123456\" },\n                          { \"key\": \"${ipaddress}\", \"value\": \"12Aa34bbcc\" },\n                          { \"key\": \"${port}\", \"value\": \"8091\" }\n                       ]\n                     };\n\n      new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.equal( log.logBuf, \"\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it( `Check that Constant key starts with \\${ works or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         constants: [\n            { key: \"{psk}\", value: \"123456\" }\n         ],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Constant definition for: \"{psk}\" must start with \"\\${\" for clarity./);\n\n   });\n\n   it( `Check that Constant key ends with } works or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         constants: [\n            { key: \"${psk\", value: \"123456\" }\n         ],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Constant definition for: \"\\${psk\" must end with \"}\" for clarity./);\n\n   });\n\n   it( `Check that Constant is an array/list or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         constants:\n            { key: \"${psk}\", value: 1 },\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Constants must be an array of { \"key\": \"\\${SomeKey}\", \"value\": \"some replacement string\" }/ );\n\n   });\n\n   it( `Check that variable definitions work`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         variables: [\n            { key: \"${psk}\", value: \"123456\" },\n            { key: \"${ipaddress}\", value: \"12Aa34bbcc\" },\n            { key: \"${port}\", value: \"8091\" }\n         ],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.equal( log.logBuf, \"\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it( `Check that variable key starts with \\${ works or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         variables: [\n            { key: \"{psk}\", value: \"123456\" }\n         ],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Variable definition for: \"{psk}\" must start with \"\\${\" for clarity./);\n\n   });\n\n   it( `Check that variable key ends with } works or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         variables: [\n            { key: \"${psk\", value: \"123456\" }\n         ],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Variable definition for: \"\\${psk\" must end with \"}\" for clarity./);\n\n   });\n\n   it( `Check that Variables is an array/list or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         variables:                     \"${psk}:1\",\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/Variables must be an array of { \"key\": \"\\${SomeKey}\", \"value\": \"some replacement string\" }/);\n\n   });\n\n   it( `Check that url definitions work`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         url:                         \"http:blah\",\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.equal( log.logBuf, \"\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it( `Check that url is a string or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         url:                             15,\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/url must be a string: \"15\"./);\n\n   });\n\n   it( `Check that requires definitions work`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         requires: [\n            { \"require\": \"${fs}\" },\n            { \"require\": \"http\" }\n         ],\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let parentInfo={ \"CMD4\": constants.PLATFORM,\n                       \"LEVEL\": -1,\n                       \"globalConstants\": [\n                          { \"key\": \"${fs}\", \"value\": \"fs\" }\n                       ]\n                     };\n\n      new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.equal( log.logBuf, \"\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it( `Check that requires is an array or throws error`, ( ) =>\n   {\n      let config =\n      {\n         name:                            \"Test Switch\",\n         type:                            \"Switch\",\n         on:                               false,\n         polling:                         true,\n         requires:                             15,\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      expect ( ( ) => new Cmd4Accessory( log, config, _api, [ ] ) ).to.throw(/requires must be an array of { \"require\": \"some requires string\" }/ );\n\n   });\n\n});\ndescribe('Cmd4Accessory Test determineCharacteristicsToPollOfAccessoryAndItsChildren', ( ) =>\n{\n   afterEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   it( `Check that cmd4Storage gets created`, ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"Test Switch\",\n         type:                         \"Switch\",\n         on:                            false,\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`,\n         interval:                      10,                // seconds\n         stateChangeResponseTime:       1,                 // seconds\n         timeout:                       6000,              // msec\n         polling:                       true\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.instanceOf( accessory.STORED_DATA_ARRAY[0].cmd4Storage, Cmd4Storage, `Expected accessory.STORED_DATA_ARRAY[0].cmd4Storage to be an instance of Cmd4Storage. Found ${ typeof accessory.STORED_DATA_ARRAY[0].cmd4Storage }` );\n\n      done( );\n   });\n\n   it( `Check that storedValuesPer Array size is: ${ ACC_EOL }`, ( ) =>\n   {\n      let config =\n      {\n         name:                         \"Test Switch\",\n         type:                         \"Switch\",\n         on:                            false,\n         state_cmd:                    `node ${ home }/.homebridge/Cmd4Scripts/State.js`,\n         interval:                      10,                // seconds\n         stateChangeResponseTime:       1,                 // seconds\n         timeout:                       6000,              // msec\n         polling:                       true\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.equal( Object.keys(accessory.STORED_DATA_ARRAY[0].cmd4Storage.DATA).length, ACC_EOL, `Expected accessory.STORED_DATA_ARRAY[0].cmd4Storage to be size: ${ ACC_EOL }` );\n\n   });\n\n   it('Polling complains related polling characteristic is missing', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:            0,\n            targetPosition:             0,\n            positionState:              0,\n            polling:                   [ { \"characteristic\": \"currentPosition\" },\n                                         { \"characteristic\": \"positionState\" } ],\n            state_cmd:    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, `cmd4Platform is not an instance of Cmd4Platform` );\n\n      this.config = platformConfig.accessories;\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.errBuf, `[33mWarning, With polling for \"currentPosition\" requested, you also must do polling of \"targetPosition\" or things will not function properly` , `expected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it( `Test Polling generates log.if related characteristic not polled also`, function( )\n   {\n      let thermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"Inactive\",\n         currentTemperature:            20.0,\n         targetTemperature:             20.0,\n         currentHeatingCoolingState:    0,\n         targetHeatingCoolingState:     0,\n         polling:                      [{characteristic: \"currentTemperature\", interval: 60, timeout:2000}],\n         state_cmd:                    \"./test/echoScripts/echo_quoted0\"\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n\n      let parentInfo = { };\n      new Cmd4Accessory( log, thermostatConfig, _api, [ ], parentInfo );\n\n      assert.equal( log.logBuf, \"\", ` Cmd4Accessory Unexpected stdout: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mWarning, With polling for \"currentTemperature\" requested, you also must do polling of \"targetTemperature\" or things will not function properly`, ` Cmd4Accessory Incorrect stderr: ${ log.errBuf }` );\n\n   });\n\n   it( `Test linked accessory gets \\${IP} constant sent to it.`, ( done ) =>\n   {\n      let platformConfig =\n      {\n         platform:                  \"Cmd4\",\n         constants: [ { key: \"${IP}\", value: \"192.168.2.65\"} ],\n         queueTypes: [ { queueType: \"WoRm\", queue: \"A\"} ],\n         accessories: [\n         {\n            type: \"Thermostat\",\n            displayName: \"Aircon\",\n            currentHeatingCoolingState: \"OFF\",\n            targetHeatingCoolingState: \"OFF\",\n            currentTemperature: 24,\n            targetTemperature: 24,\n            temperatureDisplayUnits: \"CELSIUS\",\n            name: \"Aircon\",\n            manufacturer: \"Advantage Air Australia\",\n            model: \"e-zone\",\n            serialNumber: \"Daikin e-zone\",\n            queue: \"A\",\n            polling: [\n                 { characteristic: \"currentHeatingCoolingState\" },\n                 { characteristic: \"targetHeatingCoolingState\" },\n                 { characteristic: \"currentTemperature\" },\n                 { characteristic: \"targetTemperature\" }\n             ],\n             state_cmd: \"'/usr/local/lib/node_modules/homebridge-cmd4-advantageair/AdvAir.sh'\",\n             state_cmd_suffix: \"${IP} noSensors\",\n             linkedTypes: [\n             {\n                 type: \"Fan\",\n                 displayName: \"Fan Speed\",\n                 on: \"FALSE\",\n                 rotationSpeed: 100,\n                 name: \"Fan Speed\",\n                 manufacturer: \"Advantage Air Australia\",\n                 model: \"e-zone\",\n                 serialNumber: \"Daikin e-zone\",\n                 queue: \"A\",\n                 polling: [\n                     { characteristic: \"on\" },\n                     { characteristic: \"rotationSpeed\" }\n                 ],\n                 state_cmd: \"'/usr/local/lib/node_modules/homebridge-cmd4-advantageair/AdvAir.sh'\",\n                 state_cmd_suffix: \"fanspeed ${IP}\"\n             }]\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 2, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      // The linked accessory is actually at index 0\n      let lightbulbAccessory = cmd4Platform.createdCmd4Accessories[0];\n      // The main accessory is actually at index 1\n      let thermostatAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Aircon LEVEL: 0`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Creating linked accessories for: Aircon`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[34mCreating Linked Platform Accessory type for : Fan Speed LEVEL: 1`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n\n      assert.equal( thermostatAccessory.displayName, \"Aircon\", ` Thermostat has incorrect displayName` );\n      assert.equal( lightbulbAccessory.displayName, \"Fan Speed\", ` Lightbulb has incorrect displayName` );\n      assert.equal( thermostatAccessory.state_cmd_suffix, \" 192.168.2.65 noSensors\", ` Accessory has incorrect state_cmd_suffix` );\n      assert.equal( lightbulbAccessory.state_cmd_suffix, \" fanspeed 192.168.2.65\", ` Linked accessory has incorrect state_cmd_suffix` );\n\n      done( );\n\n   });\n\n   it( `Test Polling generates log for linked accessory if related characteristic not polled also`, ( ) =>\n   {\n      let thermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"Inactive\",\n         currentTemperature:            20.0,\n         targetTemperature:             20.0,\n         linkedTypes:\n         {\n            type:                      \"Thermostat\",\n            name:                      \"Linked_Thermostat\",\n            displayName:               \"Linked_Thermostat\",\n            temperatureDisplayUnits:   \"CELSIUS\",\n            active:                    \"Inactive\",\n            currentTemperature:         20.0,\n            targetTemperature:          20.0,\n            currentHeatingCoolingState: 0,\n            targetHeatingCoolingState:  0,\n            polling:                   [{characteristic: \"currentTemperature\", interval: 60, timeout:2000}],\n            state_cmd:                   \"./test/echoScripts/echo_quoted0\"\n         },\n         CurrentHeatingCoolingState:   0,\n         TargetHeatingCoolingState:    0,\n         polling:                     [{characteristic: \"currentTemperature\",\n                                        interval: 60,\n                                        timeout:  2000},\n                                       {characteristic: \"targetTemperature\",\n                                         interval: 60,\n                                         timeout:  2000}],\n         State_cmd:                     \"./test/echoScripts/echo_quoted0\"\n      };\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1 };\n      new Cmd4Accessory( log, thermostatConfig, _api, [ ], parentInfo );\n\n      assert.include( log.logBuf, `Creating linked accessories for: Thermostat`, ` Cmd4Accessory output expected. received: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mWarning, With polling for \"currentTemperature\" requested, you also must do polling of \"targetTemperature\" or things will not function properly`, ` Cmd4Accessory Incorrect stderr:: ${ log.errBuf }` );\n\n   });\n\n   it( `Test Non Platform accessories throws an error (Cmd4 8.0)`, ( ) =>\n   {\n      let platformConfig=\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"Inactive\",\n         currentTemperature:            20.0,\n         targetTemperature:             20.0,\n         currentHeatingCoolingState:    0,\n         targetHeatingCoolingState:     0,\n         polling:                      [{ characteristic:   \"currentTemperature\" },\n                                        { characteristic:   \"targetTemperature\" } ],\n         state_cmd:                      \"./test/echoScripts/echo_quoted0\",\n         accessories: [\n         {\n            accessory:                 \"Cmd4\",\n            statusMsg:                  true,\n            type:                      \"GarageDoorOpener\",\n            displayName:               \"StandaloneDoorOpener\",\n            name:                      \"StandaloneDoorOpener\",\n            currentDoorState:          \"CLOSED\",\n            targetDoorState:           \"CLOSED\",\n            obstructionDetected:       \"1\",\n            polling:                   [ { characteristic: \"currentDoorState\" },\n                                      // { characteristic: \"targetDoorState\" },\n                                         { characteristic: \"obstructionDetected\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      let errMsg=`Accessory: has been deprecated by homebridge. Only Platform confgurations are supported by Cmd4 >= 8.0 for: \"StandaloneDoorOpener\".`;\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(errMsg);\n\n\n   });\n\n});\n\n\ndescribe('Test Cmd4Accessory change characteristic Props', ( ) =>\n{\n   it('Test successful change Props definition ', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            type:                            \"TemperatureSensor\",\n            displayName:                     \"MyTemperatureSensor\",\n            name:                            \"MyTemperatureSensor\",\n            currentTemperature:               25,\n            statusFault:                     \"NO_FAULT\",\n            props: { CurrentTemperature: { maxValue: 100,\n                                           minValue: -100,\n                                           minStep: 0.1\n                                         }\n                   },\n            polling:                         [ { characteristic: \"currentTemperature\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      };\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      assert.instanceOf( cmd4Accessory , Cmd4Accessory, `Expected cmd4Accessory to be instance of Cmd4Accessory.` );\n\n      assert.include( log.logBuf, `[90mOverriding characteristic CurrentTemperature props for: MyTemperatureSensor`, `Incorrect stdout: ${ log.logBuf }` );\n\n      done( );\n   });\n\n});\n"
  },
  {
    "path": "test/Cmd4AccessoryGetValue.js",
    "content": "\"use strict\";\n\n// ***************** TEST LOADING **********************\n\n\nlet { Cmd4Platform } = require( \"../Cmd4Platform\" );\nlet { Cmd4Accessory } = require( \"../Cmd4Accessory\" );\n//const constants = require( \"../cmd4Constants\" );\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n  it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n  it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\ndescribe( \"Testing Cmd4Accessory\", function( )\n{\n   afterEach( ( ) =>\n   {\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n   });\n\n  it( \"Test if Cmd4Accessory exists\", function ( )\n   {\n      expect( Cmd4Accessory ).not.to.be.a( \"null\", \"Cmd4Accessory was null\" );\n   });\n\n  it( \"Test init Cmd4Accessory\", function( )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                        \"MyTelevision\",\n            type:                        \"Television\",\n            category:                    \"TELEVISION\",\n            publishExternally:           true,\n            active:                      \"ACTIVE\",\n            activeIdentifier:             1234,\n            mute:                        true,\n            configuredName:              \"MyTelevision\",\n            sleepDiscoveryMode:          \"ALWAYS_DISCOVERABLE\",\n            brightness:                   8,\n            closedCaptions:              \"DISABLED\",\n            currentMediaState:           \"STOP\",\n            targetMediaState:            \"STOP\",\n            pictureMode:                 \"STANDARD\",\n            remoteKey:                   \"SELECT\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n   });\n\n  it( \"Test Cmd4Accessory.queue.priorityGetValue\", function( )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_ACTIVE\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n   });\n\n/* Characteristic.getValue() is deprecated in V2 and Characteristic.value does not call the\n * get functions.\n  it( \"getValue active should inject 1 to Hombridge for ACTIVE response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_ACTIVE\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.equal( log.logBuf, \"\", ` getValue Unexpected stdout: ${ log.logBuf }` );\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 2000 );\n   }).timeout( 3000 );\n\n  it( \"getValue Active should inject 0 to Hombridge for INACTIVE response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_INACTIVE\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mgetValue: Active function for: MyTelevision returned: INACTIVE`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Active for: MyTelevision transposed: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` getValue unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1900);\n   });\n\n  it( \"getValue active should inject 0 to Hombridge for 0 response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_0\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"Active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mgetValue: Active function for: MyTelevision returned: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` getCachedValue unexpected stderr: ${ log.errBuf }` );\n\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Active should inject 1 to Hombridge for 1 response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_1\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"Active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Active function for: MyTelevision returned: 1`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Active should inject 0 to Hombridge for quoted0 response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_quoted0\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"Active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Active function for: MyTelevision returned: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Active should inject 1 to Hombridge for quoted1 response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_quoted1\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"Active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Active function for: MyTelevision returned: 1`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Mute should inject false to Hombridge for false response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            polling:                  true,\n            state_cmd:                \"./test/echoScripts/echo_INACTIVE\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Active ]\n             .characteristic ).getValue( \"Active\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Active function for: MyTelevision returned: INACTIVE`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Active for: MyTelevision transposed: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Mute should inject true to Hombridge for true response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_true\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute function for: MyTelevision returned: true`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute for: MyTelevision transposed: 1`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Mute should inject false to Hombridge for 0 response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_0\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mgetValue: Mute function for: MyTelevision returned: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute function for: MyTelevision returned: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Mute should inject true to Hombridge for 1 response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_1\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute function for: MyTelevision returned: 1`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Mute should inject false to Hombridge for quotedFalse response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_quotedFALSE\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute function for: MyTelevision returned: False`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute for: MyTelevision transposed: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue Mute should inject true to Hombridge for quotedTrue response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_quotedTRUE\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute function for: MyTelevision returned: True`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: Mute for: MyTelevision transposed: 1`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue ClosedCaptions should inject 0 to Hombridge for DISABLED response\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since ClosedCaptions is optional\n            polling:                  [{ characteristic: \"closedCaptions\" }],\n            state_cmd:                \"./test/echoScripts/echo_DISABLED\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.ClosedCaptions ]\n             .characteristic ).getValue( \"ClosedCaptions\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: ClosedCaptions function for: MyTelevision returned: DISABLED`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: ClosedCaptions for: MyTelevision transposed: 0`, ` getValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n   //HERE\n  it( \"getValue of empty response should fail correctly\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_nothing\",\n            timeout:                  500\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         assert.include( log.errBuf, `[31mgetValue: Mute function for: MyTelevision returned an empty string \"\"`, ` getValue Incorrect stderr: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 2, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n\n   });\n\n  it( \"getValue of null response should fail correctly\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_null\",\n            timeout:                  500\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         assert.include( log.errBuf, `getValue: \"null\" returned from stdout for Mute MyTelevision`, ` getValue Incorrect stderr: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 2, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue of echo true rc=1 response pass with error message\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_true_withRcOf1\",\n            timeout:                  500\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         // The script error\n         assert.include( log.errBuf, `[31m\\u001b[31mgetValue Mute function failed for MyTelevision cmd: ./test/echoScripts/echo_true_withRcOf1 Get 'MyTelevision' 'Mute' Failed. Error: 1`, ` getValue Incorrect stderr: ${ log.errBuf }` );\n\n         // The ( error ) returned from exec\n         assert.include( log.errBuf, `[31mgetValue Mute function failed for MyTelevision cmd: ./test/echoScripts/echo_true_withRcOf1 Get 'MyTelevision' 'Mute' Failed.  Generated Error: Error: Command failed: ./test/echoScripts/echo_true_withRcOf1 Get 'MyTelevision' 'Mute'`, ` getValue Incorrect stderr: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 3, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n\n   });\n\n  it( \"getValue of quoted Null should fail correctly\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_quotedNULL\",\n            timeout:                  500\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         assert.include( log.errBuf, `getValue: Mute function for MyTelevision returned the string \"\"NULL\"\"`, ` getValue Incorrect stderr: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 2, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue of quoted Nothing should fail correctly\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_quotedNothing\",\n            timeout:                  500\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         assert.include( log.errBuf, `getValue: Mute function for: MyTelevision returned an empty string \"\" \"\"`, ` getValue Incorrect stdout: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 2, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue of Nothing to stdout and something to stderr should show error message\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/echo_errorToStderr\",\n            timeout:                  500\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.errBuf, \"[31mgetValue: Mute function for MyTelevision streamed to stderr: This message goes to stderr\", ` getValue Incorrect stderr: ${ log.errBuf }` );\n         assert.include( log.errBuf, `[31mgetValue: Mute function for: MyTelevision returned an empty string \"\"`, ` getValue Incorrect stderr: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 3, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue of Nothing to stdout and rc=0 should show error message\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            timeout:                  500,\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/justExitWithRCof0\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         assert.include( log.errBuf, `[31mgetValue: Mute function for: MyTelevision returned an empty string \"\"`, ` getValue incorrect stderr: ${ log.errBuf }` );\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MyTelevision\" getValue. Last error found Getting: \"Mute\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n         assert.equal( log.errLineCount, 2, `getValue: to many lines to stderr ${ log.errBuf }` );\n\n         done( );\n      }, 1500);\n   });\n\n  it( \"getValue of Nothing to stdout and rc=1 should show error message\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            timeout:                  500,\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/justExitWithRCof0\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n         assert.include( log.errBuf, `[31mgetValue: Mute function for: MyTelevision returned an empty string \"\"`, ` getValue incorrect stderr: ${ log.errBuf }` );\n\n         cmd4Accessory.state_cmd = \"./test/echoScripts/justExitWithRCof1\";\n         cmd4Accessory.timeout = 400;\n\n         // Call the getValue bound function, which is priorityGetValue\n         cmd4Accessory.service.getCharacteristic(\n            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n                .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n         setTimeout( ( ) =>\n         {\n\n            assert.include( log.errBuf, `getValue Mute function failed for MyTelevision cmd: ./test/echoScripts/justExitWithRCof1 Get 'MyTelevision' 'Mute' Failed.`, ` getValue incorrect stderr: ${ log.errBuf }` );\n\n            done( );\n\n         }, 700 );\n      }, 1500 );\n   }).timeout( 2500 );\n\n  it( \"getValue of timeout response should fail correctly\", function ( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"MyTelevision\",\n            type:                     \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"MyTelevision\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            timeout:                  400,\n                                      // Since Mute is optional\n            polling:                  [{ characteristic: \"mute\" }],\n            state_cmd:                \"./test/echoScripts/runToTimeoutRcOf0\"\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : MyTelevision`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: MyTelevision`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.isFunction( cmd4Accessory.queue.priorityGetValue, \"Cmd4Accessory.queue.priorityGetValue is not a function\" );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).getValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.errBuf, `[31mgetValue Mute function timed out 400ms for MyTelevision cmd: ./test/echoScripts/runToTimeoutRcOf0 Get 'MyTelevision' 'Mute' Failed`, ` getValue incorrect stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1500 );\n\n   });\n*/\n});\n"
  },
  {
    "path": "test/Cmd4AccessorySetValue.js",
    "content": "\"use strict\";\n\n// ***************** TEST LOADING **********************\n\n\nlet { Cmd4Accessory } = require( \"../Cmd4Accessory\" );\nlet { Cmd4Platform } = require( \"../Cmd4Platform\" );\n\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet Characteristic = _api.hap.Characteristic;\nlet Service = _api.hap.Service;\nlet Categories = _api.hap.Categories;\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, Service, Characteristic, Categories );\n\n\nlet getSetValueScript = \"./test/echoScripts/testGetSetValues.js\";\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\ndescribe( \"Testing Cmd4Accessory\", function( )\n{\n   it( \"Test if Cmd4Accessory exists\", function ( )\n   {\n      expect( Cmd4Accessory ).not.to.be.a( \"null\", \"Cmd4Accessory was null\" );\n   });\n\n   it( \"Test init Cmd4Accessory\", function( done )\n   {\n      // A config file to play with.\n      let platformConfig =\n      {\n         accessories:\n         [{\n             name:                     \"Television\",\n             type:                     \"Television\",\n             displayName:              \"Television\",\n             category:                 \"TELEVISION\",\n             publishExternally:        true,\n             active:                   \"ACTIVE\",\n             activeIdentifier:          1234,\n             mute:                     true,\n             configuredName:           \"Television\",\n             sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n             brightness:                8,\n             closedCaptions:           \"DISABLED\",\n             currentMediaState:        \"STOP\",\n             targetMediaState:         \"STOP\",\n             pictureMode:              \"STANDARD\",\n             remoteKey:                \"SELECT\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: Television`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      done( );\n   });\n\n   it( \"setValue 1 should send 1 to script for ClosedCaption non constant request\", function ( done )\n   {\n      // A config file to play with.\n      let fn = `/tmp/fn1`;\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"Television\",\n            type:                     \"Television\",\n            displayName:              \"Television\",\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            active:                   \"ACTIVE\",\n            activeIdentifier:          1234,\n            mute:                     true,\n            configuredName:           \"Television\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            polling:                  [{ characteristic: \"ClosedCaptions\" }],\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            state_cmd_suffix:         fn,\n            state_cmd:                `node ${ process.cwd( ) }/${ getSetValueScript }`\n         }]\n      };\n\n      // Note: We need a characteristic that does not have a verify characteristic\n      // because the getSetValueScript can't seem to handle it. At least not yet.\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n\n      let value = Characteristic.ClosedCaptions.ENABLED;\n      let acc = CMD4_ACC_TYPE_ENUM.ClosedCaptions;\n\n      cmd4Accessory.log.reset( );\n      cmd4Accessory.log.setDebugEnabled( false );\n\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `Setting Television ClosedCaptions\\u001b[39m 1`, ` setValue incorrect stdout: ${ log.logBuf }` );\n//ZZZ    assert.equal( 1, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` setCachedValue unexpected stderr: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n         done( );\n\n      }, 1000 );\n\n   });\n\n   it( `setValue 1, aka ENABLED should send \"ENABLED\" to script for constant request`, function ( done )\n   {\n      // A config file to play with.\n      let fn = `/tmp/fn2`;\n      let platformConfig =\n      {\n         accessories:\n         [{\n             name:                     \"Television\",\n             type:                     \"Television\",\n             outputConstants:          true,\n             displayName:              \"Television\",\n             category:                 \"TELEVISION\",\n             publishExternally:        true,\n             active:                   \"ACTIVE\",\n             activeIdentifier:          1234,\n             mute:                     true,\n             configuredName:           \"Television\",\n             sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n             brightness:                8,\n             closedCaptions:           \"DISABLED\",\n             polling:                  [{ characteristic: \"ClosedCaptions\" }],\n             currentMediaState:        \"STOP\",\n             targetMediaState:         \"STOP\",\n             pictureMode:              \"STANDARD\",\n             remoteKey:                \"SELECT\",\n             state_cmd:                `node ${ process.cwd( ) }/${ getSetValueScript }`,\n             state_cmd_suffix:          fn\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n\n      // Note: We need a characteristic that does not have a verify characteristic\n      // because the getSetValueScript can't seem to handle it. At least not yet.\n      let acc = CMD4_ACC_TYPE_ENUM.ClosedCaptions;\n\n      let value = Characteristic.ClosedCaptions.ENABLED;\n\n      cmd4Accessory.log.reset( );\n      cmd4Accessory.log.setDebugEnabled( false );\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mSetting Television ClosedCaptions\\u001b[39m ENABLED`, `incorrect stdout: ${ log.logBuf }` );\n//ZZZ    assert.equal( 1, log.logLineCount, ` setValue logged lines than one: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` setValue unexpected error output received: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setValue logged Error lines more than one: ${ log.errBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `Cmd4Accessory should generate warning for publishExternally`, function ( done )\n   {\n      // A config file to play with.\n      let fn = `/tmp/fn2`;\n      let platformConfig =\n      {\n         accessories:\n         [{\n             name:                     \"Television\",\n             type:                     \"Television\",\n             outputConstants:          true,\n             displayName:              \"Television\",\n             category:                 \"TELEVISION\",\n             active:                   \"ACTIVE\",\n             activeIdentifier:          1234,\n             mute:                     true,\n             configuredName:           \"Television\",\n             sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n             brightness:                8,\n             closedCaptions:           \"DISABLED\",\n             currentMediaState:        \"STOP\",\n             targetMediaState:         \"STOP\",\n             pictureMode:              \"STANDARD\",\n             remoteKey:                \"SELECT\",\n             state_cmd: `node ${ process.cwd( ) }/${ getSetValueScript }`,\n             state_cmd_suffix:         fn\n         }]\n      };\n\n      // Note: We need a characteristic that does not have a verify characteristic\n      // because the getSetValueScript can't seem to handle it. At least not yet.\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.log.reset( );\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n\n      assert.include( log.errBuf, `Televisions should be Platform Accessories with \"publishExternally\": true`, `Cmd4Accessory incorrect stderr: ${ log.logBuf }` );\n      assert.equal( 1, log.errLineCount, ` Cmd4Accessory logged Error lines more than one: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it( \"setValue true should send 0 to script for Mute request\", function ( done )\n   {\n      // A config file to play with.\n      let fn = `/tmp/fn3`;\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                     \"Television\",\n            type:                     \"Television\",\n            displayName:              \"Television\",\n            active:                   true,\n            category:                 \"TELEVISION\",\n            publishExternally:        true,\n            activeIdentifier:          1234,\n            mute:                     1,\n            configuredName:           \"Television\",\n            sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n            brightness:                8,\n            closedCaptions:           \"DISABLED\",\n            currentMediaState:        \"STOP\",\n            targetMediaState:         \"STOP\",\n            pictureMode:              \"STANDARD\",\n            remoteKey:                \"SELECT\",\n            state_cmd_suffix:         fn,\n            state_cmd:                `node ${ process.cwd( ) }/${ getSetValueScript }`\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: Television`, ` cmd4Accessory incorrect stdout: ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n\n      let acc = CMD4_ACC_TYPE_ENUM.Mute;\n      let value = true;\n\n      cmd4Accessory.log.reset( );\n      cmd4Accessory.log.setDebugEnabled( false );\n      cmd4Accessory.log.setOutputEnabled( false );\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mSetting (Cached) Television Mute\\u001b[39m true`, ` setValue incorrect output. received: ${ log.logBuf }` );\n         assert.equal( 1, log.logLineCount, ` setValue logged lines than one: ${ log.stdout }` );\n         assert.equal( \"\", log.errBuf, ` setValue unexpected error output received: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setValue logged Error lines more than one: ${ log.errBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `setValue of cached \"Target*\" characteristic, should set \"Current*\" characteristic`, function ( done )\n   {\n      // A config file to play with.\n      let platformConfig =\n      {\n         accessories: [\n         {\n            type:                      \"Thermostat\",\n            name:                      \"Thermostat\",\n            displayName:               \"Thermostat\",\n            temperatureDisplayUnits:   \"CELSIUS\",\n            active:                    \"INACTIVE\",\n            currentTemperature:         20.0,\n            targetTemperature:          20.0,\n            targetHeatingCoolingState:  0,\n            stateChangeResponseTime:    3\n         }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, `Incorrect number of created accessories` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let acc = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = 12.3;\n\n      cmd4Accessory.log.reset( );\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n\n         assert.include( log.logBuf, `Setting (Cached) Thermostat TargetTemperature\\u001b[39m 12.3`, ` setCachedValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `Also Setting (Cached) Thermostat CurrentTemperature\\u001b[39m 12.3`, ` setCachedValue incorrect stdout: ${ log.logBuf }` );\n         assert.equal( 2, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` setCachedValue unexpected error output received: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setCachedValue err lines than one: ${ log.errBuf }` );\n\n         assert.equal(result, value, \" setValue incorrect storedValue.  found: \" + result );\n\n         let relatedCurrentAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[ acc ].relatedCurrentAccTypeEnumIndex;\n\n         result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( relatedCurrentAccTypeEnumIndex );\n         assert.equal(result, value, \" setValue relatedCurrentAccTypeEnumIndex incorrect stored value \" );\n\n         done( );\n\n      }, 2000 );\n\n   }).timeout(3000);\n\n   it( `In Demo mode, setValue of cached \"Target*\" characteristic, should set ALSO \"Current*\" characteristic`, function ( done )\n   {\n      // A config file to play with.\n      let ThermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:            20.0,\n         targetTemperature:             20.0,\n         currentHeatingCoolingState:    0,\n         targetHeatingCoolingState:     0,\n         stateChangeResponseTime:       3\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, ThermostatConfig, _api, [ ], null );\n\n      assert.include( log.logBuf, `[34mCmd4 is running in Demo Mode`, ` Cmd4Accessory: incorrect stdout: ${ log.logBuf }` );\n\n      let acc = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = 12.3;\n\n      cmd4Accessory.log.reset( );\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n\n         assert.include( log.logBuf, `Setting (Cached) Thermostat TargetTemperature\\u001b[39m 12.3`, ` setCachedValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `Also Setting (Cached) Thermostat CurrentTemperature\\u001b[39m 12.3`, ` setCachedValue incorrect stdout: ${ log.logBuf }` );\n         //assert.equal( 2, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` setCachedValue unexpected stderr: ${ log.errBuf }` );\n         //assert.equal( 0, log.errLineCount, ` setCachedValue err lines than one: ${ log.errBuf }` );\n\n         assert.equal(result, value, \" setValue incorrect stored value\" );\n\n         let relatedCurrentAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[ acc ].relatedCurrentAccTypeEnumIndex;\n\n         result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( relatedCurrentAccTypeEnumIndex );\n         assert.equal(result, value, \" setValue relatedCurrentAccTypeEnum incorrect value\" );\n\n         done( );\n\n      }, 1000 );\n\n   });\n\n   it( `setValue of cached \"Target*\" characteristic, should set ALSO \"Current*\" characteristic`, function ( done )\n   {\n      // A config file to play with.\n      let ThermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:           20.0,\n         targetTemperature:            20.0,\n         currentHeatingCoolingState:   0,\n         targetHeatingCoolingState:    0,\n         stateChangeResponseTime:      1,\n         polling:                      true,\n         state_cmd:                    \"./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, ThermostatConfig, _api, [ ], null );\n\n      let acc = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let value = 12.3;\n\n      cmd4Accessory.log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n\n         assert.include( log.logBuf, `Setting Thermostat TargetTemperature\\u001b[39m 12.3`, ` setCachedValue incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: CurrentTemperature function for: Thermostat returned: 12.3`, ` setValue incorrect stdout: ${ log.logBuf }` );\n\n         assert.equal( \"\", log.errBuf, ` setValue unexpected stderr: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setValue err lines than one: ${ log.errBuf }` );\n\n         assert.equal(result, value, \" setValue incorrect stored value\" );\n\n         let relatedCurrentAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[ acc ].relatedCurrentAccTypeEnumIndex;\n\n         result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( relatedCurrentAccTypeEnumIndex );\n         assert.equal(result, value, \" setValue relatedCurrentAccTypeEnum incorrect value\" );\n\n         done( );\n\n      }, 2500 );\n\n   }).timeout( 3000 );\n\n   it( `Missing required characteristic should generate a warning and add the characteristic`, function ( done )\n   {\n      // A config file to play with.\n      let ThermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:            20.0,\n         currentHeatingCoolingState:    0,\n         targetHeatingCoolingState:     0,\n         stateChangeResponseTime:       3\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, ThermostatConfig, _api, [ ], null );\n\n      let acc = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n\n      assert.include( log.logBuf, `[34mCmd4 is running in Demo Mode`, ` Cmd4Accessory: incorrect stdout: ${ log.logBuf }` );\n      assert.equal( 1, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n      assert.include( log.errBuf, `m**** Adding required characteristic TargetTemperature for Thermostat`, ` setCachedValue incorrect stdout:${ log.errBuf }` );\n      assert.include( log.errBuf, `Not defining a required characteristic can be problematic`, ` setCachedValue incorrect stdout: ${ log.errBuf }` );\n\n      assert.equal( 2, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n      let defaultValue = CMD4_DEVICE_TYPE_ENUM.properties[ cmd4Accessory.typeIndex ].requiredCharacteristics.find( key => key.type ===  acc ).defaultValue;\n\n      let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n      assert.equal(result, defaultValue, ` setValue incorrect stored value` );\n\n      done( );\n   });\n\n   it( `In Demo mode, Missing Optional characteristic should generate a warning and add the characteristic`, function ( done )\n   {\n      // A config file to play with.\n      let ThermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:            20.0,\n         targetTemperature:             20.0,\n         currentHeatingCoolingState:    0,\n         // targetHeatingCoolingState:  0,\n         stateChangeResponseTime:       3\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      new Cmd4Accessory( log, ThermostatConfig, _api, [ ], null );\n\n      assert.include( log.logBuf, `[34mCmd4 is running in Demo Mode`, ` Cmd4Accessory: incorrect stdout: ${ log.logBuf }` );\n\n      assert.equal( 1, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n      assert.include( log.errBuf, `**** Adding required characteristic TargetHeatingCoolingState for Thermostat`, ` setCachedValue incorrect stderr: ${ log.errBuf }` );\n      assert.include( log.errBuf, `Not defining a required characteristic can be problematic`, ` setCachedValue incorrect stderr: ${ log.errBuf }` );\n\n      assert.equal( 2, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n      done( );\n   });\n\n   it( `Missing Optional characteristic should generate a warning and add the characteristic`, function ( done )\n   {\n      // A config file to play with.\n      let ThermostatConfig =\n      {\n         type:                         \"Thermostat\",\n         name:                         \"Thermostat\",\n         displayName:                  \"Thermostat\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:           20.0,\n         targetTemperature:            20.0,\n         currentHeatingCoolingState:   0,\n         // targetHeatingCoolingState: 0,\n         stateChangeResponseTime:      3,\n         polling:                      true,\n         state_cmd:                    \"./test/echoScripts/echo_1\"\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      new Cmd4Accessory( log, ThermostatConfig, _api, [ ], null );\n\n      assert.equal( log.logBuf, \"\", ` Cmd4Accessory: unexpected stdout: ${ log.logBuf }` );\n      assert.equal( 0, log.logLineCount, ` Cmd4Accessory: incorrect number of lines to stdout: ${ log.logBuf }` );\n      assert.include( log.errBuf, `**** Adding required characteristic TargetHeatingCoolingState for Thermostat`, ` setCachedValue incorrect stderr: ${ log.errBuf }` );\n      assert.include( log.errBuf, `Not defining a required characteristic can be problematic`, ` setCachedValue incorrect stderr: ${ log.errBuf }` );\n\n      assert.equal( 2, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n      done( );\n   });\n\n\n   it( `In Demo mode, setValue of cached characteristic , should not set Current*\" characteristic on TemperatureSensor`, function ( done )\n   {\n      // A config file to play with.\n      let TempSensorConfig =\n      {\n         type:                         \"TemperatureSensor\",\n         name:                         \"TemperatureSensor\",\n         displayName:                  \"TemperatureSensor\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:            20.0\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, TempSensorConfig, _api, [ ], null );\n\n      let acc = CMD4_ACC_TYPE_ENUM.CurrentTemperature;\n      let value = 12.3;\n\n      cmd4Accessory.log.reset( );\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n\n\n         // You cannot set a read only value for a Sensor\n         assert.equal( log.logBuf, ``, ` setCachedValue should not occur, incorrect stdout: ${ log.logBuf }` );\n         assert.equal( 0, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` setCachedValue logged an error: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n         // The value should not be changed and be what is in the config.json\n         assert.equal(result, 20.0, \" setValue incorrect value\" );\n\n         let relatedTargetAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[ acc ].relatedTargetAccTypeEnumIndex;\n\n         result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( relatedTargetAccTypeEnumIndex );\n         assert.isNull(result, ` getValue TargetAccTypeEnumIndex expected null to be stored.` );\n\n         done( );\n      }, 1000 );\n   });\n\n   it( `setValue of cached characteristic , should not set Current*\" characteristic on TemperatureSensor`, function ( done )\n   {\n      // A config file to play with.\n      let TempSensorConfig =\n      {\n         type:                         \"TemperatureSensor\",\n         name:                         \"TemperatureSensor\",\n         displayName:                  \"TemperatureSensor\",\n         temperatureDisplayUnits:      \"CELSIUS\",\n         active:                       \"INACTIVE\",\n         currentTemperature:           20.0,\n         polling:                      true,\n         state_cmd:                    \"./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, TempSensorConfig, _api, [ ], null );\n\n      let acc = CMD4_ACC_TYPE_ENUM.CurrentTemperature;\n      let value = 12.3;\n\n      cmd4Accessory.log.reset( );\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ acc ]\n             .characteristic ).setValue( value, function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n\n\n         // You cannot set a read only value for a Sensor\n         assert.equal( log.logBuf, ``, ` setCachedValue should not occur, incorrect stdout: ${ log.logBuf }` );\n         assert.equal( 0, log.logLineCount, ` setCachedValue logged lines than one: ${ log.logBuf }` );\n         assert.equal( \"\", log.errBuf, ` setCachedValue logged an error: ${ log.errBuf }` );\n         assert.equal( 0, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n         // The value should not be changed and be what is in the config.json\n         assert.equal(result, 20.0, \" setValue incorrect value\" );\n\n         let relatedTargetAccTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties[ acc ].relatedTargetAccTypeEnumIndex;\n\n         result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( relatedTargetAccTypeEnumIndex );\n         assert.isNull(result, ` getValue TargetAccTypeEnumIndex expected null to be stored.` );\n\n         done( );\n      }, 1000 );\n   });\n\n   it( \"setValue of timeout response should fail correctly\", function ( done )\n   {\n      // A config file to play with.\n      let TVConfig =\n      {\n          name:                     \"MyTelevision\",\n          type:                     \"Television\",\n          category:                 \"TELEVISION\",\n          publishExternally:        true,\n          active:                   \"ACTIVE\",\n          activeIdentifier:          1234,\n          mute:                     true,\n          configuredName:           \"MyTelevision\",\n          sleepDiscoveryMode:       \"ALWAYS_DISCOVERABLE\",\n          brightness:                8,\n          closedCaptions:           \"DISABLED\",\n          currentMediaState:        \"STOP\",\n          targetMediaState:         \"STOP\",\n          pictureMode:              \"STANDARD\",\n          remoteKey:                \"SELECT\",\n          timeout:                  401,\n          polling:                  [{ characteristic: \"Mute\" }],\n          state_cmd:                \"./test/echoScripts/runToTimeoutRcOf0\"\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Accessory = new Cmd4Accessory( log, TVConfig, _api, [ ], null );\n      cmd4Accessory.timeout = 400;\n\n      // Call the setValue bound function, which is priorritySetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Mute ]\n             .characteristic ).setValue( \"Mute\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[34mSetting MyTelevision Mute\\u001b[39m 0`, ` setValue output something to stdout: ${ log.logBuf }` );\n         assert.include( log.errBuf, `[31m\\u001b[31msetValue Mute function failed for MyTelevision cmd: ./test/echoScripts/runToTimeoutRcOf0 Set 'MyTelevision' 'Mute' '0' Failed`, ` setValue incorrect stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1000 );\n   });\n\n});\n"
  },
  {
    "path": "test/Cmd4Mode.js",
    "content": "\"use strict\";\n\n// ***************** TEST LOADING **********************\n\n\nlet { Cmd4Platform } = require( \"../Cmd4Platform\" );\nlet { Cmd4Accessory } = require( \"../Cmd4Accessory\" );\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\ndescribe( \"Testing Demo Mode\", function( )\n{\n\n   beforeEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n\n   it( \"Test if Cmd4Accessory exists\", function ( )\n   {\n      expect( Cmd4Accessory ).not.to.be.a( \"null\", \"Cmd4Accessory was null\" );\n   });\n\n   it( \"V2 Crippled Test that getValue (Cached) occurs in Demo mode\", function( done )\n   {\n      let platformConfig =\n      {\n         accessories:\n         [{\n            name:                         \"MySwitch\",\n            type:                         \"Switch\",\n            on:                            false,\n           }]\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[35mConfiguring platformAccessory: \\u001b[39mMySwitch`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n      assert.include( log.logBuf, `[33mAdding getCachedValue for MySwitch characteristic: On`, ` cmd4Accessory incorrect stdout\": ${ log.logBuf }` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"Cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      //log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n/* Characteristic.getValue() is deprecated in V2 and Characteristic.value does not call the\n * get functions. Worked last in homebridge-1.8\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4Accessory.service.getCharacteristic(\n         CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n             .characteristic ).getValue( \"On\", function dummyCallback( ) { } );\n\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mgetCachedValue On for: MySwitch returned (CACHED) value: false`, ` getValue incorrect stdout: ${ log.logBuf }` );\n         assert.equal( log.errBuf, \"\", ` getValue Unexpected stderr: ${ log.errBuf }` );\n\n         done( );\n      }, 1000 );\n\n*/\n      // Added for homebridge v2 .getValue lines commented out above.\n      done();\n   }).timeout( 2000 );\n\n});\n"
  },
  {
    "path": "test/Cmd4Platform.js",
    "content": "#!node\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\nlet constants = require( \"../cmd4Constants\" );\n\nlet Cmd4Accessory = require( \"../Cmd4Accessory\" ).Cmd4Accessory;\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\nlet Cmd4PriorityPollingQueue = require( \"../Cmd4PriorityPollingQueue\" ).Cmd4PriorityPollingQueue;\n\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_CHAR_TYPE_ENUMS = CHAR_DATA.init( _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n// Taken from https://stackoverflow.com/questions/11731072/dividing-an-array-by-filter-function\n//function partition(array, predicate)\n//{\n//   return array.reduce( ( acc, item ) => ( acc[+!predicate( item )].push( item ), acc ), [ [], [] ] );\n//}\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\ndescribe( \"Quick Test of CMD4_CHAR_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_CHAR_TYPE_ENUMS should be defined ( required correctly )\", ( ) =>\n   {\n      assert.isNotNull( CMD4_CHAR_TYPE_ENUMS, \"CMD4_CHAR_TYPE_ENUMS is null\" );\n   });\n});\n\n\n\ndescribe('Testing Cmd4Platform Init', ( ) =>\n{\n   before( ( ) =>\n   {\n      sinon.stub( process, `exit` );\n   });\n   after( ( ) =>\n   {\n      process.exit.restore( );\n   });\n\n   beforeEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   afterEach(function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n   });\n\n   it( \"Test if Cmd4Platform exists\", function ( )\n   {\n      expect( Cmd4Platform ).not.to.be.a( \"null\", \"Cmd4Platform was null\" );\n   });\n\n   it( \"Test creation of Cmd4Platform\", function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n               name:                   \"MySwitch\",\n               displayName:            \"MySwitch\",\n               statusMsg:              true,\n               type:                   \"Switch\",\n               on:                     0,\n               active:                 0,\n               polling:                [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4Platform unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4Platform unexpected stderr received: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('Test if Cmd4Platform creates a platform accessory', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyDoor\",\n               displayName:            \"MyDoor\",\n               statusMsg:              true,\n               type:                   \"Door\",\n               currentPosition:        0,\n               targetPosition:         0,\n               positionState:          0,\n               polling:                [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      assert.include( log.logBuf, `Adding new platformAccessory: MyDoor`, ` Cmd4Platform Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `35mConfiguring platformAccessory: \\u001b[39mMyDoor`, ` Cmd4Platform Incorrect stdout: ${ log.logBuf}` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      assert.equal( cmd4Accessory.CMD4, constants.PLATFORM, ` Created accessory was not a PLATFORM accessory` );\n\n      done( );\n   });\n\n   it('Test if OutputConstants are used from the accessory', ( done ) =>\n   {\n      let platformConfig =\n      {\n         outputConstants:               true,\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                  true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      assert.equal( cmd4Platform.outputConstants, true, ` Created Platform has incorrect OutputConstants` );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      // it's a Hierarhy variable\n      assert.equal( cmd4Accessory.hV.outputConstants, true, ` Created Accessory has incorrect OutputConstants` );\n\n      done( );\n   });\n\n   it('Test if outputConstants are used from the accessory', ( done ) =>\n   {\n      let platformConfig =\n      {\n         outputConstants:              true,\n         accessories: [\n         {\n            outputConstants:           false,\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      // Heirarchy variable\n      assert.equal( cmd4Platform.hV.outputConstants, true, ` Created Platform has incorrect OutputConstants` );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      // it's a Hierarhy variable\n      assert.equal( cmd4Accessory.hV.outputConstants, false, ` Created Accessory has incorrect outputConstants` );\n\n      done( );\n   });\n\n   it('Test if interval, timeout, outputConstants, stateChangeResponseTime are used from the platform', ( done ) =>\n   {\n      let platformConfig =\n      {\n         timeout:                      12345,\n         interval:                     12,\n         stateChangeResponseTime:      18,\n         outputConstants:              true,\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      assert.equal( Object.keys( cmd4Accessory.listOfPollingCharacteristics ).length, 3, `Incorret number of polling characteristics` );\n\n      // it's a Hierarhy variable\n      assert.equal( cmd4Accessory.hV.timeout, 12345, `Timeout was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.interval, 12000, `Interval was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.stateChangeResponseTime, 18000, `stateChangeResponseTime was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.outputConstants, true, `outputConstants was not passed down to accessory` );\n\n      Object.keys( cmd4Accessory.listOfPollingCharacteristics ).forEach( ( key ) =>\n      {\n         let entry = cmd4Accessory.listOfPollingCharacteristics[ key ];\n         assert.equal( entry.timeout, 12345, `Timeout was not passed down to polling entry` );\n         assert.equal( entry.interval, 12000, `Interval was not passed down to polling entry` );\n         assert.equal( entry.stateChangeResponseTime, 18000, `stateChangeResponseTime was not passed down to polling entry` );\n      });\n\n      done( );\n   });\n\n\n   it('Test outputConstants, stateChangeResponseTime are used from the accessory definition', ( done ) =>\n   {\n      let platformConfig =\n      {\n         timeout:                       12345,\n         interval:                      12,\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            outputConstants:           true,\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      // it's a Hierarhy variable\n      assert.equal( cmd4Platform.hV.outputConstants, false, ` Created Platform has incorrect OutputConstants` );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      assert.equal( Object.keys( cmd4Accessory.listOfPollingCharacteristics ).length, 3, `Incorret number of polling characteristics` );\n\n      // it's a Hierarhy variable\n      assert.equal( cmd4Accessory.hV.timeout, 12345, `Timeout was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.interval, 12000, `Interval was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.stateChangeResponseTime, constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME, `stateChangeResponseTime was not passed from CMD4_DEVICE_TYPE_ENUM` );\n      assert.equal( cmd4Accessory.hV.outputConstants, true, ` Created Accessory has incorrect OutputConstants` );\n\n      Object.keys( cmd4Accessory.listOfPollingCharacteristics ).forEach( ( key ) =>\n      {\n         let entry = cmd4Accessory.listOfPollingCharacteristics[ key ];\n         assert.equal( entry.timeout, 12345, `Timeout was not passed down to polling entry` );\n         assert.equal( entry.interval, 12000, `Interval was not passed down to polling entry` );\n         assert.equal( entry.stateChangeResponseTime, constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME, `stateChangeResponseTime was not passed from CMD4_DEVICE_TYPE_ENUM` );\n      });\n\n      done( );\n   });\n\n   it('Test stateChangeResponseTime default is used for PriorityQueuedPolling', ( done ) =>\n   {\n      let platformConfig =\n      {\n         timeout:                      12345,\n         interval:                     12,\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      assert.equal( Object.keys( cmd4Accessory.listOfPollingCharacteristics ).length, 3, `Incorret number of polling characteristics` );\n\n      // it's a Hierarhy variable\n      assert.equal( cmd4Accessory.hV.timeout, 12345, `Timeout was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.interval, 12000, `Interval was not passed down to accessory` );\n      assert.equal( cmd4Accessory.hV.stateChangeResponseTime, constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME, `stateChangeResponseTime was not passed from CMD4_DEVICE_TYPE_ENUM` );\n\n      Object.keys( cmd4Accessory.listOfPollingCharacteristics ).forEach( ( key ) =>\n      {\n         let entry = cmd4Accessory.listOfPollingCharacteristics[ key ];\n         assert.equal( entry.timeout, 12345, `Timeout was not passed down to polling entry` );\n         assert.equal( entry.interval, 12000, `Interval was not passed down to polling entry` );\n         assert.equal( entry.stateChangeResponseTime, constants.MEDIUM_STATE_CHANGE_RESPONSE_TIME, `stateChangeResponseTime was not passed from CMD4_DEVICE_TYPE_ENUM` );\n      });\n\n      done( );\n   });\n\n   it('Test Cmd4Platform divies queues from staggered polling', ( done ) =>\n   {\n      let platformConfig =\n      {\n         timeout:                      12345,\n         interval:                     12,\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            type:                      \"Switch\",\n            on:                        0,\n            polling:                   [ { characteristic: \"on\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         },\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 2, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory1 = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4Accessory2 = cmd4Platform.createdCmd4Accessories[1];\n\n      assert.equal( Object.keys( cmd4Accessory1.listOfPollingCharacteristics ).length, 1, `Incorret number of polling characteristics for accessory 1` );\n      assert.equal( Object.keys( cmd4Accessory2.listOfPollingCharacteristics ).length, 3, `Incorret number of polling characteristics for accessory 2` );\n\n      let numberOfQueues = Object.keys( settings.listOfCreatedPriorityQueues ).length;\n\n      assert.equal( numberOfQueues, 2, `Incorrect number of polling queues` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"Q:MyDoor\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PriorityPollingQueue\" );\n\n      // Low priority queues are continious, make sure it is put back\n      assert.equal( queue.lowPriorityQueue.length, 3, `low priority queue should init to size 3` );\n\n      done( );\n   });\n\n   // Until we remove the successful add, it screw up other tests\n   it.skip('Test definition can be created successfully', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                         description: \"An X Coordinate\",\n                         props: { format: \"uint32\",\n                                  minValue: 0,\n                                  minStep: 1,\n                                   perms: [ \"pr\", \"pw\", \"ev\" ]\n                              },\n                       validValues: { }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      assert.include( log.logBuf, `Processing definition index: 0`, ` Cmd4Platform Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Created definition type: \"PointX\".`, ` Cmd4Platform Incorrect stdout: ${ log.logBuf }` );\n\n      done( );\n   });\n\n   // Until we remove the successful add, it screw up other tests\n   it.skip('Test definition with no validValues can be created successfully', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                       description: \"An X Coordinate\",\n                       props: { format: \"uint32\",\n                                minValue: 0,\n                                minStep: 1,\n                                perms: [ \"pr\", \"pw\", \"ev\" ]\n                              }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            State_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 1, ` Cmd4Platform did not create the cmd4Accessory` );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      assert.include( log.logBuf, `Processing definition index: 0`, ` Cmd4Platform Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Created definition type: \"PointX\".`, ` Cmd4Platform Incorrect stdout: ${ log.logBuf }` );\n\n      done( );\n   });\n\n   it('Test definition type must be string or throws error', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: true,\n                       description: \"An X Coordinate\",\n                       props: { format: \"uint32\",\n                                minValue: 0,\n                                minStep: 1,\n                                perms: [ \"pr\", \"pw\", \"ev\" ]\n                              },\n                       validValues: { }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      expect( ( ) => new Cmd4Platform( log, platformConfig, _api )).to.throw(/definition.type at index: 0 is not a String./);\n\n      done( );\n   });\n\n   it('Test definition description must be string or throws error', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                       props: { format: \"uint32\",\n                                minValue: 0,\n                                minStep: 1,\n                                perms: [ \"pr\", \"pw\", \"ev\" ]\n                              },\n                       validValues: { }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      expect( ( ) => new Cmd4Platform( log, platformConfig, _api )).to.throw(/definition.description at index: 0 is not a String./);\n\n      done( );\n   });\n\n   it('Test definition props must be an Object or throws error', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                        description: \"A point on X axis\",\n                        props: [],\n                       validValues: { }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      expect( ( ) => new Cmd4Platform( log, platformConfig, _api )).to.throw(/definition.props at index: 0 is not an Object./);\n\n      done( );\n   });\n\n   it('Test definition props.format must be string or throws error', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                        description: \"A point on X axis\",\n                       props: { format: 0,\n                                minValue: 0,\n                                minStep: 1,\n                                perms: [ \"pr\", \"pw\", \"ev\" ]\n                              },\n                       validValues: { }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      expect( ( ) => new Cmd4Platform( log, platformConfig, _api )).to.throw(/definition.props.format at index: 0 is not a String./);\n\n      done( );\n   });\n\n   it('Test definition props.format must be valid or throws error', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                        description: \"A point on X axis\",\n                       props: { format: \"ZERO\",\n                                minValue: 0,\n                                minStep: 1,\n                                perms: [ \"pr\", \"pw\", \"ev\" ]\n                              },\n                       validValues: { }\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      expect( ( ) => new Cmd4Platform( log, platformConfig, _api )).to.throw(/definition.props.format at index: 0 is not a valid format./);\n\n      done( );\n   });\n\n   it('Test definition validValues must be an Object or throws error', ( done ) =>\n   {\n      let platformConfig =\n      {\n         definitions: [{ type: \"PointX\",\n                        description: \"A point on X axis\",\n                       props: { format: \"uint32\",\n                                minValue: 0,\n                                minStep: 1,\n                                perms: [ \"pr\", \"pw\", \"ev\" ]\n                              },\n                        validValues: 1\n                     }],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      }\n\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      expect( ( ) => new Cmd4Platform( log, platformConfig, _api )).to.throw(/definition.validValues at index: 0 is not an Object./);\n\n      done( );\n   });\n\n\n   it('CameraControl throws error for deprecated device', ( ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            statusMsg:                 true,\n            type:                      \"CameraControl\",\n            displayName:               \"CameraControl\",\n            name:                      \"CameraControl\",\n            on:                        \"1\",\n            currentHorizontalTiltAngle: 12,\n            polling:                   [ { characteristic: \"currentHorizontalTiltAngle\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(/Error: device type: \"CameraControl\" is now deprecated in Homebridge/);\n\n   });\n\n\n});\n"
  },
  {
    "path": "test/Cmd4PlatformRestartTests.js",
    "content": "\"use strict\";\n\nconst settings = require( \"../cmd4Settings\" );\n\nvar __importDefault = (this && this.__importDefault) || function (mod) {\n    return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\n\n\n\n\n// For caching/uncaching accessories to disk, like homebridge does.\nconst node_persist_1 = __importDefault(require(\"node-persist\"));\n\nconst path = require( \"path\" );\nconst TEST_BASE_DIR = path.join(__dirname, \"tmp\");\n\nconst rmdir = require('rimraf');\n\nfunction rand(prefix)\n{\n  return (prefix ? prefix + '-' : '') + (+ new Date()) + '-' + Math.floor(Math.random() * 1000);\n}\nfunction randDir ()\n{\n   //return path.join(TEST_BASE_DIR, '/' + \"static\" );\n   return path.join(TEST_BASE_DIR, '/' + rand());\n}\n\nfunction loadCachedPlatformAccessoriesFromDisk( accessoryStorage, cachedAccessoriesFile = \"accessories\" )\n{\n   let cachedAccessories;\n\n   cachedAccessories = accessoryStorage.getItemSync( cachedAccessoriesFile );\n   if ( cachedAccessories )\n   {\n      return cachedAccessories.map(serialized =>\n      {\n          return platformAccessory_1.PlatformAccessory.deserialize(serialized);\n      });\n\n   } else {\n      console.log( `Woops, missing ${ cachedAccessoriesFile }` );\n   }\n}\n\nfunction restoreCachedPlatformAccessories( cmd4Platform, cachedPlatformAccessories )\n{\n\n   if ( cachedPlatformAccessories._associatedPlatform == settings.PLATFORM_NAME )\n   {\n      //console.log(\"stuffing:%s\", cachedPlatformAccessories );\n      cmd4Platform.configureAccessory( cachedPlatformAccessories );\n   }\n}\n\nfunction saveCachedPlatformAccessoriesOnDisk( cachedPlatformAccessories, accessoryStorage, cachedAccessoriesFile = \"accessories\"  )\n{\n\n   if ( cachedPlatformAccessories && cachedPlatformAccessories.length > 0 )\n   {\n      const serializedAccessories = cachedPlatformAccessories.map(Cmd4Accessory => platformAccessory_1.PlatformAccessory.serialize(Cmd4Accessory));\n      accessoryStorage.setItemSync( cachedAccessoriesFile, serializedAccessories );\n\n   } else {\n      console.log( `Woops, cachedPlatformAccessories ${ cachedPlatformAccessories } is empty/null` );\n   }\n}\n\n\n\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\n\n// A config file to play with.\nlet TVConfig =\n{\n   platform:                      \"Cmd4\",\n   outputConstants:               false,\n   cmd4_Mode:                     \"Demo\",\n   accessories:\n   [\n      {   type:                   \"Television\",\n          category:               \"TELEVISION\",\n          publishExternally:      false,\n          name:                   \"Example TV\",\n          active:                 \"ACTIVE\",\n          activeIdentifier:        1,\n          configuredName:         \"Example TV\",\n          manufacturer:           \"Example TV Mfg.\",\n          model:                  \"Example TV Model\",\n          serialNumber:           \"Example TV Sn.\",\n          sleepDiscoveryMode:     \"ALWAYS_DISCOVERABLE\",\n          accessories:\n          [\n             {   type:               \"TelevisionSpeaker\",\n                 displayName:        \"My TvSpeaker\",\n                 name:               \"My TVSpeaker\",\n                 active:             \"ACTIVE\",\n                 mute:               \"FALSE\",\n                 volumeSelector:     1,\n                 volume:             10,\n                 volumeControlType:  \"ABSOLUTE\"\n              }\n          ],\n          linkedTypes:\n          [\n             {   type:                   \"InputSource\",\n                 displayName:            \"HDMI1\",\n                 configuredName:         \"HDMI 1\",\n                 currentVisibilityState: \"SHOWN\",\n                 inputSourceType:        \"HDMI\",\n                 isConfigured:           \"CONFIGURED\",\n                 identifier:              1,\n                 targetVisibilityState:  \"SHOWN\",\n                 manufacturer:           \"HDMI 1 Mfg.\",\n                 model:                  \"HDMI 1 Model\",\n                 serialNumber:           \"HDMI 1 Sn.\",\n                 name:                   \"HDMI 1\"\n             },\n             {   type:                   \"InputSource\",\n                 displayName:             \"HDMI 2\",\n                 configuredName:         \"HDMI 2\",\n                 currentVisibilityState: \"SHOWN\",\n                 inputSourceType:        \"HDMI\",\n                 isConfigured:           \"CONFIGURED\",\n                 identifier:              2,\n                 targetVisibilityState:  \"SHOWN\",\n                 manufacturer:           \"HDMI 2 Mfg.\",\n                 model:                  \"HDMI 2 Model\",\n                 serialNumber:           \"HDMI 2 Sn.\",\n                 name:                   \"HDMI 2\"\n             },\n             {   type:                   \"InputSource\",\n                 displayName:            \"Netflix\",\n                 configuredName:         \"Netflix\",\n                 currentVisibilityState: \"SHOWN\",\n                 inputSourceType:        \"HDMI\",\n                 isConfigured:           \"CONFIGURED\",\n                 identifier:              3,\n                 targetVisibilityState:   \"SHOWN\",\n                 manufacturer:            \"Netflix Mfg.\",\n                 model:                   \"Netflix Model\",\n                 serialNumber:            \"Netflix Sn.\",\n                 name:                    \"Netflix\"\n              }\n           ],\n           displayOrder:              0,\n           currentMediaState:         \"STOP\",\n           targetMediaState:          \"STOP\",\n           pictureMode:               \"STANDARD\",\n           remoteKey:                 \"SELECT\"\n      }\n   ]\n};\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\n\n\n\ndescribe( \"Testing Cmd4Platform Setup\", function( )\n{\n   it( \"Test if Cmd4Platform exists\", function ( )\n   {\n      expect( Cmd4Platform ).not.to.be.a( \"null\", \"Cmd4Platform was null\" );\n   });\n\n   it( \"Test init Cmd4Platform\", function( )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, TVConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n\n      //expect( cmd4Platform.createdCmd4Platforms.length ).to.equal( 1, \"cmd4Platform.createdCmd4Platforms.length is not 1. Found:\" + cmd4Platform.createdCmd4Platforms.length );\n   });\n\n   it( \"Test node-persist\", function( )\n   {\n      let rc;\n      let options = {\n         dir: randDir(),\n         // logging: true\n      };\n\n      //after( function( done )\n     // {\n     //    rmdir( options.dir, done);\n      //});\n\n      const accessoryStorage = node_persist_1.default.create();\n\n      accessoryStorage.initSync( options ); // Setup Accessory Cache Storage\n\n      assert.ok( fs.existsSync( options.dir ) );\n\n      accessoryStorage.setItem( \"name\", \"yourName\" );\n\n      rc = accessoryStorage.getItem('name');\n\n      assert.equal(rc, 'yourName', `write/read didn't work`);\n\n      accessoryStorage.clear();\n\n   });\n\n});\n\ndescribe( \"Testing Cmd4Platform\", function( )\n{\n   const accessoryStorage = node_persist_1.default.create();\n\n   let options = {\n       dir: randDir(),\n       // logging: true\n   };\n\n   beforeEach(async function( )\n   {\n      await accessoryStorage.init( options );\n   });\n\n   after( function( done )\n   {\n      rmdir( options.dir, done );\n   });\n\n   it( \"Test trigger of Cmd4Platform.didFinishLoading\", function( )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform=new Cmd4Platform( log, TVConfig, _api );\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      // Instead of emitting didFinishLaunching which would cause other\n      // instances to also do the didFinishLaunching and start their polling\n      // as well,\n      cmd4Platform.discoverDevices( );\n\n\n      assert.equal(cmd4Platform.createdCmd4Platforms.length, 1, `Incorrect number of Cmd4Accessories created. result: ${ cmd4Platform.createdCmd4Platforms.length }` );\n\n      saveCachedPlatformAccessoriesOnDisk( cmd4Platform.createdCmd4Platforms, accessoryStorage )\n\n      loadCachedPlatformAccessoriesFromDisk( accessoryStorage );\n   });\n\n   it( \"Test reload of saved Platforms with value change to disk\", function( )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // We need our own instance as emitting \"didFinishLaunching\" triggers other testcases\n\n      let cmd4Platform = new Cmd4Platform( log, TVConfig, _api );\n\n      // Instead of emitting didFinishLaunching which would cause other\n      // instances to also do the didFinishLaunching and start their polling\n      // as well,\n      cmd4Platform.discoverDevices( );\n\n      assert.equal(cmd4Platform.createdCmd4Platforms.length, 1, `Incorrect number of Cmd4Platforms created. result: ${ cmd4Platform.createdCmd4Platforms.length }` );\n      assert.equal(cmd4Platform.createdCmd4Accessories.length, 5, `Incorrect number of Cmd4Accessories created. result: ${ cmd4Platform.createdCmd4Accessories.length }` );\n      // This would have been already tested in Cmd4AccessorySetValue.js\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[4];\n\n      let acc = CMD4_ACC_TYPE_ENUM.ConfiguredName;\n      let foundConfiguredName = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n      assert.equal( foundConfiguredName, TVConfig.accessories[0].configuredName, `Incorrect configuredName: ${ foundConfiguredName }` );\n\n      let newValue = \"NEW_TV\";\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n      cmd4Accessory.setCachedValue( acc, \"ConfiguredName\", newValue, function( rc )\n      {\n         assert.equal( rc, null, `setCachedValue expected: zero received: ${ rc }` );\n\n         assert.include( log.logBuf, `[34mSetting (Cached) Example TV ConfiguredName\\u001b[39m NEW_TV`, `setCachedValue Incorrect stdout: ${ log.logBuf }` );\n\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n         assert.equal( result, newValue, \" setCachedValue Incorrect result\" );\n\n         // Clear the log buffer for next time.\n         log.reset();\n\n         saveCachedPlatformAccessoriesOnDisk( cmd4Platform.createdCmd4Platforms, accessoryStorage  )\n\n         // Simulate a restart of homebridge with a new Cmd4Platform instance and the stored date reloaded.\n         let cachedPlatformAccessories = loadCachedPlatformAccessoriesFromDisk( accessoryStorage );\n\n         log.debug(\" *****  RUNNING NEXT PLATFORM *****  \" );\n         let cmd4Platform2 = new Cmd4Platform( log, TVConfig, _api );\n\n         cachedPlatformAccessories.forEach( ( entry ) =>\n         {\n            restoreCachedPlatformAccessories( cmd4Platform2, entry );\n         });\n\n         // Instead of emitting didFinishLaunching which would cause other\n         // instances to also do the didFinishLaunching and start their polling\n         // as well,\n         cmd4Platform2.discoverDevices( );\n\n         cmd4Accessory = cmd4Platform2.createdCmd4Accessories[4];\n         let newFoundConfiguredName = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n         assert.equal( newFoundConfiguredName, newValue, `Incorrect configuredName: ${  newFoundConfiguredName }` );\n\n      });\n\n      //restoreCachedPlatformAccessories( cmd4Platform, cachedPlatformAccessories );\n\n      //cmd4Platform.configureAccessory( cachedPlatformAccessories );\n\n      //expect( cmd4Platform.createdCmd4Accessories.length ).to.equal( 1, \"cmd4Platform.createdCmd4Accessories.length is not 1. Found:\" + cmd4Platform.createdCmd4Accessories.length );\n\n   });\n\n   it( \"Test reload of saved Platforms with value change to disk\", function( )\n   {\n      let SwitchConfig =\n      {\n         platform:                     \"Cmd4\",\n         accessories :\n         [\n            {   type:                   \"Switch\",\n                name:                   \"Example Switch\",\n                configuredName:         \"Example Switch\",\n                on:                     0\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // We need our own instance as emitting \"didFinishLaunching\" triggers other testcases\n\n      let cmd4Platform = new Cmd4Platform( log, SwitchConfig, _api );\n\n      // Instead of emitting didFinishLaunching which would cause other\n      // instances to also do the didFinishLaunching and start their polling\n      // as well,\n      cmd4Platform.discoverDevices( );\n\n      assert.equal(cmd4Platform.createdCmd4Platforms.length, 1, `Incorrect number of Cmd4Platforms created. result: ${ cmd4Platform.createdCmd4Platforms.length }` );\n      assert.equal(cmd4Platform.createdCmd4Accessories.length, 1, `Incorrect number of Cmd4Accessories created. result: ${ cmd4Platform.createdCmd4Accessories.length }` );\n      // This would have been already tested in Cmd4AccessorySetValue.js\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let acc = CMD4_ACC_TYPE_ENUM.ConfiguredName;\n      let foundConfiguredName = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n      assert.equal( foundConfiguredName, SwitchConfig.accessories[0].configuredName, `Incorrect configuredName: ${ foundConfiguredName }` );\n\n      let newValue = \"NEW_Switch\";\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n      cmd4Accessory.setCachedValue( acc, \"ConfiguredName\", newValue, function( rc )\n      {\n         cmd4Accessory.configuredName=newValue;\n         assert.equal( rc, null, `setCachedValue expected: zero received: ${ rc }` );\n\n         assert.include( log.logBuf, `[34mSetting (Cached) Example Switch ConfiguredName\\u001b[39m NEW_Switch`, `setCachedValue Incorrect stdout: ${ log.logBuf }` );\n\n         let result = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n         assert.equal( result, newValue, \" setCachedValue Incorrect result\" );\n\n         // Clear the log buffer for next time.\n         log.reset();\n\n         saveCachedPlatformAccessoriesOnDisk( cmd4Platform.createdCmd4Platforms, accessoryStorage  )\n\n         // Simulate a restart of homebridge with a new Cmd4Platform instance and the stored date reloaded.\n         let cachedPlatformAccessories = loadCachedPlatformAccessoriesFromDisk( accessoryStorage );\n\n         log.debug(\" *****  RUNNING NEXT PLATFORM *****  \" );\n         let cmd4Platform2 = new Cmd4Platform( log, SwitchConfig, _api );\n\n         cachedPlatformAccessories.forEach( ( entry ) =>\n         {\n            restoreCachedPlatformAccessories( cmd4Platform2, entry );\n         });\n\n         // Instead of emitting didFinishLaunching which would cause other\n         // instances to also do the didFinishLaunching and start their polling\n         // as well,\n         cmd4Platform2.discoverDevices( );\n\n         cmd4Accessory = cmd4Platform2.createdCmd4Accessories[0];\n         let newFoundConfiguredName = cmd4Accessory.cmd4Storage.getStoredValueForIndex( acc );\n         assert.equal( newFoundConfiguredName, newValue, `Incorrect configuredName: ${  newFoundConfiguredName }` );\n\n      });\n\n      //restoreCachedPlatformAccessories( cmd4Platform, cachedPlatformAccessories );\n\n      //cmd4Platform.configureAccessory( cachedPlatformAccessories );\n\n      //expect( cmd4Platform.createdCmd4Accessories.length ).to.equal( 1, \"cmd4Platform.createdCmd4Accessories.length is not 1. Found:\" + cmd4Platform.createdCmd4Accessories.length );\n\n   });\n\n   it( \"Test fix of bug#130, Linked types not accessable after restart\", function( )\n   {\n      // Note: I tested this by changing Cmd4Platform.js and putting back the old code and it failed. so this test is valid. the code being:\n      // ** WRONG **\n      // linkedAccessory.service = linkedAccessory.platform.getService( devProperties.service, linkedAccessory.name, linkedAccessory.subType );\n      // ** CORRECT **\n      // linkedAccessory.service = linkedAccessory.platform.getService( linkedAccessory.name, linkedAccessory.subType );\n      let LightConfig =\n      {\n         platform:  \"Cmd4\",\n         accessories:\n         [{\n             type:                     \"Lightbulb\",\n             displayName:              \"Light1\",\n             on:                       0,\n             stateChangeResponseTime:  1,\n             brightness:               100,\n             hue:                      200,\n             saturation:               100,\n             state_cmd:                \"node .homebridge/Cmd4Scripts/State.js\",\n//           polling:                  [ { characteristic: \"on\" },\n//                                       { characteristic: \"brightness\" }\n//                                     ],\n             linkedTypes: [{\n                type:                  \"Lightbulb\",\n                displayName:           \"Light2\",\n                on:                    0,\n                brightness:            0,\n                stateChangeResponseTime: 1,\n                state_cmd:             \"node .homebridge/Cmd4Scripts/State.js\",\n//              polling:               [ { characteristic: \"on\" },\n//                                       { characteristic: \"brightness\" }\n//                                     ]\n              }]\n\n         }]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // We need our own instance as emitting \"didFinishLaunching\" triggers other testcases\n\n      let cmd4Platform = new Cmd4Platform( log, LightConfig, _api );\n\n      // Instead of emitting didFinishLaunching which would cause other\n      // instances to also do the didFinishLaunching and start their polling\n      // as well,\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `Creating linked accessories for: Light1`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding getCachedValue for Light2 characteristic: Brightness`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      saveCachedPlatformAccessoriesOnDisk( cmd4Platform.createdCmd4Platforms, accessoryStorage  )\n\n      // Simulate a restart of homebridge with a new Cmd4Platform instance and the stored date reloaded.\n      let cachedPlatformAccessories = loadCachedPlatformAccessoriesFromDisk( accessoryStorage );\n\n      log.debug(\" *****  RUNNING NEXT PLATFORM *****  \" );\n      let cmd4Platform2 = new Cmd4Platform( log, LightConfig, _api );\n\n      cachedPlatformAccessories.forEach( ( entry ) =>\n      {\n         restoreCachedPlatformAccessories( cmd4Platform2, entry );\n      });\n\n      // Instead of emitting didFinishLaunching which would cause other\n      // instances to also do the didFinishLaunching and start their polling\n      // as well,\n      cmd4Platform2.discoverDevices( );\n\n      assert.include( log.logBuf, `Creating linked accessories for: Light1`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding getCachedValue for Light2 characteristic: Brightness`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n   });\n\n   // Next testcase\n   // saveCachedPlatformAccessoriesOnDisk( cachedPlatformAccessories, accessoryStorage, cachedAccessoryPath, cachedAccessoriesFile = \"cachedAccessories\" )\n\n});\n\n\n"
  },
  {
    "path": "test/Cmd4PriorityPollingQueue.js",
    "content": "#!node\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\nlet constants = require( \"../cmd4Constants\" );\n\nlet Cmd4Accessory = require( \"../Cmd4Accessory\" ).Cmd4Accessory;\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\nlet Cmd4PriorityPollingQueue = require( \"../Cmd4PriorityPollingQueue\" ).Cmd4PriorityPollingQueue;\n\n\n// Duplicated from Cmd4PriorityPollingQueue.js\nlet HIGH_PRIORITY_SET = 0;\nlet HIGH_PRIORITY_GET = 1;\n//let LOW_PRIORITY_GET = 2;\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\nfunction dummyCallback( )\n{\n}\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\ndescribe('WoRm - Testing Cmd4PriorityPollingQueue polling', ( ) =>\n{\n   // So we can cancel any timers\n   let cmd4PriorityPollingQueue;\n\n   before( ( ) =>\n   {\n      //sinon.stub( process, `exit` );\n\n      cleanStatesDir();\n   });\n   after( ( ) =>\n   {\n      //process.exit.restore( );\n\n   });\n   beforeEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n   });\n\n   it( \"WoRm - Test if Cmd4PriorityPollingQueue exists\", function ( )\n   {\n      expect( Cmd4PriorityPollingQueue ).not.to.be.a( \"null\", \"Cmd4PriorityPollingQueue was null\" );\n   });\n\n   it( \"WoRm - Test echoRetryErrors will echo approprietly\", function( )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let queueName = \"Queue A\";\n\n      cmd4PriorityPollingQueue = new Cmd4PriorityPollingQueue( log, queueName );\n\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"cmd4PollingQueues is not an instance of Cmd4PollingQueues\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.echoRetryErrors, ` Cmd4PriorityPollingQueue.echoRetryErrors is not a function` );\n\n      assert.equal( cmd4PriorityPollingQueue.queueRetryCount, 0, ` Cmd4PriorityPollingQueue.queueRetryCount should be 0` );\n\n      // When count is zero then printing error should be true\n      let count = 0;\n      cmd4PriorityPollingQueue.queueRetryCount = 0; // Default\n      assert.isTrue( cmd4PriorityPollingQueue.echoRetryErrors( count ), ` Cmd4PriorityPollingQueue.echoRetryErrors( ${ count } ) for worm queue should not be true` );\n\n      assert.isTrue( cmd4PriorityPollingQueue.echoRetryErrors( count ), ` Cmd4PriorityPollingQueue.echoRetryErrors( ${ count } ) echoRetryErrors should be True for count = queueRetryCount = 0` );\n\n      count = 1;\n      cmd4PriorityPollingQueue.queueRetryCount = 1;\n      assert.isTrue( cmd4PriorityPollingQueue.echoRetryErrors( count ), ` Cmd4PriorityPollingQueue.echoRetryErrors( ${ count } ) echoRetryErrors should be False for count = queueRetryCount = 1` );\n\n      count = 0;\n      cmd4PriorityPollingQueue.queueRetryCount = 1;\n      assert.isFalse( cmd4PriorityPollingQueue.echoRetryErrors( count ), ` Cmd4PriorityPollingQueue.echoRetryErrors( ${ count } ) echoRetryErrors should be False for count < queueRetryCount` );\n\n   });\n\n   it( \"WoRm - Test creation of Default Cmd4PriorityPollingQueue\", function( )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let queueName = \"Queue A\";\n\n      cmd4PriorityPollingQueue = new Cmd4PriorityPollingQueue( log, queueName );\n\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"cmd4PollingQueues is not an instance of Cmd4PollingQueues\" );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4PriorityPollingQueue unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4PriorityPollingQueue unexpected stderr received: ${ log.errBuf }` );\n      assert.equal( cmd4PriorityPollingQueue.queueName, queueName, ` Cmd4PriorityPollingQueue.queueName is incorrect` );\n\n      assert.isFalse( cmd4PriorityPollingQueue.queueStarted, ` Cmd4PriorityPollingQueue should not be started` );\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type` );\n      assert.equal( cmd4PriorityPollingQueue.pauseTimer, null, ` incorrect queue pauseTimer ` );\n      assert.equal( cmd4PriorityPollingQueue.pauseTimerTimeout, constants.DEFAULT_QUEUE_PAUSE_TIMEOUT, ` incorrect queue pauseTimer interval` );\n\n   });\n\n   it( \"WoRm - Test creation of Default Cmd4PriorityPollingQueue from config.json\", function( )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"Active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true_withRcOf1\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type. Should be WoRm` );\n   });\n\n   it( \"WoRm - Test creation of Default Cmd4PriorityPollingQueue retryCount from config.json\", function( )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\", retries: 12 } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"Active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true_withRcOf1\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type. Should be WoRm` );\n      assert.equal( cmd4PriorityPollingQueue.queueRetryCount, 12, ` incorrect queue retries` );\n   });\n\n   it( \"WoRm - Test creation of Default Cmd4PriorityPollingQueue retryCount from config.json\", function( )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"Active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true_withRcOf1\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type. Should be WoRm` );\n      assert.equal( cmd4PriorityPollingQueue.queueRetryCount, constants.DEFAULT_WORM_QUEUE_RETRY_COUNT, ` incorrect default queueRetryCount` );\n   });\n\n   it( \"WoRm - Test existance of prioritySetValue\", function( )\n   {\n      let platformConfig =\n      {\n         queueTypes:                [ { queue: \"7\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            queue:                     \"7\",\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = cmd4Accessory.queue;\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"7\" with QueueType of: \"${ constants.QUEUETYPE_WORM }\" retryCount: ${ constants.DEFAULT_WORM_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n\n   });\n\n   it( \"WoRm - Test existance of priorityGetValue\", function( )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [{ queue: \"A\", queueType: \"WoRm\" }],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                  true,\n            type:                      \"Switch\",\n            queue:                     \"A\",\n            on:                         0,\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = cmd4Accessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"A\" with QueueType of: \"${ constants.QUEUETYPE_WORM }\" retryCount: ${ constants.DEFAULT_WORM_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n\n      assert.isFunction( cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry, `.addLowPriorityGetPolledQueueEntry is not a function` );\n\n      assert.isFunction( cmd4PriorityPollingQueue.priorityGetValue, `.priorityGetValue is not a function` );\n\n   });\n\n   it( \"WoRm - Test addLowPriorityGetPolledQueueEntry goes to low priority queue\", function( )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [{ queue: \"A\", queueType: \"WoRm\" }],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                  true,\n            type:                      \"Switch\",\n            queue:                     \"A\",\n            on:                         0,\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = cmd4Accessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry, `.addLowPriorityGetPolledQueueEntry is not a function` );\n\n      //                                    ( accessory, accTypeEnumIndex, characteristicstring, interval, timeout )\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4Accessory, CMD4_ACC_TYPE_ENUM.On, \"On\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 1, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 0, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ];\n\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `On was not stored as a get` );\n\n\n   });\n\n   it( \"WoRm - Test processEntryFromLowPriorityQueue\", function( done  )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" }],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.On, \"On\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.Active, \"Active\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 4, `Polled Get added to low prority queue` );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      cmd4PriorityPollingQueue.processEntryFromLowPriorityQueue( cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ] );\n\n      setTimeout( () =>\n      {\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Get 'MySwitch' 'On' timeout: 60000` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: On function for: MySwitch returned: 1` , `expected stdout: ${ log.logBuf }` );\n         // Low priority queues are continious, make sure it is still the same\n         assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 4, `After poll, low priority queue length should atill be the same size` );\n\n         let entry0 = cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ];\n         let entry1 = cmd4PriorityPollingQueue.lowPriorityQueue[ 1 ];\n\n         assert.equal( entry1.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.Active, `After poll, The low priority queue should still be the same` );\n         assert.equal( entry0.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `After poll, The low priority queue should still be the same` );\n\n         assert.equal( cmd4PriorityPollingQueue.lowPriorityQueueIndex, 0, `After poll the current index should be 1` );\n\n         done( );\n\n      }, 1000);\n\n   });\n\n   it('WoRm - Cmd4Platform created pollingQueue.', ( done ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                 true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         },\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 2, `Incorrect number of created accessories` );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 4, `Incorrect number of low level polling characteristics` );\n\n      // ACCESSORY 1\n      let accessory1 = cmd4Platform.createdCmd4Accessories[0];\n      expect( accessory1 ).to.be.a.instanceOf( Cmd4Accessory, \"accessory1 is not an instance of Cmd4Accessory\" );\n      assert.equal( Object.keys( accessory1.listOfPollingCharacteristics).length, 2, `Incorrect number of polling characteristics for accessory1` );\n\n\n      // ACCESSORY 2\n      let accessory2 = cmd4Platform.createdCmd4Accessories[1];\n      expect( accessory2 ).to.be.a.instanceOf( Cmd4Accessory, \"accessory2 is not an instance of Cmd4Accessory\" );\n      assert.equal( Object.keys( accessory2.listOfPollingCharacteristics).length, 2, `Incorrect number of polling characteristics for accessory2` );\n\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"A\" with QueueType of: \"${ constants.QUEUETYPE_WORM }\" retryCount: ${ constants.DEFAULT_WORM_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding prioritySetValue for MySwitch characteristic: On` , `expected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding priorityGetValue for MySwitch characteristic: On` , `expected stdout: ${ log.logBuf }` );\n\n      // There is only one queue created as both accessories are in the same queue\n      let numberOfQueues = Object.keys( settings.listOfCreatedPriorityQueues ).length;\n      assert.equal( numberOfQueues, 1, `Incorrect number of polling queues` );\n\n\n      cmd4Platform.startPolling( 5000, 5000 );\n\n      cmd4Platform.pollingTimers.forEach( ( timer ) =>\n      {\n         clearTimeout( timer );\n      });\n\n\n      //let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      //expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PriorityPollingQueue\" );\n\n      done( );\n   });\n\n   it('WoRm - PollingQueue getValue.', ( done ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                  true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         },\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let numberOfQueues = Object.keys( settings.listOfCreatedPriorityQueues ).length;\n\n      assert.equal( numberOfQueues, 1, `Incorrect number of polling queues` );\n      let cmd4PriorityPollingQueue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PriorityPollingQueue\" );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 4, `Incorrect number of low priority polled characteristics` );\n\n\n      //let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n\n      cmd4Platform.startPolling( 5000, 5000 );\n\n      cmd4Platform.pollingTimers.forEach( ( timer ) =>\n      {\n         clearTimeout( timer );\n      });\n\n      // Add  IOS Get to start with. This will trigger queue as we had stopped it from starting\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.Active, \"Active\", constants.DEFAULT_TIMEOUT, dummyCallback );\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 5, `Set not added to high prority queue` );\n\n      done();\n   }).timeout(10000);\n});\n\ndescribe('QUEUETYPE: STANDARD (Passthru ) -  Testing Cmd4PriorityPollingQueue polling', ( ) =>\n{\n   // So we can cancel any timers\n   let cmd4PriorityPollingQueue;\n\n   before( ( ) =>\n   {\n      sinon.stub( process, `exit` );\n\n      cleanStatesDir();\n   });\n   after( ( ) =>\n   {\n      process.exit.restore( );\n\n   });\n   beforeEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n   });\n\n   it( \"Standard - Test if Cmd4PriorityPollingQueue exists\", function ( )\n   {\n      expect( Cmd4PriorityPollingQueue ).not.to.be.a( \"null\", \"Cmd4PriorityPollingQueue was null\" );\n   });\n\n   it( \"Standard - Test creation of Standard ( Passthrue )  Cmd4PriorityPollingQueue\", function( )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let queueName = \"Queue A\";\n\n      cmd4PriorityPollingQueue = new Cmd4PriorityPollingQueue( log, queueName, constants.QUEUETYPE_STANDARD );\n\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"cmd4PollingQueues is not an instance of Cmd4PollingQueues\" );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4PriorityPollingQueue unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4PriorityPollingQueue unexpected stderr received: ${ log.errBuf }` );\n      assert.equal( cmd4PriorityPollingQueue.queueName, queueName, ` Cmd4PriorityPollingQueue.queueName is incorrect` );\n\n      assert.isFalse( cmd4PriorityPollingQueue.queueStarted, ` Cmd4PriorityPollingQueue should not be started` );\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.QUEUETYPE_STANDARD, ` incorrect default queue type` );\n      assert.equal( cmd4PriorityPollingQueue.pauseTimer, null, ` incorrect queue pauseTimer ` );\n      assert.equal( cmd4PriorityPollingQueue.pauseTimerTimeout, constants.DEFAULT_QUEUE_PAUSE_TIMEOUT, ` incorrect queue pauseTimer interval` );\n\n   });\n\n   it( \"Standard - Test existance of prioritySetValue\", function( )\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = cmd4Accessory.queue;\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n\n\n   });\n\n   it( \"Standard - Test existance of priorityGetValue\", function( )\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                  true,\n            type:                      \"Switch\",\n            on:                         0,\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = cmd4Accessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n\n      assert.isFunction( cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry, `.addLowPriorityGetPolledQueueEntry is not a function` );\n\n      assert.isFunction( cmd4PriorityPollingQueue.priorityGetValue, `.priorityGetValue is not a function` );\n\n   });\n\n   it( \"Standard - Test addLowPriorityGetPolledQueueEntry goes to low priority queue\", function( )\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                  true,\n            type:                      \"Switch\",\n            on:                         0,\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = cmd4Accessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n\n      assert.isFunction( cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry, `.addLowPriorityGetPolledQueueEntry is not a function` );\n\n      //                                    ( accessory, accTypeEnumIndex, characteristicstring, interval, timeout )\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4Accessory, CMD4_ACC_TYPE_ENUM.On, \"On\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 1, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 0, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ];\n\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `On was not stored as a get` );\n\n\n   });\n\n   it( \"Standard - Test processEntryFromLowPriorityQueue\", function( done  )\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            polling:                   [ { characteristic: \"on\"  },\n                                         { characteristic: \"active\"  }],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n\n\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.On, \"On\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n      cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.Active, \"Active\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 4, `Polled Get added to low prority queue` );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      cmd4PriorityPollingQueue.processEntryFromLowPriorityQueue( cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ] );\n\n      setTimeout( () =>\n      {\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Get 'MySwitch' 'On' timeout: 60000` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: On function for: MySwitch returned: 1` , `expected stdout: ${ log.logBuf }` );\n         // Low priority queues are continious, make sure it is still the same\n         assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 4, `After poll, low priority queue length should atill be the same size` );\n\n         let entry0 = cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ];\n         let entry1 = cmd4PriorityPollingQueue.lowPriorityQueue[ 1 ];\n\n         assert.equal( entry1.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.Active, `After poll, The low priority queue should still be the same` );\n         assert.equal( entry0.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `After poll, The low priority queue should still be the same` );\n\n         assert.equal( cmd4PriorityPollingQueue.lowPriorityQueueIndex, 0, `After poll the current index should be 1` );\n\n         done( );\n\n      }, 1000);\n\n   });\n\n   it('Standard - Cmd4Platform created pollingQueue.', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                 true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            polling:                   [ { characteristic: \"on\", Interval: 310  },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         },\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( cmd4Platform.createdCmd4Accessories.length, 2, `Incorrect number of created accessories` );\n\n      // There should be two queues created, one for each accessory\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 2, `Incorrect number of polling queues created` );\n\n\n      // ACCESSORY 1\n      let accessory1 = cmd4Platform.createdCmd4Accessories[0];\n      let queue1 = accessory1.queue;\n      expect( accessory1 ).to.be.a.instanceOf( Cmd4Accessory, \"accessory1 is not an instance of Cmd4Accessory\" );\n      expect( queue1 ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue1 is not an instance of Cmd4PollingQueue\" );\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MyLight\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n      assert.equal( queue1.lowPriorityQueue.length, 2 , `Incorrect number of low level polling characteristics` );\n      assert.equal( Object.keys( accessory1.listOfPollingCharacteristics).length, 2, `Incorrect number of polling characteristics for accessory1` );\n      assert.include( log.logBuf, `Adding prioritySetValue for MyLight characteristic: On` , `expected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding priorityGetValue for MyLight characteristic: On` , `expected stdout: ${ log.logBuf }` );\n\n\n      // ACCESSORY 2\n      let accessory2 = cmd4Platform.createdCmd4Accessories[1];\n      expect( accessory2 ).to.be.a.instanceOf( Cmd4Accessory, \"accessory2 is not an instance of Cmd4Accessory\" );\n      let queue2 = accessory2.queue;\n      expect( queue2 ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue2 is not an instance of Cmd4PollingQueue\" );\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n      assert.equal( queue2.lowPriorityQueue.length, 2 , `Incorrect number of low level polling characteristics` );\n      assert.equal( Object.keys( accessory2.listOfPollingCharacteristics).length, 2, `Incorrect number of polling characteristics for accessory2` );\n      assert.include( log.logBuf, `Adding prioritySetValue for MySwitch characteristic: On` , `expected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding priorityGetValue for MySwitch characteristic: On` , `expected stdout: ${ log.logBuf }` );\n\n\n      cmd4Platform.startPolling( 5000, 5000 );\n\n      cmd4Platform.pollingTimers.forEach( ( timer ) =>\n      {\n         clearTimeout( timer );\n      });\n\n      //let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      //expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PriorityPollingQueue\" );\n\n      done( );\n   });\n\n   it('Standard - PollingQueue getValue.', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                 true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         },\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      let numberOfQueues = Object.keys( settings.listOfCreatedPriorityQueues ).length;\n      assert.equal( numberOfQueues, 2, `Incorrect number of polling queues` );\n\n      // ACCESSORY 1\n      let accessory1 = cmd4Platform.createdCmd4Accessories[0];\n      let queue1 = accessory1.queue;\n      expect( accessory1 ).to.be.a.instanceOf( Cmd4Accessory, \"accessory1 is not an instance of Cmd4Accessory\" );\n      expect( queue1 ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue1 is not an instance of Cmd4PollingQueue\" );\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MyLight\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n      assert.equal( queue1.lowPriorityQueue.length, 2 , `Incorrect number of low level polling characteristics` );\n      assert.equal( Object.keys( accessory1.listOfPollingCharacteristics).length, 2, `Incorrect number of polling characteristics for accessory1` );\n      assert.include( log.logBuf, `Adding prioritySetValue for MyLight characteristic: On` , `expected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding priorityGetValue for MyLight characteristic: On` , `expected stdout: ${ log.logBuf }` );\n\n\n      // ACCESSORY 2\n      let accessory2 = cmd4Platform.createdCmd4Accessories[1];\n      expect( accessory2 ).to.be.a.instanceOf( Cmd4Accessory, \"accessory2 is not an instance of Cmd4Accessory\" );\n      let queue2 = accessory2.queue;\n      expect( queue2 ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue2 is not an instance of Cmd4PollingQueue\" );\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n      assert.equal( queue2.lowPriorityQueue.length, 2 , `Incorrect number of low level polling characteristics` );\n      assert.equal( Object.keys( accessory2.listOfPollingCharacteristics).length, 2, `Incorrect number of polling characteristics for accessory2` );\n      assert.include( log.logBuf, `Adding prioritySetValue for MySwitch characteristic: On` , `expected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `Adding priorityGetValue for MySwitch characteristic: On` , `expected stdout: ${ log.logBuf }` );\n\n\n\n      //let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n\n      cmd4Platform.startPolling( 5000, 5000 );\n\n      cmd4Platform.pollingTimers.forEach( ( timer ) =>\n      {\n         clearTimeout( timer );\n      });\n\n      // Add  IOS Get to start with. This will trigger queue as we had stopped it from starting\n      cmd4SwitchAccessory.queue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.Active, \"Active\", constants.DEFAULT_TIMEOUT, dummyCallback );\n      assert.equal( cmd4SwitchAccessory.queue.lowPriorityQueue.length, 3, `Set not added to high prority queue` );\n\n      done();\n   }).timeout(10000);\n\n});\n\ndescribe('WoRM - Testing Cmd4PriorityPollingQueue recovery correction', ( ) =>\n{\n   // So we can cancel any timers\n   let cmd4PriorityPollingQueue;\n\n   before( ( ) =>\n   {\n      sinon.stub( process, `exit` );\n\n      cleanStatesDir();\n\n   });\n   after( ( ) =>\n   {\n      process.exit.restore( );\n   });\n   beforeEach( function( )\n   {\n      settings.arrayOfAllStaggeredPollingCharacteristics = [ ];\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n\n   });\n\n   it( `WoRM - Test Cmd4PriorityPollingQueue queue can be started`, function( done )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let queueName = \"Queue A\";\n\n      cmd4PriorityPollingQueue = new Cmd4PriorityPollingQueue( log, queueName );\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"cmd4PollingQueues is not an instance of Cmd4PollingQueues\" );\n\n      var allDoneCallback = function( allDoneCount )\n      {\n         assert.equal( allDoneCount, 0, ` startQueue incorrect allDoneCount` );\n         log.debug( \"Test Cmd4PriorityQueue startQueue - allDone called\" );\n      };\n\n      cmd4PriorityPollingQueue.startQueue( cmd4PriorityPollingQueue, allDoneCallback );\n\n\n      assert.include( log.logBuf, `[90menablePolling for the first time`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n      assert.equal( log.errBuf, ``, ` Cmd4PriorityPollingQueue Unexpected stderr received: ${ log.errBuf }` );\n\n\n      done( );\n   });\n\n   it( `WoRM - Test Cmd4PriorityPollingQueue adds an entry to the highPriorityQueue`, function( done )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                 true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[33mAdding prioritySetValue for MyLight characteristic: On`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n\n      // Set to a large amount so it does not happen\n      cmd4PriorityPollingQueue.recoveryTimerInterval = 500000;\n\n      // Fake the queue to be blocked\n      cmd4PriorityPollingQueue.inProgressSets = 1;\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Brightness ]\n                            .characteristic ).setValue( 22, dummyCallback );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 1, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.highPriorityQueue[ 0 ];\n\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.Brightness, `Incorrect accTypeEnumIndex in entry` );\n      assert.equal( entry.isSet, true, `Incorrect isSet in entry` );\n      assert.equal( entry.characteristicString, \"Brightness\", `Incorrect isSet in entry` );\n      assert.equal( entry.value, 22, `Incorrect value in entry` );\n\n      done();\n\n   });\n\n   it( `WoRM - Test Cmd4PriorityPollingQueue adds multiple entries to the highPriorityQueue`, function( done )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                  true,\n            type:                      \"Lightbulb\",\n            on:                         0,\n            brightness:                 100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[33mAdding prioritySetValue for MyLight characteristic: On`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n\n      // Set to a large amount so it does not happen\n      cmd4PriorityPollingQueue.recoveryTimerInterval = 500000;\n\n      // Fake the queue to be blocked\n      cmd4PriorityPollingQueue.inProgressSets = 1;\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Brightness ]\n                            .characteristic ).setValue( 22, dummyCallback );\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n                            .characteristic ).setValue( 0, dummyCallback );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 2, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.highPriorityQueue[ 1 ];\n\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `Incorrect accTypeEnumIndex in entry` );\n      assert.equal( entry.isSet, true, `Incorrect isSet in entry` );\n      assert.equal( entry.characteristicString, \"On\", `Incorrect isSet in entry` );\n      assert.equal( entry.value, 0, `Incorrect value in entry` );\n\n      done();\n\n   });\n\n   it( `WoRM - Test Cmd4PriorityPollingQueue Adds \"Set\" after existing \"set\" in queue`, function( done )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                  true,\n            type:                      \"Lightbulb\",\n            on:                         0,\n            brightness:                 100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[33mAdding prioritySetValue for MyLight characteristic: On`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n\n      // Set to a large amount so it does not happen\n      cmd4PriorityPollingQueue.recoveryTimerInterval = 500000;\n\n      // Fake the queue to be blocked\n      cmd4PriorityPollingQueue.inProgressSets = 1;\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Brightness ]\n                            .characteristic ).setValue( 22, dummyCallback );\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n                            .characteristic ).setValue( 1, dummyCallback );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 2, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.highPriorityQueue[ 1 ];\n\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `Incorrect accTypeEnumIndex in entry` );\n      assert.equal( entry.isSet, true, `Incorrect isSet in entry` );\n      assert.equal( entry.characteristicString, \"On\", `Incorrect isSet in entry` );\n      assert.equal( entry.value, true, `Incorrect value in entry` );\n\n      done();\n\n   });\n\n   it( `V2 crippled WoRM - Test Cmd4PriorityPollingQueue Adds \"Get\" after existing \"set\" in queue`, function( done )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                 true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[33mAdding prioritySetValue for MyLight characteristic: On`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n\n      // Set to a large amount so it does not happen\n      cmd4PriorityPollingQueue.recoveryTimerInterval = 500000;\n\n      // Fake the queue to be blocked\n      cmd4PriorityPollingQueue.inProgressSets = 1;\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Brightness ]\n                            .characteristic ).setValue( 22, dummyCallback );\n\n/* Characteristic.getValue() is deprecated in V2 and Characteristic.value does not call the\n * get functions. Worked last in homebridge-1.8\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n                            .characteristic ).getValue( dummyCallback );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 2, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.highPriorityQueue[ 1 ];\n\n      // Even though the \"Get\" was added second, the next \"Set\" gets put before it\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `Incorrect accTypeEnumIndex in entry` );\n      assert.equal( entry.isSet, false, `Incorrect isSet in entry` );\n      assert.equal( entry.characteristicString, \"On\", `Incorrect isSet in entry` );\n*/\n      done();\n\n   });\n\n   it( `V2 crippled WoRM - Test Cmd4PriorityPollingQueue same \"Set\" replaces old in queue`, function( done )\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyLight\",\n            displayName:               \"MyLight\",\n            statusMsg:                 true,\n            type:                      \"Lightbulb\",\n            on:                        0,\n            brightness:                100,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\", interval: 310 },\n                                         { characteristic: \"brightness\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         } ]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.include( log.logBuf, `[33mAdding prioritySetValue for MyLight characteristic: On`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n\n      let cmd4PriorityPollingQueue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.isFunction( cmd4PriorityPollingQueue.prioritySetValue, `.prioritySetValue is not a function` );\n\n      // Set to a large amount so it does not happen\n      cmd4PriorityPollingQueue.recoveryTimerInterval = 5000000;\n\n      // Fake the queue to be blocked\n      cmd4PriorityPollingQueue.inProgressSets = 1;\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Brightness ]\n                            .characteristic ).setValue( 22, dummyCallback );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 1, `Polled Get added to high prority queue` );\n\n/* Characteristic.getValue() is deprecated in V2 and Characteristic.value does not call the\n * get functions. Worked last in homebridge-1.8\n      // Call the getValue bound function, which is priorityGetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n                            .characteristic ).getValue( dummyCallback );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 2, `Polled Get added to high prority queue` );\n\n      // Call the setValue bound function, which is prioritySetValue\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n                            .characteristic ).setValue( 1, dummyCallback );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 3, `Polled Get added to high prority queue` );\n\n      // This setValue should replace the first\n      cmd4LightAccessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Brightness ]\n                            .characteristic ).setValue( 30, dummyCallback );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Polled Get added to low prority queue` );\n      assert.equal( cmd4PriorityPollingQueue.highPriorityQueue.length, 3, `Polled Get added to high prority queue` );\n\n      let entry = cmd4PriorityPollingQueue.highPriorityQueue[ 0 ];\n\n      // Check that the entry was replaced at queue index 0.\n      assert.equal( entry.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.Brightness, `Incorrect accTypeEnumIndex in entry` );\n      assert.equal( entry.isSet, true, `Incorrect isSet in entry` );\n      assert.equal( entry.characteristicString, \"Brightness\", `Incorrect isSet in entry` );\n      assert.equal( entry.value, 30, `Incorrect value in entry` );\n\n*/\n      done();\n   });\n\n   it( `WoRM - Test \"Get\" Entry From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: cmd4SwitchAccessory.hV.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Get\" entry: ${ CMD4_ACC_TYPE_ENUM.On } isUpdate: false length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Get 'MySwitch' 'On' timeout: 60000` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: On function for: MySwitch returned: 1` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `WoRM - Test \"Get\" Entry From High Priority Queue Failure >` + constants.DEFAULT_WORM_QUEUE_RETRY_COUNT + ` times`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true_withRcOf1\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      var allDoneCallback = function( allDoneCount )\n      {\n         assert.equal( allDoneCount, 0, ` startQueue incorrect allDoneCount` );\n         log.debug( \"Test Cmd4PriorityQueue startQueue - allDone called\" );\n      };\n\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type. Should be WoRm` );\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      //cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n      cmd4PriorityPollingQueue.startQueue( cmd4PriorityPollingQueue, allDoneCallback );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n\n         assert.include( log.errBuf, `[33m*1* error(s) were encountered for \"MySwitch\" getValue. Last error found Getting: \"On\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n\n         // A quick way to stop the queue. For whatever reason, if the above fails,\n         // the testcase will not do this command and the testcase runs forever\n         cmd4SwitchAccessory.queue.inProgressSets = 10;\n\n         done( );\n\n      }, 1500 );\n\n   }).timeout( 2000 );\n\n   it( `WoRM - Test \"Get\" Entry RetryCount = 1 fails twice`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\", retries: 1 } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            timeout:                   10, // Need to change the record we add for this\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"./test/echoScripts/runToTimeoutRcOf1\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n      assert.equal( queue.queueRetryCount, 1, `Incorrect queueRetryCount` );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      var allDoneCallback = function( allDoneCount )\n      {\n         assert.equal( allDoneCount, 0, ` startQueue incorrect allDoneCount` );\n         log.debug( \"Test Cmd4PriorityQueue startQueue - allDone called\" );\n      };\n\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type. Should be WoRm` );\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: 10, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      //cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n      cmd4PriorityPollingQueue.startQueue( cmd4PriorityPollingQueue, allDoneCallback );\n\n      // Wait for the 1st entry in the Queue to be processed\n      setTimeout( ( ) =>\n      {\n\n         assert.include( log.errBuf, `[33m*2* error(s) were encountered for \"MySwitch\" getValue. Last error found Getting: \"On\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n\n\n         assert.equal( cmd4PriorityPollingQueue.queueRetryCount, 1, `incorrect queueReturyCount. Should be 1` );\n         // A quick way to stop the queue. For whatever reason, if the above fails,\n         // the testcase will not do this command and the testcase runs forever\n         cmd4SwitchAccessory.queue.inProgressSets = 10;\n\n         done( );\n\n      }, 2500 );\n\n   }).timeout( 3000 );\n\n   it( `WoRM - Test \"Set\" Entry From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue setValue will just return successful\n      // and do the actual setValue later\n      var dummyCallback = function( rc )\n      {\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: true, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Set\" entry: ${ CMD4_ACC_TYPE_ENUM.On } length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90msetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch 1  cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Set 'MySwitch' 'On' '1'` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `WoRM - Test \"Set\" Entry From High Priority Queue Failure >*` + constants.DEFAULT_WORM_QUEUE_RETRY_COUNT + ` times`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true_withRcOf1\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.queueType, constants.DEFAULT_QUEUE_TYPE, `Incorrect queue type was created ` );\n      assert.equal( queue.queueRetryCount, constants.DEFAULT_WORM_QUEUE_RETRY_COUNT, `Incorrect queue retryCount ` );\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      var allDoneCallback = function( allDoneCount )\n      {\n         assert.equal( allDoneCount, 0, ` startQueue incorrect allDoneCount` );\n         log.debug( \"Test Cmd4PriorityQueue startQueue - allDone called\" );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: true, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      //cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n      cmd4PriorityPollingQueue.startQueue( cmd4PriorityPollingQueue, allDoneCallback );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         // Counting starts from zero, i.e queueRetries = 0, so add 1\n         assert.include( log.errBuf, `[33m*${ constants.DEFAULT_WORM_QUEUE_RETRY_COUNT +1 }* error(s) were encountered for \"MySwitch\" getValue. Last error found Getting: \"On\". Perhaps you should run in debug mode to find out what the problem might be.\\u001b`, `queue Incorrect stderr: ${ log.errBuf }` );\n\n         // A quick way to stop the queue. For whatever reason, if the above fails,\n         // the testcase will not do this command and the testcase runs forever\n         cmd4SwitchAccessory.queue.inProgressSets = 10;\n\n         done( );\n\n      }, 1500 );\n\n   }).timeout( 2000 );\n\n   it( `WoRM - Test \"Set\" Entry With Related CharacteristicFrom High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             \"STOPPED\",\n            stateChangeResponseTime:   0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4DoorAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4DoorAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let dummyCallbackCount = 0;\n      var dummyCallback = function( rc )\n      {\n         dummyCallbackCount ++;\n         assert.equal( dummyCallbackCount, 1, ` callback called too many times` );\n\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4DoorAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.TargetPosition, [ constants.CHARACTERISTIC_STRING_lv ]: \"TargetPosition\", [ constants.TIMEOUT_lv ]: cmd4DoorAccessory.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: 100, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      //log.reset( );\n      //log.setOutputEnabled( false );\n      //log.setDebugEnabled( true );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_SET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Set\" entry: ${ CMD4_ACC_TYPE_ENUM.TargetPosition} length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90msetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.TargetPosition } )-\"TargetPosition\" function for: MyDoor 100  cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Set 'MyDoor' 'TargetPosition' '100'`, `expected stdout: ${ log.logBuf }` );\n\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Get\" entry: 43 isUpdate: true length: ` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.CurrentPosition } )-\"CurrentPosition\" function for: MyDoor cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Get 'MyDoor' 'CurrentPosition'`, `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: CurrentPosition function for: MyDoor returned: 100`, `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 3000 );\n\n   }).timeout( 6000 );\n});\ndescribe('Standard - Testing Cmd4PriorityPollingQueue recovery correction', ( ) =>\n{\n   // So we can cancel any timers\n   let cmd4PriorityPollingQueue;\n\n   before( ( ) =>\n   {\n      sinon.stub( process, `exit` );\n\n      cleanStatesDir();\n\n   });\n   after( ( ) =>\n   {\n      process.exit.restore( );\n   });\n   beforeEach( function( )\n   {\n      settings.arrayOfAllStaggeredPollingCharacteristics = [ ];\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n   });\n\n   it( `Standard - Test Cmd4PriorityPollingQueue queue can be started`, function( done )\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let queueName = \"Queue A\";\n\n      cmd4PriorityPollingQueue = new Cmd4PriorityPollingQueue( log, queueName, constants.QUEUETYPE_STANDARD );\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"cmd4PollingQueues is not an instance of Cmd4PollingQueues\" );\n\n      var allDoneCallback = function( allDoneCount )\n      {\n         assert.equal( allDoneCount, 0, ` startQueue incorrect allDoneCount` );\n         log.debug( \"Test Cmd4PriorityQueue startQueue - allDone called\" );\n      };\n\n      cmd4PriorityPollingQueue.startQueue( cmd4PriorityPollingQueue, allDoneCallback );\n\n\n      assert.include( log.logBuf, `[90menablePolling for the first time`, `Cmd4PriorityPollingQueue expected stdout received: ${ log.logBuf }` );\n      assert.equal( log.errBuf, ``, ` Cmd4PriorityPollingQueue Unexpected stderr received: ${ log.errBuf }` );\n\n\n      done( );\n   });\n\n   it( `Standard - Test \"Get\" Entry From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      assert.include( log.logBuf, `[90mCreating new Priority Polled Queue \"Q:MySwitch\" with QueueType of: \"${ constants.QUEUETYPE_STANDARD }\" retryCount: ${ constants.DEFAULT_STANDARD_QUEUE_RETRY_COUNT }` , `expected stdout: ${ log.logBuf }` );\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n      expect( cmd4SwitchAccessory ).to.be.a.instanceOf( Cmd4Accessory, `cmd4Platform did not create an instance of Cmd4Accessory` );\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: cmd4SwitchAccessory.hV.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Get\" entry: ${ CMD4_ACC_TYPE_ENUM.On } isUpdate: false length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Get 'MySwitch' 'On' timeout: 60000` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: On function for: MySwitch returned: 1` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `Standard - Test \"Set\" Entry From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue setValue will just return successful\n      // and do the actual setValue later\n      var dummyCallback = function( rc )\n      {\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: true, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Set\" entry: ${ CMD4_ACC_TYPE_ENUM.On } length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90msetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch 1  cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Set 'MySwitch' 'On' '1'` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `Standard - Test \"Set\" Entry With Related CharacteristicFrom High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MyDoor\",\n            displayName:               \"MyDoor\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             \"STOPPED\",\n            stateChangeResponseTime:   0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         { characteristic: \"targetPosition\"  } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n\n\n      let cmd4DoorAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4DoorAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n      assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      let dummyCallbackCount = 0;\n      var dummyCallback = function( rc )\n      {\n         dummyCallbackCount ++;\n         assert.equal( dummyCallbackCount, 1, ` callback called too many times` );\n\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4DoorAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.TargetPosition, [ constants.CHARACTERISTIC_STRING_lv ]: \"TargetPosition\", [ constants.TIMEOUT_lv ]: cmd4DoorAccessory.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: 100, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      //log.reset( );\n      //log.setOutputEnabled( false );\n      //log.setDebugEnabled( true );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_SET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Set\" entry: ${ CMD4_ACC_TYPE_ENUM.TargetPosition } length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90msetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.TargetPosition } )-\"TargetPosition\" function for: MyDoor 100  cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Set 'MyDoor' 'TargetPosition' '100'`, `expected stdout: ${ log.logBuf }` );\n\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Get\" entry: ${ CMD4_ACC_TYPE_ENUM.CurrentPosition } isUpdate: true length: ` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.CurrentPosition } )-\"CurrentPosition\" function for: MyDoor cmd: node ./Extras/Cmd4Scripts/Examples/AnyDevice Get 'MyDoor' 'CurrentPosition'`, `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: CurrentPosition function for: MyDoor returned: 100`, `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 3000 );\n\n   }).timeout( 6000 );\n});\n"
  },
  {
    "path": "test/Cmd4Storage.js",
    "content": "\"use strict\";\n\n\nlet Cmd4Storage = require( \"../utils/Cmd4Storage\" );\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n\ndescribe(`Basic Cmd4Storage Tests`, ( ) =>\n{\n   it( `Test creation of Cmd4Storage`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      const cmd4Storage = new Cmd4Storage( log );\n\n      assert.instanceOf( cmd4Storage , Cmd4Storage, \"Expected cmd4Storage to be instance of Cmd4Storage. Found %s\" , cmd4Storage );\n\n      assert.isFunction( cmd4Storage.getStoredValueForIndex, \".getStoredValueForIndex is not a function\" );\n      assert.isFunction( cmd4Storage.getStoredValueForCharacteristic, \".getStoredValueForCharacteristic is not a function\" );\n      assert.isFunction( cmd4Storage.setStoredValueForIndex, \".setStoredValueForIndex is not a function\" );\n      assert.isFunction( cmd4Storage.setStoredValueForCharacteristic, \".setStoredValueForCharacteristic is not a function\" );\n      assert.isFunction( cmd4Storage.testStoredValueForIndex, \".testStoredValueForIndex is not a function\" );\n      assert.isFunction( cmd4Storage.testStoredValueForCharacteristic, \".testStoredValueForCharacteristic is not a function\" );\n\n      assert.isFunction( cmd4Storage.loadLatestData, \".loadLatestData is not a function\" );\n\n      done( );\n\n   });\n\n   it( `Cmd4Storage can init itself properly`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      assert.equal( cmd4Storage.DATA.length, CMD4_ACC_TYPE_ENUM.EOL, `cmd4Storage is not the correct size` );\n\n      for ( let i = 0; i < CMD4_ACC_TYPE_ENUM.EOL; i++ )\n      {\n        assert.equal( cmd4Storage.DATA[ i ], null, `cmd4Storage[ ${ i } ] is not null` );\n      }\n\n      done( );\n   });\n\n   it( `Cmd4Storage can set data properly using an index`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n      assert.equal( cmd4Storage.DATA[ CMD4_ACC_TYPE_ENUM.On ], 1, `cmd4Storage.DATA[ ${ CMD4_ACC_TYPE_ENUM.On } ] is not 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can set data properly using a UC characteristic`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForCharacteristic( characteristicString, 1 );\n      assert.equal( cmd4Storage.DATA[ CMD4_ACC_TYPE_ENUM.On ], 1, `cmd4Storage.DATA[ ${ CMD4_ACC_TYPE_ENUM.On } ] is not 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can set data properly using a LC characteristic`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForCharacteristic( characteristicString, 1 );\n      assert.equal( cmd4Storage.DATA[ CMD4_ACC_TYPE_ENUM.On ], 1, `cmd4Storage.DATA[ ${ CMD4_ACC_TYPE_ENUM.On } ] is not 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can get data properly using an index`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n      assert.equal( cmd4Storage.DATA[ CMD4_ACC_TYPE_ENUM.On ], 1, `cmd4Storage.DATA[ ${ CMD4_ACC_TYPE_ENUM.On } ] is not 1` );\n\n\n      let value = cmd4Storage.getStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On );\n      assert.equal( value, 1, `cmd4Storage.getStoredValueForIndex( ${ CMD4_ACC_TYPE_ENUM.On } ) did not return 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can get data properly using a LC characteristic`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n      assert.equal( cmd4Storage.DATA[ CMD4_ACC_TYPE_ENUM.On ], 1, `cmd4Storage.DATA[ ${ CMD4_ACC_TYPE_ENUM.On } ] is not 1` );\n\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n\n      let value = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, 1, `cmd4Storage.getStoredValueForCharacteristic( ${ characteristicString } ) did not return 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can get data properly using a UC characteristic`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n      assert.equal( cmd4Storage.DATA[ CMD4_ACC_TYPE_ENUM.On ], 1, `cmd4Storage.DATA[ ${ CMD4_ACC_TYPE_ENUM.On } ] is not 1` );\n\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n\n      let value = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, 1, `cmd4Storage.getStoredValueForCharacteristic( ${ characteristicString } ) did not return 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can test data properly for an index value to be null`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      //let characteristicString = CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ].type;\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      let value = cmd4Storage.testStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On );\n      assert.equal( value, undefined, `cmd4Storage.testSoredValueForIndex( ${ CMD4_ACC_TYPE_ENUM.On } ) did not return undefined` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can test data properly for an index value to be set`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n\n      let value = cmd4Storage.testStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On );\n      assert.equal( value, 1, `cmd4Storage.testSoredValueForIndex( ${ CMD4_ACC_TYPE_ENUM.On } ) did not return 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can test data properly for an UC characteristic value to be null`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      let value = cmd4Storage.testStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, undefined, `cmd4Storage.testSoredValueForIndex( ${ characteristicString } ) did not return undefined` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can test data properly for an LC characteristic value to be null`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      let value = cmd4Storage.testStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, undefined, `cmd4Storage.testSoredValueForIndex( ${ characteristicString } ) did not return undefined` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can test data properly for an UC characteristic value to be set`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n\n      let value = cmd4Storage.testStoredValueForCharacteristic( characteristicString );\n\n      assert.equal( value, 1, `cmd4Storage.testSoredValueForIndex( ${ CMD4_ACC_TYPE_ENUM.On } ) did not return 1` );\n\n      done( );\n   });\n\n   it( `Cmd4Storage can test data properly for an LC characteristic value to be set`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n      cmd4Storage.setStoredValueForIndex( CMD4_ACC_TYPE_ENUM.On, 1 );\n\n      let value = cmd4Storage.testStoredValueForCharacteristic( characteristicString );\n\n      assert.equal( value, 1, `cmd4Storage.testSoredValueForIndex( ${ CMD4_ACC_TYPE_ENUM.On } ) did not return 1` );\n\n      done( );\n   });\n\n\n\n   it( `Cmd4Storage can set/get data`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n\n      let cmd4Storage = new Cmd4Storage( log );\n\n      cmd4Storage.setStoredValueForCharacteristic( characteristicString, 50 );\n      let rc = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( rc, 50, `cmd4Storage did not set/get data correctly` );\n\n      done( );\n   });\n});\ndescribe(`Init with Class data Tests`, ( ) =>\n{\n   it( `Test creation of Cmd4Storage with Class data`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      // The Test data\n      let testData = new Cmd4Storage( log );\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n      testData.setStoredValueForCharacteristic( characteristicString, 1 );\n\n\n      let cmd4Storage = new Cmd4Storage( log, testData );\n      assert.instanceOf( cmd4Storage , Cmd4Storage, \"Expected cmd4Storage to be instance of Cmd4Storage. Found %s\" , cmd4Storage );\n\n      let value = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, 1, `cmd4Storage[ ${characteristicString} ] did not return 1` );\n      done( );\n   });\n\n   it( `Test creation of Cmd4Storage with invalid Class data throws error`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      // The Test data\n      let testData = new Cmd4Storage( log );\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n      testData.setStoredValueForCharacteristic( characteristicString, 1 );\n\n      expect ( ( ) => new Cmd4Storage( log, 155 ) ).to.throw(/Do not know how to handle typeof: number Cmd4_Storage parm: 155/);\n\n      done( );\n   });\n\n   it( `Test creation of Cmd4Storage with invalid Class Version throws error`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      // The Test data\n      let testData = new Cmd4Storage( log );\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n      testData.setStoredValueForCharacteristic( characteristicString, 1 );\n      testData.CLASS_VERSION = 0;\n\n\n      expect ( ( ) => new Cmd4Storage( log, testData ) ).to.throw(/Do not know how to handle Cmd4_Storage Class version: 0/);\n\n      done( );\n   });\n\n});\n\ndescribe(`Init with Old data Tests`, ( ) =>\n{\n   it( `Test creation of Cmd4Storage with old data below ListPairing`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      // The Test data\n      let storedValuesPerCharacteristic = new Array( CMD4_ACC_TYPE_ENUM.EOL -1 ).fill( null );\n      storedValuesPerCharacteristic[ CMD4_ACC_TYPE_ENUM.Active ] = 1;\n\n\n      let cmd4Storage = new Cmd4Storage( log, storedValuesPerCharacteristic );\n      assert.instanceOf( cmd4Storage , Cmd4Storage, \"Expected cmd4Storage to be instance of Cmd4Storage. Found %s\" , cmd4Storage );\n\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.Active );\n      let value = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, 1, `cmd4Storage[ ${characteristicString} ] did not return 1` );\n      done( );\n   });\n\n   it( `Test creation of Cmd4Storage with old data above ListPairing`, ( done ) =>\n   {\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n\n      // The Test data\n      let storedValuesPerCharacteristic = new Array( CMD4_ACC_TYPE_ENUM.EOL -1 ).fill( null );\n      // The old data would be the new minus one.\n      storedValuesPerCharacteristic[ CMD4_ACC_TYPE_ENUM.LockControlPoint -1 ] = 1;\n      storedValuesPerCharacteristic[ CMD4_ACC_TYPE_ENUM.WiFiSatelliteStatus -1 ] = 1;\n\n\n      let cmd4Storage = new Cmd4Storage( log, storedValuesPerCharacteristic );\n      assert.instanceOf( cmd4Storage , Cmd4Storage, \"Expected cmd4Storage to be instance of Cmd4Storage. Found %s\" , cmd4Storage );\n\n      // Check the next characteristic past ListPairing\n      let characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.LockControlPoint );\n      let value = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, 1, `cmd4Storage[ ${characteristicString} ] did not return 1` );\n      characteristicString = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.WiFiSatelliteStatus );\n      value = cmd4Storage.getStoredValueForCharacteristic( characteristicString );\n      assert.equal( value, 1, `cmd4Storage[ ${characteristicString} ] did not return 1` );\n      done( );\n   });\n});\n\n\n\n\n"
  },
  {
    "path": "test/HV.js",
    "content": "\"use strict\";\n\n\nlet HV = require( \"../utils/HV\" );\nlet constants = require( \"../cmd4Constants\" );\n\n\ndescribe(`A Hierarchy Variable Test`, ( ) =>\n{\n   it( `Test creation of HV`, ( ) =>\n   {\n      const hv = new HV( );\n\n      assert.instanceOf( hv , HV, \"Expected hv to be instance of HV. Found %s\" , hv );\n      assert.isFunction( hv.update, \".update is not a function\" );\n\n      assert.equal( hv.allowTLV8, constants.DEFAULT_ALLOW_TLV8, `default not created` );\n      assert.equal( hv.debug, constants.DEFAULT_DEBUG, `default not created` );\n      assert.equal( hv.outputConstants, constants.DEFAULT_OUTPUTCONSTANTS, `default not created` );\n      assert.equal( hv.interval, constants.DEFAULT_INTERVAL, `default not created` );\n      assert.equal( hv.stateChangeResponseTime, constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME, `default not created` );\n      assert.equal( hv.statusMsg, constants.DEFAULT_STATUSMSG, `default not created` );\n      assert.equal( hv.timeout, constants.DEFAULT_TIMEOUT, `default not created` );\n\n\n   });\n\n   it( `HV can update variables`, ( done ) =>\n   {\n      let data =\n      {\n         allowTLV8: false,\n         debug: true,\n         outputConstants: true,\n         interval: 100,\n         stateChangeResponseTime: 122,\n         statusMsg: false,\n         timeout: 141\n      };\n      let hv = new HV( );\n\n      // Simple check previously tested\n      assert.equal( hv.allowTLV8, constants.DEFAULT_ALLOW_TLV8, `default not created` );\n\n      hv.update( data );\n\n      assert.equal( hv.allowTLV8, data.allowTLV8, `hv not updated` );\n      assert.equal( hv.debug, data.debug, `hv not updated` );\n      assert.equal( hv.outputConstants, data.outputConstants, `hv not updated` );\n      assert.equal( hv.interval, data.interval, `hv not updated` );\n      assert.equal( hv.stateChangeResponseTime, data.stateChangeResponseTime, `hv not updated` );\n      assert.equal( hv.statusMsg, data.statusMsg, `hv not updated` );\n      assert.equal( hv.timeout, data.timeout, `hv not updated` );\n\n      done( );\n   });\n\n   it( `Test HV can update updated variables`, ( done ) =>\n   {\n      let data =\n      {\n         allowTLV8: false,\n         debug: true,\n         outputConstants: true,\n         interval: 100,\n         stateChangeResponseTime: 122,\n         statusMsg: false,\n         timeout: 141\n      };\n      let hv = new HV( );\n\n      hv.update( data );\n\n      let data2 =\n      {\n         allowTLV8: true,\n         debug: false,\n         outputConstants: false,\n         interval: 300,\n         // stateChangeResponseTime: 122,\n         statusMsg: true,\n         timeout: 333\n      };\n\n      hv.update( data2 );\n\n      assert.equal( hv.allowTLV8, data2.allowTLV8, `hv not updated` );\n      assert.equal( hv.debug, data2.debug, `hv not updated` );\n      assert.equal( hv.outputConstants, data2.outputConstants, `hv not updated` );\n      assert.equal( hv.interval, data2.interval, `hv not updated` );\n      assert.equal( hv.stateChangeResponseTime, data.stateChangeResponseTime, `hv not updated` );\n      assert.equal( hv.statusMsg, data2.statusMsg, `hv not updated` );\n      assert.equal( hv.timeout, data2.timeout, `hv not updated` );\n\n      done( );\n   });\n\n   it( `Test HV copy does not change original`, ( done ) =>\n   {\n      const hv = new HV( );\n\n      let rHV = Object.assign( {}, hv );\n      assert.equal( hv.timeout, constants.DEFAULT_TIMEOUT, `hv not initialized` );\n\n      rHV.timeout = 1500;\n\n      assert.equal( rHV.timeout, 1500, `rhv not changed` );\n      assert.equal( hv.timeout, constants.DEFAULT_TIMEOUT, `hv was changed` );\n\n      done( );\n   });\n\n   it( `Test HV copy does not change original`, ( done ) =>\n   {\n      const hv = new HV( );\n\n      let rHV = Object.assign( {}, hv );\n      rHV.update = hv.update;\n\n      assert.equal( hv.timeout, constants.DEFAULT_TIMEOUT, `hv not initialized` );\n\n      let data =\n      {\n         allowTLV8: true,\n         debug: false,\n         outputConstants: false,\n         interval: 300,\n         // stateChangeResponseTime: 122,\n         statusMsg: true,\n         timeout: 333\n      };\n\n      rHV.update( data );\n\n      // Check changed\n      assert.equal( rHV.allowTLV8, data.allowTLV8, `rHV not updated` );\n      assert.equal( rHV.debug, data.debug, `rHV not updated` );\n      assert.equal( rHV.outputConstants, data.outputConstants, `rHV not updated` );\n      assert.equal( rHV.interval, data.interval, `rHV not updated` );\n      assert.equal( rHV.stateChangeResponseTime, constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME, `default not created` );\n      assert.equal( rHV.statusMsg, data.statusMsg, `rHV not updated` );\n      assert.equal( rHV.timeout, data.timeout, `rHV not updated` );\n\n      // Check original\n      assert.equal( hv.allowTLV8, constants.DEFAULT_ALLOW_TLV8, `default was changed` );\n      assert.equal( hv.debug, constants.DEFAULT_DEBUG, `default was changed` );\n      assert.equal( hv.outputConstants, constants.DEFAULT_OUTPUTCONSTANTS, `default was changed` );\n      assert.equal( hv.interval, constants.DEFAULT_INTERVAL, `default was changed` );\n      assert.equal( hv.stateChangeResponseTime, constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME, `default was changed` );\n      assert.equal( hv.statusMsg, constants.DEFAULT_STATUSMSG, `default was changed` );\n      assert.equal( hv.timeout, constants.DEFAULT_TIMEOUT, `default was changed` );\n\n\n      done( );\n\n   });\n});\n\n"
  },
  {
    "path": "test/Logger.js",
    "content": "\"use strict\";\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\n// Let logger control logs for Unit Testing\nsettings.cmd4Dbg = true;\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\nlet { Cmd4Accessory } = require( \"../Cmd4Accessory\" );\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\n\n// ******** TEST logger  *************\ndescribe('A simple logger Test', ( ) =>\n{\n   it( \"Test bufferEnabled is off by default\", ( ) =>\n   {\n      const log = new Logger( );\n      log.setOutputEnabled( false );\n\n      let STDOUT_DATA=\"stdout_data\";\n      log.info( STDOUT_DATA );\n\n      // Logger adds a \\n so use include\n      assert.equal( log.logBuf , \"\", `Expected no logs to stdout` );\n      assert.equal( log.logLineCount, 0 , `unexpected number of lines to stdout` );\n      assert.equal( log.errBuf , \"\", `Expected no logs to stderr` );\n      assert.equal( log.errLineCount, 0 , `unexpected number of lines to stderr` );\n\n   });\n\n   it( \"Test info log to stdout gets captured and mothing else\", ( ) =>\n   {\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let STDOUT_DATA=\"stdout_data\";\n      log.info( STDOUT_DATA );\n\n      // Logger adds a \\n so use include\n      assert.include( log.logBuf , STDOUT_DATA, `Expected logs to stdout for log.info ` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n      assert.equal( log.errBuf , \"\", `Expected no logs to stderr` );\n      assert.equal( log.errLineCount, 0 , `unexpected number of lines to stderr` );\n\n   });\n\n   it( \"Test warn log to stderr gets captured and mothing else\", ( ) =>\n   {\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let STDERR_DATA=\"stderr_data\";\n      log.warn( STDERR_DATA );\n\n      assert.equal( log.logBuf , \"\", `Expected no logs to stout` );\n      assert.equal( log.logLineCount, 0 , `unexpected number of lines to stdout` );\n      // Logger adds a \\n so use include\n      assert.include( log.errBuf , STDERR_DATA, `Expected logs to stderr for log.warn ` );\n      assert.equal( log.errLineCount, 1 , `unexpected number of lines to stderr` );\n\n   });\n\n   it( \"Test log to stderr gets captured and mothing else\", ( ) =>\n   {\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let STDERR_DATA=\"stderr_data\";\n      log.error( STDERR_DATA );\n\n      assert.equal( log.logBuf , \"\", `Expected no logs to stdout` );\n      assert.equal( log.logLineCount, 0 , `unexpected number of lines to stdout` );\n      // Logger adds a \\n so use include\n      assert.include( log.errBuf , STDERR_DATA, `Expected logs to stderr` );\n      assert.equal( log.errLineCount, 1 , `unexpected number of lines to stderr` );\n\n   });\n\n   it( \"Test log to stderr and different to stdout\", ( ) =>\n   {\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let STDERR_DATA=\"stderr_data\";\n      let STDOUT_DATA=\"stdout_data\";\n      log.info( STDOUT_DATA );\n      log.error( STDERR_DATA );\n\n      // Logger adds a \\n so use include\n      assert.include( log.logBuf , STDOUT_DATA, `Expected logs to stdout for log.info ` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n      // Logger adds a \\n so use include\n      assert.include( log.errBuf , STDERR_DATA, `Expected logs to stderr` );\n      assert.equal( log.errLineCount, 1 , `unexpected number of lines to stderr` );\n\n   });\n\n\n   it( \"Test can create an instance of Cmd4Accessory with new logger\", ( ) =>\n   {\n      let config =\n      {\n         name:                         \"Test Switch\",\n         type:                         \"Switch\",\n         on:                           false,\n         polling:                      true,\n         state_cmd:                    \"./test/echoScripts/echo_1\"\n      };\n\n      const log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let accessory = new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.instanceOf( accessory , Cmd4Accessory, \"Expected accessory to be instance of Cmd4Accessory. Found %s\" , accessory );\n      assert.equal( log.logBuf , \"\", `unexpected logs to stdout for a simple instance of Cmd4Accessory` );\n      assert.equal( log.logLineCount, 0 , `unexpected number of lines to stdout` );\n      assert.equal( log.errBuf , \"\", `Expected no logs to stderr for a simple instance of Cmd4Accessory` );\n      assert.equal( log.errLineCount, 0 , `unexpected number of lines to stderr` );\n\n      log.reset();\n   });\n\n   it( \"Test can create an instance of Cmd4Accessory with a debug log\", ( ) =>\n   {\n      let config =\n      {\n         name:                         \"Test Switch\",\n         type:                         \"Switch\",\n         on:                           false,\n         polling:                      true,\n         state_cmd:                    \"./test/echoScripts/echo_1\"\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      new Cmd4Accessory( log, config, _api, [ ] );\n\n      assert.include( log.logBuf, \"Creating Standalone Accessory type for \", `Expected debug logs to stdout with setDebugEnabled` );\n      //assert.equal( log.logLineCount, 17 , `unexpected number of lines to stdout` );\n      assert.equal( log.errBuf, \"\", `Expected no logs to stderr for a simple instance of Cmd4Accessory` );\n      assert.equal( log.errLineCount, 0 , `unexpected number of lines to stderr` );\n\n      log.reset();\n   });\n\n   it( \"Test logger performance of NOT enabled message\", ( ) =>\n   {\n      const log = new Logger( );\n      log.setBufferEnabled( false );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n      let entry = { characteristicString: \"testCharacteristic\",\n                    accessory:\n                    { displayName: \"testDevice\",\n                      queue:\n                      { inProgressGets: 0,\n                        inProgressSets: 0\n                      }\n                    }\n                  };\n\n      let logStartTime = process.hrtime( );\n\n      log.debug( `OUTPUT FOR MEASUREMENT High priority \"Get\" queue interrupt attempted: ${ entry.accessory.displayName } ${ entry.characteristicString } inProgressSets:${ entry.accessory.queue.inProgressSets } inProgressGets: ${ entry.accessory.queue.inProgressGets }` );\n      let logTotalTime = process.hrtime( logStartTime );\n\n      let debug = false;\n      let debugStartTime = process.hrtime( );\n      if ( debug ) log.debug( `OUTPUT FOR MEASUREMENT High priority \"Get\" queue interrupt attempted: ${ entry.accessory.displayName } ${ entry.characteristicString } inProgressSets:${ entry.accessory.queue.inProgressSets } inProgressGets: ${ entry.accessory.queue.inProgressGets }` );\n      let debugTotalTime = process.hrtime(  debugStartTime );\n\n      let diff = logTotalTime[1] - debugTotalTime[1];\n      console.log( `logTotalTime: ${ logTotalTime[1] } debugTotalTime: ${ debugTotalTime[1] } diff: ${ diff }` );\n\n      assert.isAbove( logTotalTime[1], debugTotalTime[1], `Expected log total time to be greater than debug total time` );\n\n   });\n});\n\n"
  },
  {
    "path": "test/VariableTimer.js",
    "content": "\"use strict\";\n\n\nlet VariableTimer = require( \"../utils/VariableTimer\" );\n\n\ndescribe('A Variable Timer Test', ( ) =>\n{\n   it( \"Test creation of variableTimer\", ( ) =>\n   {\n      const timer = new VariableTimer( );\n\n      assert.instanceOf( timer , VariableTimer, \"Expected timer to be instance of VariableTimer. Found %s\" , timer );\n      assert.isFunction( timer.start, \".start is not a function\" );\n      assert.isFunction( timer.stop, \".stop is not a function\" );\n      assert.isFunction( timer.set_interval, \".set_interval is not a function\" );\n\n   });\n\n   // Only skip this test because it takes 20 seconds\n   it.skip( \"Test timer can change intervals, stop start ...\", ( done ) =>\n   {\n      const timer = new VariableTimer( );\n      var start = new Date();\n      var total = 0;\n\n      timer.start( ( ) =>\n      {\n         var end = new Date();\n         var seconds = ( end - start) / 1000\n         total += Math.trunc( seconds );\n         start = end;\n         console.log(`done ${ seconds } ${ total }`);\n      }, 1000);\n      assert.equal( timer.iv, 1000, \"iv is set incorrectly\" );\n      setTimeout(() =>\n      {\n         console.log(\"changing timer to 2 seconds.\");\n         timer.set_interval( 2000 );\n         assert.equal( timer.iv, 2000, \"iv is reset incorrectly\" );\n         assert.equal( total, 4, \"total is incorrect\" );\n         setTimeout(() =>\n         {\n            assert.equal( total, 12, \"total is incorrect\" );\n            timer.stop();\n            done();\n         }, 10000);\n      }, 5000);\n\n   }).timeout(20000);\n\n   it( \"Test timer can change intervals, only by .5s increments\", ( done ) =>\n   {\n      const timer = new VariableTimer( );\n      var start = new Date();\n      var total = 0;\n\n      timer.start( ( ) =>\n      {\n         var end = new Date();\n         var seconds = ( end - start) / 1000\n         total += Math.trunc( seconds );\n         start = end;\n         console.log(`done ${ seconds } ${ total }`);\n      }, 1000);\n      assert.equal( timer.iv, 1000, \"iv is set incorrectly\" );\n      timer.set_interval( 2000 );\n      assert.equal( timer.iv, 2000, \"iv reset to 2000 incorrectly\" );\n      timer.set_interval( 2100 );\n      assert.equal( timer.iv, 2000, \"iv reset incorrectly to 2100\" );\n      timer.set_interval( 2500 );\n      assert.equal( timer.iv, 2500, \"iv reset incorrectly to 2500\" );\n      timer.set_interval( 2999 );\n      assert.equal( timer.iv, 2500, \"iv reset incorrectly to 2999\" );\n      timer.set_interval( 3000 );\n      assert.equal( timer.iv, 3000, \"iv reset incorrectly to 3000\" );\n      timer.set_interval( 2500 );\n      assert.equal( timer.iv, 2500, \"iv reset incorrectly down to 2500\" );\n      timer.stop();\n      done( );\n\n   }).timeout(20000);\n});\n\n"
  },
  {
    "path": "test/allTests",
    "content": "test/Logger.js\ntest/async-dump.js\ntest/configHasCharacteristicProps.js\ntest/isJSON.js\ntest/indexOfEnum.js\ntest/isNumeric.js\ntest/extractKeyValue.js\ntest/getAccessoryNameFunctions.js\ntest/getAccessoryUUID.js\ntest/getSetAllValues.js\ntest/VariableTimer.js\ntest/transposeCMD4Props.js\ntest/trueTypeOf.js\ntest/versionChecker.js\ntest/Cmd4Storage.js\ntest/HV.js\ntest/cmd4Constants.js\ntest/CMD4_CHAR_TYPE_ENUMS.js\ntest/CMD4_ACC_TYPE_ENUM.js\ntest/CMD4_DEVICE_TYPE_ENUM.js\ntest/isAccDirective.js\ntest/isDevDirective.js\ntest/isCmd4Directive.js\ntest/testOurConfig.json.js\ntest/configTest.js\ntest/loadPluginTest.js\ntest/Cmd4Accessory.js\ntest/internalRelatedTargetTests.js\ntest/Cmd4Platform.js\ntest/Cmd4AccessoryGetValue.js\ntest/Cmd4AccessorySetValue.js\ntest/Cmd4Mode.js\ntest/Cmd4PriorityPollingQueue.js\ntest/initPluginTest.js\ntest/fakeGato.js\ntest/pollingTest.js\ntest/Cmd4PlatformRestartTests.js\n"
  },
  {
    "path": "test/async-dump.js",
    "content": "'use strict';\n\n// How To use:\n//\n// 1. In package.json change scipt \"test\", adding:\n//       node_modules/.bin/mocha --require ./test/async-dump.js\n// 2. In the failing test add at the top:\n//       after(function () {\n//          global.asyncDump();\n//       });\n// 3. Run the test\n//       npm run test test/failingTest\n//\n//\n// Taken from: https://gist.github.com/boneskull/7fe75b63d613fa940db7ec990a5f5843\n\nconst { createHook } = require( 'async_hooks' );\nconst { stackTraceFilter } = require( 'mocha/lib/utils' );\nconst allResources = new Map();\n\n// this will pull Mocha internals out of the stacks\nconst filterStack = stackTraceFilter();\n\nconst hook = createHook({\n   init(asyncId, type, triggerAsyncId)\n   {\n      allResources.set(asyncId, { type, triggerAsyncId, stack: ( new Error( ) ).stack });\n   },\n   destroy( asyncId ) {\n      allResources.delete( asyncId );\n   }\n}).enable( );\n\nglobal.asyncDump = module.exports = ( ) => {\n   hook.disable( );\n   console.error(`\nSTUFF STILL IN THE EVENT LOOP:`)\n   allResources.forEach(value => {\n      console.error( `Type: ${value.type}` );\n      console.error( filterStack(value.stack ) );\n      console.error( '\\n' );\n   });\n};\n"
  },
  {
    "path": "test/cmd4Constants.js",
    "content": "\"use strict\";\n\nvar fs = require(\"fs\");\n\nconst constants = require( \"../cmd4Constants\" );\n\n\ndescribe( \"Testing cmd4Constants\", function( )\n{\n   it( \"All cmd4Constants should be declared the same.\", function ( done )\n   {\n       assert.equal( constants.STANDALONE, \"Standalone\", `Incorrect global value` );\n       assert.equal( constants.PLATFORM, \"Platform\", `Incorrect global value` );\n\n\n       assert.equal( constants.DEFAULT_TIMEOUT, 60000, `Incorrect global value` );\n       assert.equal( constants.DEFAULT_INTERVAL, 60000, `Incorrect global value` );\n\n       assert.equal( constants.DEFAULT_STATUSMSG, \"TRUE\", `Incorrect global value` );\n\n       assert.equal( constants.FAKEGATO_TYPE_ENERGY, \"energy\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO_TYPE_ROOM, \"room\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO_TYPE_WEATHER, \"weather\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO_TYPE_DOOR, \"door\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO_TYPE_MOTION, \"motion\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO_TYPE_THERMO, \"thermo\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO_TYPE_AQUA, \"aqua\", `Incorrect global value` );\n       assert.equal( constants.EVE, \"eve\", `Incorrect global value` );\n       assert.equal( constants.STORAGE, \"storage\", `Incorrect global value` );\n       assert.equal( constants.STORAGEPATH, \"storagePath\", `Incorrect global value` );\n       assert.equal( constants.FOLDER, \"folder\", `Incorrect global value` );\n       assert.equal( constants.KEYPATH, \"keyPath\", `Incorrect global value` );\n       assert.equal( constants.STATUS, \"status\", `Incorrect global value` );\n       assert.equal( constants.TEMP, \"temp\", `Incorrect global value` );\n       assert.equal( constants.SETTEMP, \"setTemp\", `Incorrect global value` );\n       assert.equal( constants.HUMIDITY, \"humidity\", `Incorrect global value` );\n       assert.equal( constants.PPM, \"ppm\", `Incorrect global value` );\n       assert.equal( constants.POWER, \"power\", `Incorrect global value` );\n       assert.equal( constants.PRESSURE, \"pressure\", `Incorrect global value` );\n       assert.equal( constants.CURRENTTEMP, \"currentTemp\", `Incorrect global value` );\n       assert.equal( constants.VALVEPOSITION, \"valvePosition\", `Incorrect global value` );\n       assert.equal( constants.WATERAMOUNT, \"waterAmount\", `Incorrect global value` );\n       assert.equal( constants.TIME, \"time\", `Incorrect global value` );\n       assert.equal( constants.PATH, \"path\", `Incorrect global value` );\n\n       assert.equal( constants.FS, \"fs\", `Incorrect global value` );\n       assert.equal( constants.GOOGLE_DRIVE, \"googleDrive\", `Incorrect global value` );\n\n       assert.equal( constants.OUTPUTCONSTANTS, \"outputConstants\", `Incorrect global value` );\n       assert.equal( constants.STATUSMSG, \"statusMsg\", `Incorrect global value` );\n\n       assert.equal( constants.TYPE, \"type\", `Incorrect global value` );\n       assert.equal( constants.SUBTYPE, \"subType\", `Incorrect global value` );\n       assert.equal( constants.DISPLAYNAME, \"displayName\", `Incorrect global value` );\n       assert.equal( constants.UUID, \"uuid\", `Incorrect global value` );\n       assert.equal( constants.ACCESSORY, \"accessory\", `Incorrect global value` );\n       assert.equal( constants.CATEGORY, \"category\", `Incorrect global value` );\n       assert.equal( constants.PUBLISHEXTERNALLY, \"publishExternally\", `Incorrect global value` );\n       assert.equal( constants.PROPS, \"props\", `Incorrect global value` );\n       assert.equal( constants.CHARACTERISTIC, \"characteristic\", `Incorrect global value` );\n       assert.equal( constants.TIMEOUT, \"timeout\", `Incorrect global value` );\n       assert.equal( constants.QUEUE, \"queue\", `Incorrect global value` );\n       assert.equal( constants.POLLING, \"polling\", `Incorrect global value` );\n       assert.equal( constants.INTERVAL, \"interval\", `Incorrect global value` );\n       assert.equal( constants.STATECHANGERESPONSETIME, \"stateChangeResponseTime\", `Incorrect global value` );\n       assert.equal( constants.STATE_CMD_PREFIX, \"state_cmd_prefix\", `Incorrect global value` );\n       assert.equal( constants.STATE_CMD_SUFFIX, \"state_cmd_suffix\", `Incorrect global value` );\n       assert.equal( constants.STATE_CMD, \"state_cmd\", `Incorrect global value` );\n       assert.equal( constants.FAKEGATO, \"fakegato\", `Incorrect global value` );\n       assert.equal( constants.REQUIRES, \"requires\", `Incorrect global value` );\n       assert.equal( constants.CONSTANTS, \"constants\", `Incorrect global value` );\n       assert.equal( constants.VARIABLES, \"variables\", `Incorrect global value` );\n       assert.equal( constants.LINKEDTYPES, \"linkedTypes\", `Incorrect global value` );\n       assert.equal( constants.ACCESSORIES, \"accessories\", `Incorrect global value` );\n       assert.equal( constants.URL, \"url\", `Incorrect global value` );\n       assert.equal( constants.ALLOWTLV8, \"allowTLV8\", `Incorrect global value` );\n\n       assert.equal( constants.CMD4_STORAGE_lv, \"cmd4Storage\", `Incorrect global value` );\n\n       done( );\n   });\n\n});\ndescribe( \"Testing cmd4Constants ErrorStrings\", function( )\n{\n   it( \"All cmd4Constants error Strings should be declared correctly.\", function ( done )\n   {\n      let len = Object.keys( constants.ERROR_STRINGS ).length;\n\n      assert.equal( constants.ERROR_STRING_MIN - constants.ERROR_STRING_MAX + 1, len, `Totals do not match` );\n\n      assert.equal( constants.ERROR_STRINGS[ constants.ERROR_STRING_MIN - constants.ERROR_TIMER_EXPIRED ],\n                    \"Timer expired contacting accessory\",\n                    \"ERROR_TIMER_EXPIRED not defined correctly\");\n      assert.equal( constants.ERROR_STRINGS[ constants.ERROR_STRING_MIN - constants.ERROR_NULL_REPLY ],\n                    \"Reply is NULL\",\n                    \"ERROR_NULL_REPPLY not defined correctly\");\n      done();\n\n   });\n\n   it( \"cmd4Constants.errorString should be a function\", ( ) =>\n   {\n      assert.isFunction( constants.errorString, \"errorString is not a function\" );\n   });\n\n   it( \"cmd4Constants errorString function works correctly.\", function ( done )\n   {\n      assert.equal( constants.errorString( constants.ERROR_TIMER_EXPIRED ),\n                    \"Timer expired contacting accessory\",\n                    \"ERROR_TIMER_EXPIRED not defined correctly\" );\n      assert.equal( constants.errorString( constants.ERROR_NO_DATA_REPLY ),\n                    \"No data returned from accessory\",\n                    \"ERROR_NO_DATA_REPLY not defined correctly\" );\n\n      done();\n\n   });\n\n   it( \"cmd4Constants errorString limits.\", function ( done )\n   {\n      assert.equal( constants.errorString( constants.ERROR_STRING_MIN +1  ),\n                    \"Device returned its own error; \" + ( constants.ERROR_STRING_MIN +1 ),\n                    \".errorString MIN limit error\" );\n      assert.equal( constants.errorString( constants.ERROR_STRING_MAX -1  ),\n                    \"Device returned its own error; \" + ( constants.ERROR_STRING_MAX -1 ),\n                    \".errorString MAX limit error\" );\n\n      done();\n\n   });\n});\n\n\ndescribe( \"Testing cmd4Constants - unused\", function( )\n{\n   it( \"All cmd4Constants should be used somewhere\", function ( done )\n   {\n      var cmd4Files = [ \"./Cmd4Platform.js\",\n                        \"./Cmd4Accessory.js\",\n                        \"./Cmd4PriorityPollingQueue.js\",\n                        \"./utils/HV.js\",\n                        \"./index.js\",\n                        \"./lib/CMD4_DEVICE_TYPE_ENUM.js\",\n                        \"./tools/Cmd4AccDocGenerator\",\n                        \"./test/cmd4Constants.js\",\n                       ];\n      // This is the count of the found constants in result\n      let foundCount=0;\n      let len = Object.keys( constants ).length;\n\n      Object.keys( constants ).forEach( ( key ) =>\n      {\n         // This one is not found yet\n         let found = false;\n\n         // This is the constant defind in cmd4Constants\n         let c = key;\n\n         // The regex to find the constant in the source files\n         // A great regex site:\n         // https://regex101.com/r/bE3c0x/5\n         const regex = new RegExp( `.*constants.${ c}.*$` ); // 115\n\n         //console.log(\"Looking for constants.%s ( %s of %s )\", c, index, len );\n\n         // The constant must be in one of the Cmd4 source files\n         for ( let fileIndex = 0;\n                   (fileIndex < cmd4Files.length );\n                   fileIndex++ )\n         {\n            let cmd4File = cmd4Files[ fileIndex ];\n\n            // Read in all the code from the source file\n            let code =  fs.readFileSync( cmd4File, \"utf8\" );\n\n            // If I could grep the source file I would, so\n            // check the regex against each line\n            var codeLines = code.split( '\\n' );\n            let lineCount = 0;\n            for ( let lineIndex = 0;\n                      lineIndex < codeLines.length;\n                      lineIndex++, lineCount++ )\n            {\n               let line = codeLines[ lineIndex ];\n\n               // Check the regex\n               let t = regex.test( line );\n               if ( t == true )\n               {\n                  found = true;\n                  foundCount++;\n                  break;\n               }\n            }\n            if (found == true )\n               break;\n         }\n         if (found == false )\n         {\n            console.log( \"Not Found constants.%s\", c );\n            assert.isTrue( found, `Not found constants.${ c } in source files` );\n         }\n      });\n\n      console.log( \"Total found was %s of %s \", foundCount, len );\n      assert.equal( foundCount, len , `Totals do not match` );\n\n      done( );\n   }).timeout(20000);\n});\n\ndescribe( \"Testing source constants  -  are defined\", function( )\n{\n   it( \"All Source constants should be defined\", function ( done )\n   {\n      var cmd4Files = [ \"./Cmd4Platform.js\",\n                        \"./Cmd4Accessory.js\",\n                        \"./Cmd4PriorityPollingQueue.js\",\n                        \"./utils/HV.js\",\n                        \"./tools/Cmd4AccDocGenerator\",\n                        \"./lib/CMD4_DEVICE_TYPE_ENUM.js\",\n                        \"./tools/Cmd4AccDocGenerator\"\n                      ];\n\n      let totalSourceConstants = 0;\n      let foundCount = 0;\n\n      // The constant must be in one of the Cmd4 source files\n      for ( let fileIndex = 0;\n         (fileIndex < cmd4Files.length );\n         fileIndex++ )\n      {\n         let cmd4File = cmd4Files[ fileIndex ];\n\n         let sourceData = fs.readFileSync( cmd4File, \"utf8\" );\n\n         // Matches source files with stuff like:\n         // constants.STANDALONE\n         var sourceConstantsMatches = sourceData.toString().match(/constants.(\\w).*\\n/g);\n         assert.isNotNull( sourceConstantsMatches, `Fike ${ cmd4File } has no constants and should be removed from this testcase` );\n\n         // This is the array of defined constants\n         var sourceMappedConstantsArray = sourceConstantsMatches.map( ( s ) =>\n         {\n            let returningArray = [ ];\n            let occurranceCountArray = s.match( /constants\\./g );\n\n            if ( occurranceCountArray != null )\n            {\n               for ( let i = 0; i < occurranceCountArray.length; i++ )\n               { // '{' - Used to cancel RegExp in vim\n                  s = s.slice( s.indexOf( \"constants.\" ) + 10 );\n\n                  const reg = new RegExp(`[\\\\s|,|:|;|}]|\\\\)|\\\\(` );\n                  let sourceConstantLen = s.search( reg );\n                  let sourceConstant = s.substr(0,  sourceConstantLen );\n\n                  if ( returningArray.length == 0 )\n                  {\n                     //console.log(\"pushing -->%s<--\", sourceConstant );\n                     returningArray.push( sourceConstant );\n                  } else if ( returningArray.find( ( entry ) => entry == sourceConstant ) == -1 )\n                  {\n                     //console.log(\"pushing another  -->%s<--\", sourceConstant );\n                     returningArray.push( sourceConstant );\n                  } else\n                  {\n                     // console.log(\"Duplicate  X->%s<-X\", sourceConstant );\n                     // Duplicate\n                  }\n\n                  // Proceed to the next constant within the same line\n                  if ( i + 1 < occurranceCountArray.length )\n                  {\n                     s = s.slice( sourceConstant.length )\n                  }\n               }\n            }\n\n            // return [ \"NAME\", \"NAME2\" ... ]\n            return returningArray;\n         });\n\n         // Inside the mapping we created an array of constants because\n         // there could be multiple constants per line. Therefore we need\n         // to unwind the array of arrays.\n         let sourceConstantsArray = [ ];\n         sourceMappedConstantsArray.forEach( ( item ) =>\n         {\n            item.forEach( ( sourceConstant ) =>\n            {\n               // console.log(\"Unwinding -->%s<--\", sourceConstant );\n               sourceConstantsArray.push( sourceConstant );\n            });\n         });\n\n         totalSourceConstants += sourceConstantsArray.length;\n\n         // Over every source constant, find if defined in cmd4Constants\n         for ( let sIndex = 0;\n                   sIndex < sourceConstantsArray.length;\n                   sIndex++)\n         {\n             let sourceConstant = sourceConstantsArray[ sIndex ];\n\n             //if ( constants.indexOf( sourceConstant ) == -1 )\n             if ( constants[ sourceConstant ] == undefined )\n             {\n                console.log( \"Not Found from: %s -->%s<--\", cmd4File, sourceConstant );\n                assert( \"Not Found from: %s -->%s<--\", cmd4File, sourceConstant );\n             } else {\n                //console.log( \"FOUND -->%s<--\", sourceConstant );\n                foundCount ++\n             }\n         }\n      }\n      console.log( \"Total found was %s of %s\", foundCount, totalSourceConstants );\n      // If you are off by 1 or 2, check that the code does not\n      // have something like constants.QUEUETYPE_WORM2)\n      // Where the bracket follow the constant without a space\n      assert.equal( foundCount, totalSourceConstants, `Totals do not match` );\n\n      done( );\n   }).timeout(20000);\n});\n"
  },
  {
    "path": "test/configHasCharacteristicProps.js",
    "content": "\"use strict\";\n\n\n// ***************** TEST LOADING **********************\n\n\n\nlet { Cmd4Accessory } = require( \"../Cmd4Accessory\" );\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\nlet changedMinStep = 1;   // Was .1\nlet changedMinValue = 16; // Was -27\nlet changedMaxValue = 32; // Was 100\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\n\n// *** TEST configHasCharacteristicProps *******\ndescribe('Test configHasCharacteristicProps.', ( ) =>\n{\n   it('configHasCharacteristicProps should be a function', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.isFunction(accessory.configHasCharacteristicProps, \"configHasCharacteristicProps is not a function\" );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n\n   });\n\n   it('configHasCharaceristicProps should work with full props.', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let props = { TargetTemperature: { maxValue: +100,\n                                         minValue: -100,\n                                         minStep: 0.1,\n                                       }\n                   };\n\n\n      let result = accessory.configHasCharacteristicProps(accTypeEnumIndex, props, CMD4_ACC_TYPE_ENUM  );\n\n      assert.isObject(CMD4_ACC_TYPE_ENUM, \"configHasCharacteristicProps of valid data with full properties returned incorrect result: \" + result );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it('configHasCharaceristicProps should work with property in small Caps.', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let props = { TargetTemperature: { maxValue: +100,\n                                         minValue: -100,\n                                         minStep: 0.1,\n                                       }\n                   };\n\n\n      let result = accessory.configHasCharacteristicProps(accTypeEnumIndex, props, CMD4_ACC_TYPE_ENUM  );\n\n      assert.isObject(CMD4_ACC_TYPE_ENUM, \"configHasCharacteristicProps of valid data in small Caps returned incorrect result: \" + result );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it('configHasCharaceristicProps should work with two properties', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      let props = { TargetTemperature: { maxValue: +100,\n                                         minValue: -100,\n                                         minStep: 0.1,\n                                       }\n                   };\n\n\n      let result = accessory.configHasCharacteristicProps(accTypeEnumIndex, props, CMD4_ACC_TYPE_ENUM  );\n\n      assert.isObject(CMD4_ACC_TYPE_ENUM, \"configHasCharacteristicProps of valid data in small Caps returned incorrect result: \" + result );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it('configHasCharaceristicProps should work with one property.', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      accessory.props = { TargetTemperature: { maxValue: +100 } };\n\n      let result = accessory.configHasCharacteristicProps( accTypeEnumIndex );\n\n      assert.isObject(result, \"configHasCharacteristicProps of valid data with one propertyreturned incorrect result: \" + result );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it('configHasCharaceristicProps should work with two characteristics.', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      accessory.props = { CurrentTemperature: { maxValue: +100 },\n                          TargetTemperature: { maxValue: +100 },\n                        };\n      let result = accessory.configHasCharacteristicProps( accTypeEnumIndex );\n\n      assert.isObject(result, \"configHasCharacteristicProps of valid data with two characteristicsreturned incorrect result: \" + result );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n   });\n\n   it('configHasCharaceristicProps should fail with a unknown prop', ( ) =>\n   {\n      let config =\n      {\n         type:                            \"TemperatureSensor\",\n         displayName:                     \"MyTemperatureSensor\",\n         name:                            \"MyTemperatureSensor\",\n         currentTemperature:               25,\n         statusFault:                     \"NO_FAULT\",\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TargetTemperature;\n      accessory.props = { TargetTemperature: { maxValue: +100,\n                                               minValue: -100,\n                                               uhoh: 0.1\n                                              }\n                        };\n\n      expect ( ( ) => accessory.configHasCharacteristicProps( accTypeEnumIndex  ) ).to.throw(/props for key \"uhoh\" not in definition of \"targetTemperature\"/);\n\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyTemperatureSensor\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.equal( log.logLineCount, 1 , `unexpected number of lines to stdout` );\n\n\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unxexpected stderr: ${ log.errBuf }` );\n\n   });\n\n   it('setProps should be called for two defind characteristics', ( ) =>\n   {\n      let config =\n      {\n         type:               \"Thermostat\",\n         displayName:        \"MyThermostat\",\n         name:               \"MyThermostat\",\n         currentTemperature: 25,\n         targetTemperature:  25,\n         statusFault:        \"NO_FAULT\",\n         props:              {  \"currentTemperature\":\n                                {\n                                   \"maxValue\": 32,\n                                   \"minValue\": 16,\n                                   \"minStep\": 1\n                                },\n                                \"targetTemperature\":\n                                {\n                                   \"maxValue\": 32,\n                                   \"minValue\": 16,\n                                   \"minStep\": 1\n                                }\n                             }\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.isFunction(accessory.configHasCharacteristicProps, \"configHasCharacteristicProps is not a function\" );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyThermostat\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, \"[90mOverriding characteristic CurrentTemperature props for: MyThermostat\", `Unxexpected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, \"[90mOverriding characteristic TargetTemperature props for: MyThermostat\", `Unxexpected stdout: ${ log.logBuf }` );\n\n   });\n\n   it('setProps should alter characteristics', ( ) =>\n   {\n      let config =\n      {\n         type:               \"Thermostat\",\n         displayName:        \"MyThermostat\",\n         name:               \"MyThermostat\",\n         currentTemperature: 25,\n         targetTemperature:  25,\n         statusFault:        \"NO_FAULT\",\n         props:              {  \"currentTemperature\":\n                                {\n                                   \"maxValue\": 32,\n                                   \"minValue\": 16,\n                                   \"minStep\": 1\n                                },\n                                \"targetTemperature\":\n                                {\n                                   \"maxValue\": 32,\n                                   \"minValue\": 16,\n                                   \"minStep\": 1\n                                }\n                             }\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let parentInfo = undefined;\n      let accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.include( log.logBuf, \"[34mCmd4 is running in Demo Mode for MyThermostat\", ` Cmd4Accessory Unxexpected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, \"[90mOverriding characteristic CurrentTemperature props for: MyThermostat\", `Unxexpected stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, \"[90mOverriding characteristic TargetTemperature props for: MyThermostat\", `Unxexpected stdout: ${ log.logBuf }` );\n\n\n      let props = accessory.service.getCharacteristic(\n                            CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.CurrentTemperature ].characteristic).props;\n      //let util = require('util');\n      //console.log(util.inspect(props, {depth: null}));\n\n      // test minValue\n      let hapMinValue = props.minValue;  // Was -27 now 16\n      let hapMaxValue = props.maxValue;  // Was 100 now 32\n      let hapMinStep = props.minStep;    // Was .1 now 1\n\n      assert.equal( hapMinValue, changedMinValue, `minValue: ${ hapMinValue } not equal to expected: ${ changedMinValue }` );\n      assert.equal( hapMaxValue, changedMaxValue, `maxValue: ${ hapMaxValue } not equal to expected: ${ changedMaxValue }` );\n      assert.equal( hapMinStep, changedMinStep, `minStep: ${ hapMinStep } not equal to expected: ${ changedMinStep }` );\n\n   });\n});\n\n"
  },
  {
    "path": "test/configTest.js",
    "content": "'use strict';\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\nlet indexOfEnum = require( \"../utils/indexOfEnum\" );\nObject.defineProperty( exports, \"indexOfEnum\", { enumerable: true, get: function ( ) { return indexOfEnum.indexOfEnum; } });\n\n\nconst cmd4Config = require( \"../Extras/config.json\" );\nconst isJSON = require( \"../utils/isJSON\" );\nconst ucFirst = require( \"../utils/ucFirst\" );\nconst lcFirst = require( \"../utils/lcFirst\" );\n\n// Constants\nconst constants = require( \"../cmd4Constants\" );\n\ndescribe( `Testing our config.json`, ( ) =>\n{\n   it( `cmdConfig should be a JSON object`, ( ) =>\n   {\n      assert.isObject( cmd4Config, `cmd4Config is not an object` );\n   });\n\n})\n\n\n\n// This would be the plugin un-initialized\nvar pluginModule = require( \"../index\" );\n\ndescribe( `Initializing our plugin module`, ( ) =>\n{});\n\nvar cmd4 = pluginModule.default( _api );\n\nlet CMD4_ACC_TYPE_ENUM = cmd4.CMD4_ACC_TYPE_ENUM;\nlet CMD4_DEVICE_TYPE_ENUM = cmd4.CMD4_DEVICE_TYPE_ENUM;\n\n\ndescribe( `Testing our config.json`, ( ) =>\n{\n   const accessories = cmd4Config.platforms[ 0 ].accessories;\n   for ( let index=0; index < accessories.length; index ++ )\n   {\n      testAccessoryConfig(   accessories[ index ]   );\n   }\n});\n\n\nfunction testAccessoryConfig ( accessoryConfig )\n{\n   describe( `Testing Device Name: ${ accessoryConfig.displayName }`, ( ) =>\n   {\n      for ( let key in accessoryConfig )\n      {\n         let value = accessoryConfig[ key ];\n\n         //let ucKey = ucFirst( key );\n         let lcKey = lcFirst( key );\n\n         switch ( lcKey )\n         {\n            case constants.TYPE:\n               testType ( value );\n\n               break;\n            case constants.DISPLAYNAME:\n               testName( value );\n\n               break;\n            case constants.UUID:\n               testName( value );\n\n               break;\n            case constants.ACCESSORY:\n               break;\n            case constants.CATEGORY:\n               break;\n            case constants.PUBLISHEXTERNALLY:\n               break;\n            case constants.PROPS:\n               break;\n            case constants.NAME:\n               testName( value );\n\n               break;\n            case constants.MODEL:\n               testModel( value );\n\n               break;\n            case constants.MANUFACTURER:\n               testName( value );\n\n               break;\n            case constants.SERIALNUMBER:\n               testName( value );\n\n               break;\n            case constants.FIRMWAREREVISION:\n               break;\n            case constants.OUTPUTCONSTANTS:\n               break;\n            case constants.TIMEOUT:\n               testTimeout( value );\n\n               break;\n            case constants.POLLING:\n               testPollingConfig( value );\n\n               break;\n            case constants.CMD4_MODE:\n               testCmd4_Mode( value );\n              break;\n            case constants.INTERVAL:\n              testInterval( value );\n\n              break;\n           case constants.STATECHANGERESPONSETIME:\n              testStateChangeResponseTime( value );\n\n              break;\n           case constants.STATE_CMD_PREFIX:\n              break;\n           case constants.STATE_CMD_SUFFIX:\n              break;\n           case constants.STATE_CMD:\n              testStateCmd( value );\n\n              break;\n           case constants.STORAGE:\n           case constants.STORAGEPATH:\n           case constants.FOLDER:\n           case constants.KEYPATH:\n              break;\n           case constants.FAKEGATO:\n              testFakegatoConfig( value );\n\n              break;\n           case constants.REQUIRES:\n               break;\n            case constants.CONSTANTS:\n              processConstantsConfig( value );\n\n              break;\n           case constants.VARIABLES:\n              processVariablesConfig( value );\n              break;\n           case constants.LINKEDTYPES:\n\n              processLinkedTypesConfig ( value );\n\n              break;\n           case constants.ACCESSORIES:\n                break;\n           case constants.URL:\n              break;\n           default:\n           {\n              //console.log( \"1 %s Testing %s\", accessoryConfig.displayName, value);\n              testCharacteristic( key, value );\n           }\n        }\n      }\n\n      // Test that we define displayName\n      it( `Testing for a displayName`, ( ) =>\n      {\n         assert.isNotNull( accessoryConfig.displayName , `displayName cannot be undefined` );\n      });\n\n   });\n}\n\nfunction testConstantKey( key )\n{\n   it( `Constant key: ${ key } must start with \"\\${\"`, ( ) =>\n   {\n      assert.isTrue( key!=null && key.startsWith( '${' ), `Constant: \"${ key }\" does not start with \"\\${\"` );\n   });\n   it( `Constant key: ${ key } should end with \"}\"`, ( ) =>\n   {\n      assert.isTrue( key!=null && key.endsWith( \"}\" ), `Constant: \"${ key }\" does not end with \"}\"` );\n   });\n}\n\nfunction processConstantsConfig( config )\n{\n   if ( Array.isArray( config ) )\n   {\n      for ( let i = 0; i < config.length; i++ )\n      {\n         processConstantsConfig( config[ i ] );\n      }\n      return;\n   }\n   if ( isJSON( config ) )\n   {\n      describe( \"test JSON Config\", ( ) =>\n      {});\n\n      // I assume only 1, but you know about assuming ...\n      for ( let key in config )\n      {\n         testConstantKey( key );\n      }\n      return;\n   }\n   it( `Constant Config must be valid`, ( ) =>\n   {\n      assert.isTrue( isJSON( config ), `Constants: \"${ config }\" must be an array of/or list of key/value pairs` );\n   });\n}\nfunction testVariableKey( key )\n{\n   it( `Variable key: \"${ key }\" must start with \"\\${\"`, ( ) =>\n   {\n      assert.isTrue( key!=null && key.startsWith( '${' ), `Variable: \"${ key }\" does not start with \"\\${\"` );\n   });\n   it( `Variable key: \"${ key }\" should end with \"}\"`, ( ) =>\n   {\n      assert.isTrue( key!=null && key.endsWith( '}' ), `Variable \"${ key }\" does not end with \"}\"` );\n   });\n}\nfunction processVariablesConfig( config )\n{\n   if ( Array.isArray( config ))\n   {\n      for ( let i = 0; i < config.length; i++ ) {\n         processVariablesConfig( config[ i ] );\n      }\n      return;\n   }\n   if ( isJSON ( config ) )\n   {\n      // I assume only 1, but you know about assuming ...\n      for ( let key in config )\n      {\n         let valueToAdd = config[ key ] ;\n\n         testVariableKey( key );\n\n         // remove any leading and trailing single quotes\n         // so that using it for replacement will be easier.\n         valueToAdd.replace( /^'/, \"\" )\n         valueToAdd.replace( /'$/, \"\" )\n\n         // Need to test is constants exist for valueToAdd\n\n         return;\n      }\n   }\n   it( \"Variable Config must be valid\", ( ) =>\n   {\n      assert.isTrue( isJSON( config ), `Variable: \"${ config }\" must be an array of/or list of key/value pairs` );\n   });\n}\nfunction processLinkedTypesConfig( config )\n{\n   if ( Array.isArray ( config ) )\n   {\n      for ( let i = 0; i < config.length; i++ )\n      {\n         processLinkedTypesConfig( config[ i ] );\n      }\n      return;\n   }\n   if ( isJSON ( config ) )\n   {\n      describe( `Processing Linked accessory: ${ config.displayName }`, ( ) =>\n      {});\n\n      testAccessoryConfig( config );\n      return;\n   }\n\n   it( `Variable Config must be valid`, ( ) =>\n   {\n      assert.isTrue( isJSON( config ), `LinkedTypes: \"${ config }\" must be an array of/or list of key/value pairs` );\n   });\n}\nfunction testType( type )\n{\n   let ucKeyIndex = CMD4_DEVICE_TYPE_ENUM.properties.indexOfEnum( i => i.deviceName === type);\n   it( `Device Type: \"${ type }\" should be valid`, ( ) =>\n   {\n      assert.isAbove( ucKeyIndex, -1, `Invalid device type: ${ type }` );\n   });\n}\nfunction testName( name )\n{\n   it( `Device name: ${ name } should be valid`, ( ) =>\n   {\n      assert.isString( name, `Invalid name: ${ name }` );\n   });\n}\nfunction testModel ( model )\n{\n   it( `Device model: ${ model } should be valid`, ( ) =>\n   {\n      assert.isString( model, `Invalid model: ${ model }` );\n   });\n}\nfunction testStateChangeResponseTime ( stateChangeResponseTime )\n{\n   it( `Device stateChangeResponseTime: ${ stateChangeResponseTime } should be valid`, ( ) =>\n   {\n      assert.isNumber( stateChangeResponseTime, `Invalid stateChangeResponseTime: ${ stateChangeResponseTime }` );\n   });\n}\nfunction testInterval( interval )\n{\n   it( `Device interval: ${ interval } should be valid`, ( ) =>\n   {\n      assert.isNumber( interval, `Invalid interval: ${ interval }` );\n   });\n}\nfunction testCmd4_Mode( cmd4Mode )\n{\n   it( `Cmd4_Mode: ${ cmd4Mode } should be a valid string`, ( ) =>\n   {\n      let ucCmd4Mode = ucFirst( cmd4Mode );\n      assert.equal( ucCmd4Mode, \"Demo\", `Invalid Cmd4_Mode: ${ cmd4Mode }` );\n   });\n}\nfunction testTimeout( timeout )\n{\n   it( `Device timeout: ${ timeout } should be a valid number`, ( ) =>\n   {\n      assert.isNumber( timeout, \"Invalid timeout:\" + timeout );\n   });\n}\nfunction testStateCmd ( state_cmd )\n{\n   it( `Device state_cmd: ${ state_cmd } should be valid`, ( ) =>\n   {\n      assert.isString( state_cmd, `Invalid state_cmd: ${ state_cmd }` );\n   });\n}\nfunction testCharacteristicString ( characteristic )\n{\n   describe( `Testing characteristic string: ${ characteristic }`, ( ) =>\n   {\n      let ucCharacteristic = ucFirst( characteristic );\n      let characteristicIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.type === ucCharacteristic );\n\n      it( `Characteristic ${ characteristic } should be valid`, ( ) =>\n      {\n         assert.isAbove( characteristicIndex, -1, `Invalid characteristic: ${ characteristic }` );\n      });\n\n   });\n}\nfunction testCharacteristic ( characteristic, value )\n{\n   describe( `Testing characteristic: ${characteristic }`, ( ) =>\n   {\n      let characteristicIndex = CMD4_ACC_TYPE_ENUM.indexOfEnum( characteristic );\n\n      it( `Characteristic index: ${ characteristicIndex } should be valid`, ( ) =>\n      {\n         assert.isAbove( characteristicIndex, -1, `Invalid characteristic index` );\n      });\n\n\n      it( `Characteristic ${ characteristic } should be valid`, ( ) =>\n      {\n         assert.isNumber( characteristicIndex, `Invalid characteristic : ${ characteristic }` );\n      });\n\n      // Check if properties is not null\n      it( `Characteristic  ${ characteristic } properties should be valid`, ( ) =>\n      {\n         assert.isNotNull( CMD4_ACC_TYPE_ENUM.properties, `properties is null: ${ characteristic }` );\n      });\n\n      // Check if properties[ charisticIndex ] is not null\n      it( `Characteristic  ${ characteristic } properties[ ${ characteristicIndex }  should be valid`, ( ) =>\n      {\n         assert.isNotNull( CMD4_ACC_TYPE_ENUM.properties[ characteristicIndex ], `properties is null: ${ characteristic }` );\n      });\n\n      // Check if the characteristic has constant values to test\n      if ( Object.keys( CMD4_ACC_TYPE_ENUM.properties[ characteristicIndex ].validValues).length > 0 )\n      {\n         it( `Value: \"${ value }\" should be valid characteristic value`, ( ) =>\n         {\n            assert.property( CMD4_ACC_TYPE_ENUM.properties[ characteristicIndex ].validValues, value, `Could not find \" ${ value }\" for characteristic: ${ characteristic }` );\n         });\n      }\n   });\n}\nfunction testPollingConfig( pollingConfig )\n{\n   switch ( typeof pollingConfig )\n   {\n      case \"object\":\n      {\n         it( `Device polling: ${ pollingConfig } should be an array`, ( ) =>\n         {\n            assert.isArray( pollingConfig, \"Invalid polling:\" + pollingConfig );\n         });\n         for ( let cindex=0; cindex < pollingConfig.length; cindex ++)\n         {\n            describe( `Testing polling object:`, ( ) =>\n            {\n               for ( let pollingKey in pollingConfig[ cindex ] )\n               {\n\n                  switch ( pollingKey)\n                  {\n                     case constants.TIMEOUT:\n                     {\n                        testTimeout ( pollingConfig[ cindex ].timeout );\n                        break;\n                     }\n                     case constants.INTERVAL:\n\n                        testInterval( pollingConfig[ cindex ].interval );\n\n                        break;\n                     case constants.CHARACTERISTIC:\n                     {\n                        let value = pollingConfig[ cindex ].characteristic;\n                        // console.log( \"2 Testing %s\", value);\n                        testCharacteristicString( value );\n\n                        break;\n                     }\n                     default:\n                     {\n                        let value = pollingConfig[ cindex ][ pollingKey ];\n                        // console.log( \"3 Testing %s\", value);\n                        describe( `Testing polling characteristic: ${ pollingKey }`, ( ) =>\n                        {\n                           testCharacteristic ( pollingKey, value );\n                        });\n                     }\n                  }\n               }\n            });\n         }\n         break;\n      }\n      case \"boolean\":\n      {\n         it( `Device polling: ${ pollingConfig } should be a boolean`, ( ) =>\n         {\n            assert.isBoolean( pollingConfig, `Invalid polling: ${ pollingConfig }` );\n         });\n         break;\n      }\n      default:\n      {\n         it( `Device polling: ${ pollingConfig } should be an array or string`, ( ) =>\n         {\n            assert.typeOf( typeof pollingConfig, \"number\", `Invalid characteristic polling type: ${ pollingConfig }` );\n         });\n      }\n   }\n}\nfunction testFakegatoConfig( fakegatoConfig )\n{\n   switch ( typeof fakegatoConfig )\n   {\n      case \"object\":\n      {\n         // FakeGato Object - OK\n         for ( let fakegatoKey in fakegatoConfig )\n         {\n            let ucFakegatoKey = ucFirst( fakegatoKey );\n\n            switch ( ucFakegatoKey )\n            {\n               case constants.EVE:\n               case constants.FOLDER:\n               case constants.KEYPATH:\n               case constants.STORAGE:\n               case constants.STORAGEPATH:\n               case constants.POLLING:\n               {\n                  // console.log( \"Found ucKey '%s'\", ucFakegatoKey );\n                  break;\n               }\n               default:\n               {\n                  //console.log( \"Found default ucKey '%s'\", ucFakegatoKey );\n               }\n            }\n         }\n         break;\n      }\n      default:\n      {\n         it( `fakegato: ${ typeof fakegato } should be an object`, ( ) =>\n         {\n            assert.typeOf( typeof fakegatoConfig, \"number\", `Invalid fakegato type: ${ typeof fakegatoConfig }` );\n         });\n      }\n   }\n}\n"
  },
  {
    "path": "test/echoScripts/echo_0",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo 0;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_1",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \"1\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_ACTIVE",
    "content": "#!/bin/bash\necho \"blast\" > /tmp/blast;\n\nstdbuf -o0 echo ACTIVE;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_DISABLED",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \"DISABLED\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_ENABLED",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \"Enabled\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_INACTIVE",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo INACTIVE;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_On",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo On;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_after5seconds",
    "content": "#!/bin/bash\n\nsleep 5;\nstdbuf -o0 echo false;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_errorToStderr",
    "content": "#!/bin/bash\n\nstdbuf -e0 -i0 echo \"This message goes to stderr\" >&2;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_false",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo false;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_nothing",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \"\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_null",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \"null\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_nullAndErrorToStderr",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo null\nstdbuf -o0 e0 echo \"This message goes to stderr\" >&2;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_quoted0",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \\\"0\\\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_quoted1",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \\\"1\\\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_quotedFALSE",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \\\"False\\\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_quotedNULL",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \\\"NULL\\\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_quotedNothing",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \\\"   \\\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_quotedTRUE",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \\\"True\\\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_too_much",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo \"\";\nstdbuf -o0 echo \"second extra line\";\nstdbuf -o0 echo \"third extra line\";\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_true",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo true;\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/echo_true_withRcOf1",
    "content": "#!/bin/bash\n\nstdbuf -o0 echo true;\n\nexit 1;\n"
  },
  {
    "path": "test/echoScripts/justExitWithRCof0",
    "content": "#!/bin/bash\n\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/justExitWithRCof1",
    "content": "#!/bin/bash\n\nexit 1;\n"
  },
  {
    "path": "test/echoScripts/runToTimeoutRcOf0",
    "content": "#!/bin/bash\n\nsleep 1000000;\nexit 0;\n"
  },
  {
    "path": "test/echoScripts/runToTimeoutRcOf1",
    "content": "#!/bin/bash\n\nsleep 1000000;\nexit 1;\n"
  },
  {
    "path": "test/echoScripts/testGetSetValues.js",
    "content": "#!/opt/homebrew/bin/node\n\nconst fs = require( \"fs\" );\n\nfunction showHelp()\n{\n   console.log(`\n   Syntax: Get Device <Characteristic> < fn >\n           Set Device <Characteristic> [< value >] < fn >\n\n\n    Set writes stuff to < fn > as a required fn with\n      INPUTS.IO\n      INPUTS.DEVICE\n      INPUTS.CHARACTERISTIC\n      INPUTS.VALUE\n\n    Get echos what Set would have sent\n\n\n` );\n  process.exit( 666 );\n}\n\nfunction createDeviceFileName( fn, DEVICE, CHARACTERISTIC )\n{\n   return `${ fn }_${ DEVICE }_${ CHARACTERISTIC }`;\n}\n\nfunction doGet( )\n{\n   if ( ELEMENTS != 6 ) { showHelp( ); process.exit( 1 ); }\n\n   let fn = process.argv[5];\n\n   let deviceFile = createDeviceFileName( fn, DEVICE, CHARACTERISTIC );\n\n   let INPUTS;\n\n   try {\n     INPUTS = require( deviceFile );\n   } catch ( e ) {\n     console.log(`Cannot load fn: ${ deviceFile }, error: ${ e }`);\n     process.exit( 666 );\n   }\n\n   console.log( `${ INPUTS.VALUE }` );\n\n   process.exit( 0 );\n}\n\nfunction doSet( )\n{\n   if ( ELEMENTS != 7 ) { showHelp( ); process.exit( 1 ); };\n\n   let VALUE = process.argv[5];\n   let fn = process.argv[6];\n\n   let deviceFile = createDeviceFileName( fn, DEVICE, CHARACTERISTIC );\n\n   // Skip the fn\n   ELEMENTS--;\n\n   // Remove the old fn\n   try {\n     fs.unlinkSync( deviceFile );\n   } catch(err) {\n     // Don't care\n     // console.error( err )\n     // process.exit( 666 );\n   }\n\n   let data = `exports.IO=\"${ IO }\";\n      exports.DEVICE=\"${ DEVICE }\";\n      exports.CHARACTERISTIC=\"${ CHARACTERISTIC }\";\n      exports.VALUE=\"${ VALUE }\";\\n`;\n\n   // Write the arguments as requires\n   fs.writeFileSync( deviceFile, data, function( err )\n   {\n       console.log(` Error writing to fn: ${ deviceFile } error: ${ err }\\n`);\n       process.exit( 666 );\n   });\n\n   process.exit( 0 );\n}\n\nlet ELEMENTS = process.argv.length;\nif ( ELEMENTS < 4 ) { showHelp( ); process.exit( 1 ); }\n\nlet IO = process.argv[2];\nlet DEVICE = process.argv[3];\nlet CHARACTERISTIC = process.argv[4];\n\nswitch( IO )\n{\n    case \"Get\":\n       doGet( );\n       break;\n    case \"Set\":\n       doSet( );\n       break;\n    default:\n       console.log(`Invalid Get/Set: ${IO}` );\n       showHelp();\n}\nprocess.exit( 1 );\n"
  },
  {
    "path": "test/extractKeyValue.js",
    "content": "'use strict';\n\nvar CMD4_ACC_TYPE_ENUM = {\n   AccessoryFlags:                        0,\n   properties: {}\n};\nCMD4_ACC_TYPE_ENUM.properties =\n      {\n         0:   { type: \"AccessoryFlags\",\n                // characteristic: Characteristic.AccessoryFlags,\n                // props: {format: Characteristic.Formats.UINT32,\n                //         perms: [Characteristic.Perms.READ,\n                //                 Characteristic.Perms.NOTIFY\n                //                ]\n                //        },\n               validValues:\n                  {\"OPEN\":    0,\n                   \"CLOSED\":  1,\n                   \"OPENING\": 2,\n                   \"CLOSING\": 3,\n                   \"STOPPED\": 4\n                  }\n              }\n      };\n\nvar extractKeyValue = require( \"../utils/extractKeyValue.js\" );\n\ndescribe( \"Testing extractKeyValue\", ( ) =>\n{\n   it( \"extractKeyValue should be a function\", ( ) =>\n   {\n      assert.isFunction( extractKeyValue, \"extractKeyValue is not a function\" );\n   });\n\n   it( \"test 1 extractKeyValue should return correct key\", ( ) =>\n   {\n      let expectedKey = \"CLOSING\";\n      let value = 3;\n      let result = extractKeyValue( CMD4_ACC_TYPE_ENUM.properties[0].validValues, value );\n      assert.equal( result, expectedKey, \"Test 1 extractKeyValue( \" + value + \" ) returned:\" + result  + \" expected:\" +  expectedKey );\n   });\n\n   it( \"test 2 extractKeyValue should return undefined for no value\", ( ) =>\n   {\n      let expectedKey = undefined;\n      let value = undefined;\n      let result = extractKeyValue( CMD4_ACC_TYPE_ENUM.properties[\"0\"].validValues, value );\n      assert.equal( result, expectedKey, \"Test 1 extractKeyValue( \" + value + \" ) returned:\" + result  + \" expected:\" +  expectedKey );\n   });\n});\n"
  },
  {
    "path": "test/fakeGato.js",
    "content": "#!node\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\n\nlet Cmd4Accessory = require( \"../Cmd4Accessory\" ).Cmd4Accessory;\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\n\n\nlet Logger = require( \"../utils/Logger\" );\n\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n// Taken from https://stackoverflow.com/questions/11731072/dividing-an-array-by-filter-function\n//function partition(array, predicate)\n//{\n//   return array.reduce( ( acc, item ) => ( acc[+!predicate( item )].push( item ), acc ), [ [], [] ] );\n//}\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( `Quick Test of CMD4_DEVICE_TYPE_ENUM`, ( ) =>\n{\n   it( `CMD4_DEVICE_TYPE_ENUM.EOL ${ DEVICE_EOL }`, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( `Quick Test of CMD4_ACC_TYPE_ENUM`, ( ) =>\n{\n   it( `CMD4_ACC_TYPE_ENUM.EOL = ${ ACC_EOL }`, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\ndescribe('Testing FakeGato gets created', ( ) =>\n{\n   before( ( ) =>\n   {\n   });\n   after( ( ) =>\n   {\n   });\n\n   beforeEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   afterEach(function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n\n   });\n\n   it( `Test if Cmd4Platform exists`, function ( )\n   {\n      expect( Cmd4Platform ).not.to.be.a( \"null\", `Cmd4Platform was null` );\n   });\n\n   it( `Test creation of Accessory with FakeGato Thermo`, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"On\" },\n                                         { characteristic: \"Brightness\" }\n                                       ],\n               state_cmd: \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n               type:                   \"Thermostat\",\n               name:                   \"Thermostat\",\n               displayName:            \"Thermostat\",\n               temperatureDisplayUnits:\"CELSIUS\",\n               active:                 \"INACTIVE\",\n               currentTemperature:     20.0,\n               targetTemperature:      20.0,\n               currentHeatingCoolingState: 0,\n               targetHeatingCoolingState: 0,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"CurrentTemperature\" },\n                                         { characteristic: \"TargetTemperature\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\",\n               fakegato: {\n                  eve:                 \"thermo\",\n                  currentTemp:         \"CurrentTemperature\",\n                  setTemp:             \"TargetTemperature\",\n                  valvePosition:       0,\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n              }\n\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, `cmd4Platform is not an instance of Cmd4Platform` );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4Platform unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4Platform unexpected stderr received: ${ log.errBuf }` );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4ThermostatAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Light is not an instance of Cmd4Accessory` );\n      expect( cmd4ThermostatAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Thermostat is not an instance of Cmd4Accessory` );\n\n      done( );\n   });\n\n   it( `Test creation of Accessory with FakeGato room`, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"On\" },\n                                         { characteristic: \"Brightness\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n               type:                   \"Thermostat\",\n               name:                   \"Thermostat\",\n               displayName:            \"Thermostat\",\n               temperatureDisplayUnits: \"CELSIUS\",\n               active:                 \"INACTIVE\",\n               currentTemperature:     20.0,\n               targetTemperature:      20.0,\n               currentHeatingCoolingState: 0,\n               targetHeatingCoolingState: 0,\n               currentRelativeHumidity: 44,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"CurrentTemperature\" },\n                                         { characteristic: \"TargetTemperature\" },\n                                         { characteristic: \"CurrentRelativeHumidity\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\",\n               fakegato: {\n                  eve:                 \"room\",\n                  temp:                \"CurrentTemperature\",\n                  humidity:            \"CurrentRelativeHumidity\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\"\n               }\n\n            }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, `cmd4Platform is not an instance of Cmd4Platform` );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4Platform unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4Platform unexpected stderr received: ${ log.errBuf }` );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4ThermostatAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Light is not an instance of Cmd4Accessory` );\n      expect( cmd4ThermostatAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Thermostat is not an instance of Cmd4Accessory` );\n\n      done( );\n   });\n\n   it( `Test creation of Accessory with FakeGato door`, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"On\" },\n                                         { characteristic: \"Brightness\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n                 type:                 \"Door\",\n                 name:                 \"MyDoor\",\n                 currentPosition:      0,\n                 targetPosition:       0,\n                 contactSensorState:   \"CONTACT_DETECTED\",\n                 holdPosition:         \"FALSE\",\n                 obstructionDetected:  \"FALSE\",\n                 statusActive:         0,\n                 statusFault:          0,\n                 polling:              [ { characteristic: \"StatusActive\" },\n                                         { characteristic: \"StatusFault\" }\n                                       ],\n                 fakegato: {\n                    eve:               \"door\",\n                    status:            \"StatusActive\",\n                    storage:           \"fs\",\n                    storagePath:       \".homebridge/FakegatoStorage\",\n                    folder:            \"folderName\",\n                    keyPath:           \"/place/to/store/my/keys/\"\n                 },\n                 stateChangeResponseTime:     3,\n                 state_cmd:            \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n              }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, `cmd4Platform is not an instance of Cmd4Platform` );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4Platform unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4Platform unexpected stderr received: ${ log.errBuf }` );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4DoorAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Light is not an instance of Cmd4Accessory` );\n      expect( cmd4DoorAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Door is not an instance of Cmd4Accessory` );\n\n      done( );\n   });\n\n   it( `Test creation of Accessory with FakeGato power`, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"On\" },\n                                         { characteristic: \"Brightness\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"RotationDirection\" },\n                                         { characteristic: \"RotationSpeed\" },\n                                         { characteristic: \"On\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"energy\",\n                  // rotationSpeed used as an example.\n                  // Not really power characteristic\n                  power:               \"RotationSpeed\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, `cmd4Platform is not an instance of Cmd4Platform` );\n\n      assert.equal( \"\", log.logBuf, ` Cmd4Platform unexpected stdout received: ${ log.logBuf }` );\n      assert.equal( \"\", log.errBuf, ` Cmd4Platform unexpected stderr received: ${ log.errBuf }` );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4LightAccessory = cmd4Platform.createdCmd4Accessories[0];\n      let cmd4FanAccessory = cmd4Platform.createdCmd4Accessories[1];\n\n      expect( cmd4LightAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Light is not an instance of Cmd4Accessory` );\n      expect( cmd4FanAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Fan is not an instance of Cmd4Accessory` );\n\n      done( );\n   });\n\n   it( `Test incorrect characteristic throws fakegato error `, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"On\" },\n                                         { characteristic: \"Brightness\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"RotationDirection\" },\n                                         { characteristic: \"On\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"energy\",\n                  // An invalid characteristic.\n                  power:               \"BadData\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(/Invalid characteristic \"BadData\" for fakegato to log of \"power\"./);\n\n      done( );\n   });\n\n   it( `Test not defining polling characteristic throws fakegato error `, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               name:                   \"MyLight\",\n               displayName:            \"MyLight\",\n               statusMsg:              true,\n               type:                   \"Lightbulb\",\n               on:                     0,\n               brightness:             100,\n               polling:                [ { characteristic: \"On\" },\n                                         { characteristic: \"Brightness\" }\n                                       ],\n               state_cmd:              \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n            },\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"RotationDirection\" },\n                                         { characteristic: \"On\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"energy\",\n                  // rotationSpeed used as an example.\n                  // Not really power characteristic\n                  power:               \"rotationSpeed\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(/Characteristic: \"rotationSpeed\" for fakegato to log of \"power\" is not being polled.\\nHistory can not be updated continiously./);\n\n      done( );\n   });\n\n   it( `Test invalid Eve type throws error `, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"RotationDirection\" },\n                                         { characteristic: \"RotationSpeed\" },\n                                         { characteristic: \"On\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"BadType\",\n                  // rotationSpeed used as an example.\n                  // Not really power characteristic\n                  power:               \"RotationSpeed\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(/Invalid fakegato eve type: \"BadType\". It must be one of \\( energy, room, weather, door, motion, thermo, aqua \\). Check the Cmd4 README at: \"https:\\/\\/github.com\\/simont77\\/fakegato-history\"/);\n\n      done( );\n   });\n\n   it( `Test invalid fakegato key throws error `, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"RotationDirection\" },\n                                         { characteristic: \"RotationSpeed\" },\n                                         { characteristic: \"On\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"energy\",\n                  badKey:              \"badValue\",\n                  // rotationSpeed used as an example.\n                  // Not really power characteristic\n                  power:               \"RotationSpeed\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(/Invalid fakegato key: \"badKey\" in json.config for: \"Myv1Fan\"./);\n\n      done( );\n   });\n\n   it( `Test uppercase FakeGato Key throws an error.  It Always did `, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"rotationDirection\" },\n                                         { characteristic: \"rotationSpeed\" },\n                                         { characteristic: \"on\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"Energy\",\n                  // rotationSpeed used as an example.\n                  // Not really power characteristic\n                  power:               \"rotationSpeed\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect ( ( ) => cmd4Platform.discoverDevices( ) ).to.throw(/Invalid fakegato eve type: \"Energy\". It must be one of \\( energy, room, weather, door, motion, thermo, aqua \\). Check the Cmd4 README at: \"https:\\/\\/github.com\\/simont77\\/fakegato-history\"./);\n\n      assert.equal( 2, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n\n      done( );\n   });\n\n   it( `Test uppercase FakeGato Characteristic creates a warning `, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               type:                   \"Fan\",\n               name:                   \"Myv1Fan\",\n               rotationDirection:      1,\n               rotationSpeed:          100,\n               stateChangeResponseTime: 1,\n               polling:                [ { characteristic: \"rotationDirection\" },\n                                         { characteristic: \"rotationSpeed\" },\n                                         { characteristic: \"on\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"energy\",\n                  // rotationSpeed used as an example.\n                  // Not really power characteristic\n                  power:               \"RotationSpeed\",\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4FanAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      expect( cmd4FanAccessory ).to.be.a.instanceOf( Cmd4Accessory, `Fan is not an instance of Cmd4Accessory` );\n\n\n      //assert.equal( \"\", log.logBuf, ` Cmd4Platform unexpected stdout received: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mThe config.json FakeGato characteristic: RotationSpeed is Capitalized it should be: rotationSpeed.  In the near future this will be an Error so that Cmd4 can use homebridge-ui`, ` Cmd4Platform unexpected stderr received: ${ log.errBuf }` );\n      assert.equal( 3, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n\n\n      done( );\n   });\n\n   it( `Test FakeGato updateAccessoryAttribute creates a log for THERMO`, function( done )\n   {\n      let platformConfig =\n      {\n         accessories: [\n            {\n               type:                   \"Thermostat\",\n               name:                   \"MyThermostat\",\n               displayName:            \"MyThermostat\",\n               currentHeatingCoolingState: \"OFF\",\n               targetHeatingCoolingState:  \"OFF\",\n               currentTemperature:     22.2,\n               targetTemperature:      22.2,\n               temperatureDisplayUnits: \"CELSIUS\",\n               currentRelativeHumidity: 60,\n               targetRelativeHumidity: 60,\n               coolingThresholdTemperature: 21.4,\n               heatingThresholdTemperature: 20.2,\n               polling:                [ { characteristic: \"currentTemperature\" },\n                                         { characteristic: \"targetTemperature\" }\n                                       ],\n               fakegato: {\n                  eve:                 \"thermo\",\n                  currentTemp:         \"currentTemperature\",\n                  setTemp:             \"targetTemperature\",\n                  valvePosition:       0,\n                  storage:             \"fs\",\n                  storagePath:         \".homebridge/FakegatoStorage\",\n                  folder:              \"folderName\",\n                  keyPath:             \"/place/to/store/my/keys/\"\n               },\n               state_cmd:              \"./test/echoScripts/echo_ACTIVE\"\n             }\n         ]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false );\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      cmd4Platform.discoverDevices( );\n\n      let cmd4Accessory = cmd4Platform.createdCmd4Accessories[0];\n\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, `Fan is not an instance of Cmd4Accessory` );\n\n\n\n      assert.include( log.logBuf, `[39m Adding new platformAccessory: MyThermostat` );\n      assert.include( log.logBuf, `35mConfiguring platformAccessory: \\u001b[39mMyThermostat` );\n      assert.equal( 2, log.logLineCount, ` Unexpected number of stdout lines:  ${ log.logBuf }` );\n      //assert.equal( \"\", log.logBuf, ` Unexpected stdout: ${ log.logBuf }` );\n      assert.equal( 0, log.errLineCount, ` setCachedValue logged lines than one: ${ log.errBuf }` );\n\n      log.reset( );\n      log.setBufferEnabled( true );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      cmd4Accessory.updateAccessoryAttribute( CMD4_ACC_TYPE_ENUM.CurrentTemperature, 18);\n\n\n      assert.include( log.logBuf, `[39m \\u001b[90mLogging currentTemp: 18 setTemp:22.2 valvePosition:0`, `Incorrect stdout: ${ log.logBuf }` );\n\n      done( );\n   });\n});\n"
  },
  {
    "path": "test/getAccessoryNameFunctions.js",
    "content": "'use strict';\n\nconst { getAccessoryName, getAccessoryDisplayName } = require( \"../utils/getAccessoryNameFunctions\" );\n\ndescribe( \"Testing getAccessoryName LC\", ( ) =>\n{\n   it( \"getAccessoryName.js should be a function\", ( ) =>\n   {\n\n      assert.isFunction( getAccessoryName, \"getAccessoryName is not a function\" );\n   });\n\n   it( \"getAccessoryName should choose name first LC \", ( ) =>\n   {\n      let config = {displayName: \"Kodi\",\n                    name: \"blah\"\n      };\n      let expectedResult = \"blah\";\n      let result = getAccessoryName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryName should return name over displayName. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"getAccessoryName should choose displayName second LC \", ( ) =>\n   {\n      let config = { noName: \"blah\",\n                     displayName: \"Kodi\"\n      };\n      let expectedResult = \"Kodi\";\n      let result = getAccessoryName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryName should return displayName over name. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n})\n\ndescribe( \"Testing getAccessoryDisplayName LC\", ( ) =>\n{\n   it( \"getAccessoryDisplayName.js should be a function LC\", ( ) =>\n   {\n\n      assert.isFunction( getAccessoryDisplayName, \"getAccessoryDisplayName is not a function\" );\n   });\n\n   it( \"getAccessoryDisplayName should choose displayName first LC \", ( ) =>\n   {\n      let config = {displayName: \"Kodi\",\n                    name: \"blah\"\n      };\n      let expectedResult = \"Kodi\";\n      let result = getAccessoryDisplayName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"getAccessoryDisplayName should choose name second LC \", ( ) =>\n   {\n      let config = { name: \"Kodi\",\n                     configuredName: \"blah\"\n      };\n      let expectedResult = \"Kodi\";\n      let result = getAccessoryDisplayName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n})\n\n\ndescribe( \"Testing getAccessoryName UC\", ( ) =>\n{\n   it( \"getAccessoryName should choose name first UC \", ( ) =>\n   {\n      let config = {displayName: \"Kodi\",\n                    name: \"blah\"\n      };\n      let expectedResult = \"blah\";\n      let result = getAccessoryName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryName should return name over displayName. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"getAccessoryName should choose displayName second UC \", ( ) =>\n   {\n      let config = { NoName: \"blah\",\n                     displayName: \"Kodi\"\n      };\n      let expectedResult = \"Kodi\";\n      let result = getAccessoryName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryName should return displayName over name. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n})\n\ndescribe( \"Testing getAccessoryDisplayName.js\", ( ) =>\n{\n   it( \"getAccessoryDisplayName.js should be a function UC\", ( ) =>\n   {\n\n      assert.isFunction( getAccessoryDisplayName, \"getAccessoryDisplayName is not a function\" );\n   });\n\n   it( \"getAccessoryDisplayName should choose displayName first UC \", ( ) =>\n   {\n      let config = {displayName: \"Kodi\",\n                    name: \"blah\"\n      };\n      let expectedResult = \"Kodi\";\n      let result = getAccessoryDisplayName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"getAccessoryDisplayName should choose name second UC \", ( ) =>\n   {\n      let config = { name: \"Kodi\",\n                     configuredName: \"blah\"\n      };\n      let expectedResult = \"Kodi\";\n      let result = getAccessoryDisplayName( config );\n\n      assert.equal( result, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + result  + \" expected: \" +  expectedResult );\n   });\n})\n\n/* Mucking about.  Result, just use getAccessoryName\ndescribe( \"Testing logic of config.name\", ( ) =>\n{\n   it.skip( \"name should equal whatever config.[Nn]ame is\", ( ) =>\n   {\n      let config = { Name: \"Np\",\n                     ConfiguredName: \"Np\"\n      };\n\n      let configPassedToGetAccessoryNane = { Name: \"Kodi\",\n                     ConfiguredName: \"blah\"\n      };\n\n      // This does not do what I thought\n      let name = config.name = config.name = config.Name || getAccessoryName( configPassedToGetAccessoryNane );\n\n      let expectedResult = \"Kodi\";\n\n      // This fails with:\n      // AssertionError: getAccessoryDisplayName should return displayName over name. result: Np expected: Kodi: expected 'Np' to equal 'Kodi'\n      // + expected - actual\n      // -Np\n      // +Kodi\n      assert.equal( name, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + name  + \" expected: \" +  expectedResult );\n      assert.equal( config.name, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + name  + \" expected: \" +  expectedResult );\n      assert.equal( config.Name, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + name  + \" expected: \" +  expectedResult );\n\n   });\n\n   it.skip( \"name should equal whatever config.[Nn]ame is\", ( ) =>\n   {\n      let config = { Name: \"Np\",\n                     ConfiguredName: \"Np\"\n      };\n\n      let configPassedToGetAccessoryNane = { Name: \"Kodi\",\n                     ConfiguredName: \"blah\"\n      };\n\n      // This does do what is expected, but config.Name never gets set.\n      let name = config.name = config.name || getAccessoryName( configPassedToGetAccessoryNane );\n\n      let expectedResult = \"Kodi\";\n\n      assert.equal( name, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + name  + \" expected: \" +  expectedResult );\n      assert.equal( config.name, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + name  + \" expected: \" +  expectedResult );\n\n      // This fails with:\n      // AssertionError: getAccessoryDisplayName should return displayName over name. result: Kodi expected: Kodi: expected 'Np' to equal 'Kodi'\n      // + expected - actual\n      // -Np\n      // +Kodi\n      assert.equal( config.Name, expectedResult, \"getAccessoryDisplayName should return displayName over name. result: \"  + name  + \" expected: \" +  expectedResult );\n   });\n})\n*/\n"
  },
  {
    "path": "test/getAccessoryUUID.js",
    "content": "\"use strict\";\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\nvar pluginModule = require( \"../index\" );\n\nvar getAccessoryUUID = require( \"../utils/getAccessoryUUID.js\" );\n\ndescribe(\"Quick Testing load of index.js\", ( ) =>\n{\n   it(\"API should not be null\", ( ) =>\n   {\n      assert.isNotNull(_api, \"_api is null\" );\n   });\n\n   it(\"index.js loaded should not be null\", ( ) =>\n   {\n      assert.isNotNull(pluginModule, \"loading resulted in null\" );\n   });\n\n   it(\"UUIDGen should be found\", ( ) =>\n   {\n      var t = typeof _api.hap.uuid.generate;\n      assert.equal(t, \"function\" );\n   });\n});\n\ndescribe( \"Testing getAccessoryUUID.js\", ( ) =>\n{\n   it( \"getAccessoryUUID.js should be a function\", ( ) =>\n   {\n\n      assert.isFunction( getAccessoryUUID, \"getAccessoryUUID is not a function\" );\n   });\n\n   it( \"getAccessoryUUID should return a string \", ( ) =>\n   {\n      let config = {displayName: \"Kodi\",\n                    name: \"blah\"\n      };\n      let result = getAccessoryUUID( config, _api.hap.uuid);\n\n      assert.isString( result, \"getAccessoryUUID should return a string. result:: \"  + result );\n   });\n\n   it( \"getAccessoryUUID should return a string length 36 \", ( ) =>\n   {\n      let config = { name: \"Kodi\",\n                     configuredUUID: \"blah\"\n      };\n      let result = getAccessoryUUID( config, _api.hap.uuid);\n\n      assert.isString( result, \"getAccessoryUUID should return a string. result:: \"  + result );\n\n      assert.equal( result.length, 36, \"getAccessoryUUID return a string length of 36. result:: \"  + result.length );\n   });\n})\n"
  },
  {
    "path": "test/getSetAllValues.js",
    "content": "'use strict';\n\nconst os = require( \"os\" );\nconst cmd4StateDir = os.homedir( ) + \"/.homebridge/Cmd4Scripts/Cmd4States/\"\n\nvar glob = require( \"glob\" );\n\n\ndescribe( 'Cleaning up any old Cmd4States/Status_Device_* files ...', ( ) =>\n{\n   glob( cmd4StateDir + \"Status_Device_*\", null, function ( er, files )\n   {\n      for ( var file of files )\n      {\n         // To use the promise of unlink, it must be in an async function\n         // so put it in one.  Why not unLinkSync, because for whatever reason\n         // some files were notbremoved synchronously.\n         ( async( ) =>\n         {\n            await fs.unlink( file, function( err, result )\n            {\n               it('file:' + file +' should be removed', function ( done )\n               {\n                  if ( err && err.code != 'ENOENT' )\n                     assert.isNull( err, 'file not removed err: ' + err + \" result: \" + result );\n                  done( );\n               });\n            });\n         });\n      }\n   })\n});\n\n\n\nfunction removeStateFileThatShouldAlreadyBeRemoved( characteristicString )\n{\n   let stateFile = cmd4StateDir + \"Status_Device_\" + characteristicString;\n   if (fs.existsSync( stateFile ))\n   {\n      // console.log(' *** BLAST! The path exists.' + stateFile );\n      // To use the promise of unlink, it must be in an async function\n      // so put it in one.  Why not unLinkSync, because for whatever reason\n      // some files were notbremoved synchronously.\n      ( async( ) =>\n      {\n         fs.unlink( stateFile, function( err, result )\n         {\n            if ( err && err.code != 'ENOENT' )\n               assert.isNull( err, 'file not removed err: ' + err + \" result: \" + result );\n         });\n      });\n   }\n}\n\n\n// ***************** TEST LOADING **********************\n\n// This would be the plugin un-initialized\nvar pluginModule = require( \"../index\" );\n\ndescribe( \"Testing load of index.js\", ( ) =>\n{\n   it( \"index.js loaded should not be null\", ( ) =>\n   {\n      assert.isNotNull( pluginModule, \"loading resulted in null\" );\n   });\n\n   var t = typeof pluginModule.default;\n   it( \"index.js default initializer should be found\", ( ) =>\n   {\n      assert.equal( t, \"function\");\n   });\n});\n\n// ************ TEST UNINITIALIZED CMD4_DEVICE_TYPE_ENUM EOL **************\ndescribe( \"Quick Testing CMD4_DEVICE_TYPE_ENUM EOL\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM has EOL\", ( ) =>\n   {\n      assert.isNotNull( pluginModule.DEVICE_DATA.CMD4_DEVICE_TYPE_ENUM.EOL, \"EOL is null\" );\n   });\n\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL = \" + DEVICE_EOL, ( ) =>\n   {\n      assert.equal( pluginModule.DEVICE_DATA.CMD4_DEVICE_TYPE_ENUM.EOL, DEVICE_EOL );\n   });\n});\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\ndescribe( \"Testing homebridge API\", ( ) =>\n{\n   it( \"API should not be null\", ( ) =>\n   {\n      assert.isNotNull( _api, \"_api is null\");\n   });\n});\n\ndescribe( \"Initializing our plugin module\", ( ) =>\n{});\nvar cmd4 = pluginModule.default( _api );\n\n\n\n\n// ***************** TEST State.js **********************\nconst child_process = require( \"child_process\" );\n\n\n// *** TEST Get of Characteristic properties of default written data *******\ndescribe( \"Testing State.js Get Characteristics default written data ( \" + CMD4_ACC_TYPE_ENUM.EOL + \" of them )\", ( ) =>\n{\n   for ( let accTypeEnumIndex=0; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex ++ )\n   {\n      let characteristicString = cmd4.CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].type;\n      let cmd = \"./Extras/Cmd4Scripts/State.js\";\n      let args2 = \" Get Device \" + characteristicString + \" \";\n      let args = [\"Get\", \"Device\", characteristicString ];\n\n      it( accTypeEnumIndex + \": \" + cmd + args2 + \"should return something\", ( ) =>\n      {\n\n         // Why twice with two awaits, beats me !\n         removeStateFileThatShouldAlreadyBeRemoved( characteristicString );\n\n         const ps = child_process.spawnSync( cmd, args );\n\n         var data=\"not set by me\";\n\n         if ( ps.status !== 0 )\n         {\n             assert.equal( ps.status, 0, \"Process error stdout: \" + ps.stdout + \" stderr: \" + ps.stderr + \" status: \" + ps.status + \" signal: \" + ps.signal );\n         } else {\n           data = ps.stdout;\n           assert( data != \"\", \"data returned '\" + data + \"'\" );\n\n           assert( data.length != 0, \"data returned: \" + data.length );\n        }\n     });\n   }\n});\n\n// *** TEST Set of Characteristic properties *******\n\nlet dummyData = \"X0X0Test\";\nlet dummyDataR = \"\\\"\" + dummyData + \"\\\"\";\n\ndescribe( `Testing State.js Set Characteristics ( ${ CMD4_ACC_TYPE_ENUM.EOL } of them )`, ( ) =>\n{\n   for ( let accTypeEnumIndex=0; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex ++ )\n   {\n      let characteristicString = CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].type;\n      let cmd = \"./Extras/Cmd4Scripts/State.js\";\n      let args2 = \" Set Device \" + characteristicString + \" \" + dummyData;\n      let args = [\"Set\", \"Device\", characteristicString, dummyData];\n\n      const ps = child_process.spawnSync( cmd, args );\n\n      it( accTypeEnumIndex + \": \" + cmd + args2 + \" should return no data\", ( ) =>\n      {\n         var data=\"not set by me\";\n\n         // console.log( \"status is '%s'\", ps.status );\n         if ( ps.status !== 0 )\n         {\n            assert.equal( ps.status, 0, \"Process error stdout: \" + ps.stdout + \" stderr: \" + ps.stderr + \" status: \" + ps.status + \" signal: \" + ps.signal );\n         } else {\n           data = ps.stdout;\n           assert( data == \"\", \"No data should be returned: '\" + data + \"'\" );\n\n        }\n     });\n   }\n});\n\n// *** TEST Get of Characteristic properties after set of dummy data *******\n\ndescribe( \"Begin Testing\", ( ) =>\n{});\n\n\n// *** TEST Get of Characteristic properties of written data *******\ndescribe( \"Testing State.js Get Characteristics written data ( \" + cmd4.CMD4_ACC_TYPE_ENUM.EOL + \" of them ). Note: May fail even number of times ????\", ( ) =>\n{\n   for ( let accTypeEnumIndex=0; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex ++ )\n   {\n      let characteristicString = CMD4_ACC_TYPE_ENUM.properties[accTypeEnumIndex].type;\n      let cmd = \"./Extras/Cmd4Scripts/State.js\";\n      let args2 = \" Get Device \" + characteristicString + \" \";\n      let args = [\"Get\", \"Device\", characteristicString];\n\n      it( accTypeEnumIndex + \": \" + cmd + args2 + \"should return: \" + dummyDataR , ( ) =>\n      {\n         const ps = child_process.spawnSync( cmd, args );\n\n         var data=\"not set by me\";\n\n         if ( ps.status !== 0 )\n         {\n           assert.equal( ps.status, 0, \"Process error stdout: \" + ps.stdout + \" stderr: \" + ps.stderr + \" status: \" + ps.status + \" signal: \" + ps.signal );\n         } else {\n           data = ps.stdout;\n           // fixme ??? assert( data == dummyData, \"data returned: '\" + data + \"'\" );\n           //  The carriage return is stripped by getValue\n           assert( data == dummyDataR, \"data returned:\" + data );\n\n           assert( data.length != 0, \"data returned: \" + data.length );\n        }\n     });\n   }\n});\n"
  },
  {
    "path": "test/indexOfEnum.js",
    "content": "'use strict';\n\nlet { indexOfEnum } = require( \"../utils/indexOfEnum\" );\nObject.defineProperty(exports, \"indexOfEnum\", { enumerable: true, get: function () { return indexOfEnum.indexOfEnum; } });\n\n// ***************** TEST Plugin Initialized Variables ***************\n\ndescribe( \"Initializing our plugin module\", ( ) => {});\n\nlet _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( \"Quick Test load of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n      expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\ndescribe( \"Quick Test load of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n      expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n// ******** TEST indexOfEnum .*************\n\ndescribe( \"Test indexOfEnum import\", ( ) =>\n{\n   it( \"indexOfEnum should be a function \", ( ) =>\n   {\n      assert.isFunction( indexOfEnum, \"index of enum is not a function. Found: %s\", typeof indexOfEnum );\n   });\n});\n\ndescribe( \"Test indexOfEnum\", ( ) =>\n{\n   it( \"indexOfEnum should be identify a deviceName \", ( ) =>\n   {\n      let j = CMD4_DEVICE_TYPE_ENUM.WiFiSatellite;\n      let name = CMD4_DEVICE_TYPE_ENUM.properties[ j ].deviceName;\n      let ucKeyIndex = CMD4_DEVICE_TYPE_ENUM.properties.indexOfEnum( i => i.deviceName === name );\n      assert.equal( j, ucKeyIndex, \"index of enum should identify the device %s(%s). Found: %s\", name, j, ucKeyIndex );\n   });\n\n   it( \"indexOfEnum should identify a Characteristic Name \", ( ) =>\n   {\n      let j = CMD4_ACC_TYPE_ENUM.BatteryLevel;\n      let type = CMD4_ACC_TYPE_ENUM.properties[ j ].type;\n      let ucKeyIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.type === type);\n      assert.equal( j, ucKeyIndex, \"index of enum should identify the characteristic \" + type + \"(\" + j + \"). Found: \" + ucKeyIndex );\n   });\n   it( \"indexOfEnum should identify a Characteristic Name \", ( ) =>\n   {\n      let j = CMD4_ACC_TYPE_ENUM.CurrentRelativeHumidity;\n      //let j = CMD4_ACC_TYPE_ENUM.CurrentHumidifierDehumidifierState;\n      //let j = CMD4_ACC_TYPE_ENUM.blast;\n      console.log(\"j=\" + j);\n      let type = CMD4_ACC_TYPE_ENUM.properties[ j ].type;\n      let ucKeyIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.type === type);\n      assert.equal( j, ucKeyIndex, \"index of enum should identify the characteristic \" + type + \"(\" + j + \"). Found: \" + ucKeyIndex );\n   });\n   describe( \"Test each characteristic type\", ( ) =>\n   {\n      for ( let index = 0; index < ACC_EOL; index++ )\n      {\n         it( \"indexOfEnum should be identify a Characteristic Type \", ( ) =>\n         {\n             let type = CMD4_ACC_TYPE_ENUM.properties[ index ].type;\n             let ucKeyIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.type === type);\n             assert.equal( index, ucKeyIndex, \"index of enum should identify the characteristic \" + type + \"(\" + index + \"). Found: \" + ucKeyIndex );\n         });\n      }\n   });\n});\n"
  },
  {
    "path": "test/initPluginTest.js",
    "content": "\"use strict\";\n\n\n\n// ***************** TEST LOADING **********************\n\n\nvar pluginModule = require( \"../index\" );\n\n\ndescribe(`Testing load of index.js`, ( ) =>\n{\n   it( `index.js loaded should not be null`, ( ) =>\n   {\n      assert.isNotNull(pluginModule, `loading resulted in null` );\n   });\n\n   var t = typeof pluginModule.default;\n   it( `index.js default initializer should be found`, ( ) =>\n   {\n      assert.equal(t, `function` );\n   });\n});\n\ndescribe( `Testing homebridge API`, ( ) =>\n{\n   it( `API should not be null`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      assert.isNotNull( apiInstance, ` apiInstance is null` );\n   });\n});\n\ndescribe( `Testing homebridge setup`, ( ) =>\n{\n   it( `HAP Categories should not be null`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      assert.isNotNull( apiInstance.hap.Categories, `Categories is null` );\n   });\n\n   it( `HAP Characteristic should be a function`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      assert.isFunction( apiInstance.hap.Characteristic, \"Characteristic is not an function\" );\n   });\n   it( `HAP Accessory should be a function`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      assert.isFunction( apiInstance.hap.Accessory, `apiInstance.hap.Accessory is not an function` );\n   });\n   it( `HAP Service should be a function`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      assert.isFunction( apiInstance.hap.Service, ` apiInstance.hap.Service is not an function` );\n   });\n});\n\n\n// ***************** TEST Plugin Un Initialized Variables ***************\n\ndescribe( `Testing index.js plugin unInitialized variables.`, ( ) =>\n{\n   it( `Plugin CMD4_DEVICE_TYPE_ENUM should be a object`, ( ) =>\n   {\n      assert.isObject(CMD4_DEVICE_TYPE_ENUM, `CMD4_DEVICE_TYPE_ENUM is not an object` );\n   });\n   it( `Plugin CMD4_ACC_TYPE_ENUM should be a object`, ( ) =>\n   {\n      assert.isObject(CMD4_ACC_TYPE_ENUM, \"CMD4_ACC_TYPE_ENUM is not an object\" );\n   });\n   it( `Plugin CMD4_ACC_TYPE_ENUM.EOL should be defined`, ( ) =>\n   {\n      assert.equal(CMD4_DEVICE_TYPE_ENUM.EOL, DEVICE_EOL, `CMD4_DEVICE_TYPE_ENUM.EOL is incorrect` );\n   });\n   it( `Plugin CMD4_ACC_TYPE_ENUM.EOL should be defined`, ( ) =>\n   {\n      assert.equal(CMD4_ACC_TYPE_ENUM.EOL, ACC_EOL, \"CMD4_ACC_TYPE_ENUM.EOL is incorrect\" );\n   });\n});\n\n// ***************** TEST Plugin Initialized Variables ***************\n\ndescribe( `Testing index.js plugin Initialized variables.`, ( ) =>\n{\n   it( `Initialized Plugin CMD4_DEVICE_TYPE_ENUM.EOL should be correct`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      let cmd4 = pluginModule.default( apiInstance );\n\n      assert.equal(cmd4.CMD4_DEVICE_TYPE_ENUM.EOL, DEVICE_EOL, \"returned CMD4_DEVICE_TYPE_ENUM.EOL is incorrect\" );\n   });\n   it( `Initialized Plugin returned CMD4_ACC_TYPE_ENUM.EOL should be correct`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      let cmd4 = pluginModule.default( apiInstance );\n\n      assert.equal(cmd4.CMD4_ACC_TYPE_ENUM.EOL, ACC_EOL, `returned CMD4_ACC_TYPE_ENUM.EOL is incorrect` );\n   });\n\n   it( `Initialized Plugin returned CMD4_DEVICE_TYPE_ENUM.properties length should be correct`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      let cmd4 = pluginModule.default( apiInstance );\n      let properties = cmd4.CMD4_DEVICE_TYPE_ENUM.properties;\n\n      assert.equal(Object.keys(properties).length, DEVICE_EOL, 'returned CMD4_DEVICE_TYPE_ENUM.properties length is incorrect' );\n   });\n\n   it( `Initialized Plugin returned CMD4_ACC_TYPE_ENUM.properties length should be correct`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      let cmd4 = pluginModule.default( apiInstance );\n      let properties = cmd4.CMD4_ACC_TYPE_ENUM.properties;\n\n      assert.equal(Object.keys(properties).length, ACC_EOL, 'returned CMD4_ACC_TYPE_ENUM.properties length is incorrect' );\n   });\n\n   it( `Initialized Plugin returned CMD4_ACC_TYPE_ENUM.properties[0-${ ACC_EOL }].Characteristic should be defined`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      let cmd4 = pluginModule.default( apiInstance );\n      let properties = cmd4.CMD4_ACC_TYPE_ENUM.properties;\n\n      for ( let accTypeEnumIndex = 0; accTypeEnumIndex < ACC_EOL; accTypeEnumIndex++ )\n      {\n         assert.isNotNull( properties[ accTypeEnumIndex ].characteristic, `Characteristic at index: ${ accTypeEnumIndex } is null. found ${ properties[ accTypeEnumIndex ].characteristic }` );\n      }\n   });\n\n   it( `Initialized Plugin returned CMD4_DEVICE_TYPE_ENUM.properties[0-${ DEVICE_EOL }].service should be defined`, ( ) =>\n   {\n      let apiInstance = new HomebridgeAPI();\n      let cmd4 = pluginModule.default( apiInstance );\n      let properties = cmd4.CMD4_DEVICE_TYPE_ENUM.properties;\n\n      for ( let deviceTypeEnumIndex = 0; deviceTypeEnumIndex < DEVICE_EOL; deviceTypeEnumIndex++ )\n      {\n         if ( properties[ deviceTypeEnumIndex ].deprecated == true )\n               continue;\n\n         assert.isNotNull( properties[ deviceTypeEnumIndex ].service, `service at index: ${ deviceTypeEnumIndex } is null.. found ${ properties[ deviceTypeEnumIndex ].service }` );\n      }\n   });\n   /*\n   // While this works individualy, it intercepts loading from other unit tests\n   it( `Initialized Plugin returned CMD4_DEVICE_TYPE_ENUM.properties[0-${ DEVICE_EOL }].service should be defined`, ( ) =>\n   {\n      let Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\n\n\n      var apiInstance = new HomebridgeAPI(); // object we feed to Plugins\n\n      let cmd4 = pluginModule.default( apiInstance );\n      let CMD4_DEVICE_TYPE_ENUM = cmd4.CMD4_DEVICE_TYPE_ENUM;\n      let CMD4_ACC_TYPE_ENUM = cmd4.CMD4_ACC_TYPE_ENUM;\n      assert.equal( CMD4_DEVICE_TYPE_ENUM.EOL, DEVICE_EOL, \"returned CMD4_DEVICE_TYPE_ENUM.EOL is incorrect\" );\n      assert.equal( CMD4_ACC_TYPE_ENUM.EOL, ACC_EOL, `returned CMD4_ACC_TYPE_ENUM.EOL is incorrect` );\n\n      let config =\n      {\n          \"platform\": \"Cmd4\",\n          \"name\": \"Cmd4\",\n          \"accessories\":\n          [\n             {\n                \"type\": \"Switch\",\n                \"name\": \"PS_4\",\n                \"displayName\": \"PS_4\",\n                \"on\": false,\n              }\n           ]\n       }\n\n      let cmd4Platform = new Cmd4Platform( null, config, apiInstance );\n      let log = cmd4Platform.log;\n      log.setBufferEnabled( );\n\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n      assert.equal( log.logBuf, \"\", ` cmd4Platform unexpected output received: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` cmd4Platform unexpected error output received: ${ log.errBuf }` );\n      log.reset( );\n\n\n      apiInstance.emit(\"didFinishLaunching\");\n\n      assert.include( log.logBuf, `Cmd4Platform didFinishLaunching`, `didFinishLaunching Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\", ` cmd4Platform Unexpected stderr: ${ log.errBuf }` );\n\n   });\n   */\n});\n"
  },
  {
    "path": "test/internalRelatedTargetTests.js",
    "content": "\"use strict\";\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\n\nvar Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\n\ndescribe( \"Initializing our CMD4 Libraries \", ( ) => {});\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n // Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\ndescribe('Testing isRelatedTargetCharacteristicInSameDevice', ( ) =>\n{\n   afterEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   it('isRelatedTargetCharacteristicInSameDevice returns correctly for TemperatureSensor with no REQUIRED *Target* Characteristic', ( ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            statusMsg:                 true,\n            type:                      \"TemperatureSensor\",\n            displayName:               \"TemperatureSensor\",\n            name:                      \"TemperatureSensor\",\n            currentTemperature:        \"22.2\",\n            polling:                   [ { characteristic: \"currentTemperature\" }],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : TemperatureSensor`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCharacteristic polling for: TemperatureSensor`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: TemperatureSensor`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[33mAdding getCachedValue for TemperatureSensor characteristic: Name`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mSetting up accessory: TemperatureSensor for polling of: CurrentTemperature timeout: 60000 interval: 60000 queueName: \"Q:TemperatureSensor\"`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[33mAdding priorityGetValue for TemperatureSensor characteristic: CurrentTemperature`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mSetting up accessory: TemperatureSensor for polling of: CurrentTemperature timeout: 60000 interval: 60000`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n      // Not Target setValue\n      assert.notInclude( log.logBuf,  `[33mAdding prioritySetValue for TemperatureSensor characteristic: TargetTemperature`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      // Not Target polling\n      assert.notInclude( log.logBuf, `[90mSetting up accessory: TemperatureSensor for polling of: TargetTemperature timeout: 60000 interval: 60000`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      // No errors\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unexpected stderr: ${ log.errBuf }` );\n\n\n   });\n\n   it('isRelatedTargetCharacteristicInSameDevice returns correctly for TemperatureSensor with no REQUIRED *Target* Characteristic With QUEUE', ( done ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [{ queue: \"A\", queueType: \"WoRm\" }],\n         accessories: [\n         {\n            statusMsg:                 true,\n            type:                      \"TemperatureSensor\",\n            displayName:               \"TemperatureSensor\",\n            name:                      \"TemperatureSensor\",\n            queue:                     \"A\",\n            currentTemperature:        \"22.2\",\n            polling:                   [ { characteristic: \"currentTemperature\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : TemperatureSensor`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCharacteristic polling for: TemperatureSensor`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: TemperatureSensor`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf,  `[33mAdding getCachedValue for TemperatureSensor characteristic: Name`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mSetting up accessory: TemperatureSensor for polling of: CurrentTemperature timeout: 60000 interval: 60000 queueName: \"A\"`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[33mAdding priorityGetValue for TemperatureSensor characteristic: CurrentTemperature`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mSetting up accessory: TemperatureSensor for polling of: CurrentTemperature timeout: 60000 interval: 60000 queueName: \"A\"`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n      // Not setValue\n      assert.notInclude( log.logBuf, `[33mAdding prioritySetValue for TemperatureSensor characteristic: TargetTemperature`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      // Not polling\n      assert.notInclude( log.logBuf, `[90mSetting up accessory: TemperatureSensor for polling of: TargetTemperature timeout: 60000 interval: 60000 queueName: \"A\"`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      // No errors\n      assert.equal( log.errBuf, \"\", ` Cmd4Accessory Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('Polling complains related polling characteristic is missing', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"Door\",\n            displayName:               \"Door\",\n            statusMsg:                 true,\n            type:                      \"Door\",\n            currentPosition:           0,\n            targetPosition:            0,\n            positionState:             0,\n            polling:                   [ { characteristic: \"currentPosition\" },\n                                         // { characteristic: \"TargetPosition\" },\n                                         { characteristic: \"positionState\" } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n\n      assert.include( log.logBuf, `[34mCreating Platform Accessory type for : Door`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCharacteristic polling for: Door`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[90mCreated platformAccessory: Door`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[33mAdding getCachedValue for Door characteristic: Name`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, `[33mAdding priorityGetValue for Door characteristic: CurrentPosition`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n      assert.include( log.errBuf, `[33mWarning, With polling for \"currentPosition\" requested, you also must do polling of \"targetPosition\" or things will not function properl` , `Incorrect stderr: ${ log.errBuf }` );\n      assert.notInclude( log.logBuf, `[33mAdding prioritySetValue for Door characteristic: TargetPosition`, ` Cmd4Accessory Incorrect stdout: ${ log.logBuf }` );\n\n      done( );\n   });\n});\n"
  },
  {
    "path": "test/isAccDirective.js",
    "content": "'use strict';\n\nlet { indexOfEnum } = require( \"../utils/indexOfEnum\" );\nObject.defineProperty(exports, \"indexOfEnum\", { enumerable: true, get: function () { return indexOfEnum.indexOfEnum; } });\n\nlet isAccDirective = require( \"../utils/isAccDirective\" );\n\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n\n// ******** TEST isAccDirectivw .*************\n\ndescribe( `Test isAccDirective import`, ( ) =>\n{\n   it( `isAccDirectivw should be a function `, ( ) =>\n   {\n      assert.isFunction( isAccDirective, `isAccDirective is not a function. Found: ${ typeof isAccDirective }` );\n   });\n});\n\ndescribe( `Test isAccDirective`, ( ) =>\n{\n   it( `isAccDirective should identify a type `, ( ) =>\n   {\n      let type = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n      let rc = isAccDirective( type );\n      assert.isString( rc.type, `Unexpected result for isAccDirective` );\n      assert.equal( rc.type, type, `Expected result to be \"on\"` );\n      assert.equal( rc.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `UnExpected result` );\n   });\n   it( `isAccDirective should NOT identify an uppercase type `, ( ) =>\n   {\n      let ucType = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n      let rc =  isAccDirective( ucType );\n      assert.isNull( rc.accTypeEnumIndex, `Expected result to be null` );\n   });\n   it( `isAccDirective should NOT identify an unknown type `, ( ) =>\n   {\n      let type = \"Blast\";\n      let rc =  isAccDirective( type );\n      assert.isNull( rc.accTypeEnumIndex, `Expected result to be null` );\n   });\n   it( `isAccDirective should identify an uppercase type if upperCase is checked`, ( ) =>\n   {\n      let type = CMD4_ACC_TYPE_ENUM.accEnumIndexToLC( CMD4_ACC_TYPE_ENUM.On );\n      let ucType = CMD4_ACC_TYPE_ENUM.accEnumIndexToUC( CMD4_ACC_TYPE_ENUM.On );\n\n      let rc = isAccDirective( ucType, true );\n      assert.isString( rc.type, `Unexpected result for isAccDirective` );\n      assert.equal( rc.type, type, `Expected result to be \"on\"` );\n      assert.equal( rc.accTypeEnumIndex, CMD4_ACC_TYPE_ENUM.On, `UnExpected result` );\n   });\n});\n"
  },
  {
    "path": "test/isCmd4Directive.js",
    "content": "'use strict';\n\nlet { indexOfEnum } = require( \"../utils/indexOfEnum\" );\nObject.defineProperty(exports, \"indexOfEnum\", { enumerable: true, get: function () { return indexOfEnum.indexOfEnum; } });\n\nlet isCmd4Directive = require( \"../utils/isCmd4Directive\" );\n\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\n\n\n// ******** QUICK TEST of SETUP *************\ndescribe('Quick Test of Setup', ( ) =>\n{\n   it( `CMD4_ACC_TYPE_ENUM.EOL = ${ ACC_EOL }`, ( ) =>\n   {\n      expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n// ******** TEST isCmd4Directive .*************\n\ndescribe( `Test isCmd4Directive import`, ( ) =>\n{\n   it( `isCmd4Directive should be a function `, ( ) =>\n   {\n      assert.isFunction( isCmd4Directive, `isCmd4Directive is not a function. Found: ${ typeof isCmd4Directive }` );\n   });\n});\n\ndescribe( `Test isCmd4Directive`, ( ) =>\n{\n   it( `isCmd4Directive should identify a Cmd4 directive`, ( ) =>\n   {\n      let directive = \"polling\";\n      let rc = isCmd4Directive( directive );\n      assert.isString( rc.key, `Unexpected result for isCmd4Directive` );\n      assert.equal( rc.key, directive, `Expected result to be \"polling\"` );\n   });\n   it( `isCmd4Directive should NOT identify an uppercase type `, ( ) =>\n   {\n      let directive = \"Polling\";\n      let rc = isCmd4Directive( directive );\n      assert.isNull( rc, `Expected result to be null` );\n   });\n   it( `isCmd4Directive should NOT identify an unknown type `, ( ) =>\n   {\n      let directive = \"Blast\";\n      let rc = isCmd4Directive( directive );\n      assert.isNull( rc, `Expected result to be null` );\n   });\n   it( `isCmd4Directive should identify an uppercase type if upperCase is checked`, ( ) =>\n   {\n      let directive = \"Polling\";\n      let rc = isCmd4Directive( directive, true );\n      assert.isString( rc.key, `Expected result to be a string` );\n      assert.equal( rc.key, \"polling\", `Expected result to be \"polling\"` );\n   });\n});\n"
  },
  {
    "path": "test/isDevDirective.js",
    "content": "'use strict';\n\nlet { indexOfEnum } = require( \"../utils/indexOfEnum\" );\nObject.defineProperty(exports, \"indexOfEnum\", { enumerable: true, get: function () { return indexOfEnum.indexOfEnum; } });\n\nlet isDevDirective = require( \"../utils/isDevDirective\" );\nlet lcFirst = require( \"../utils/lcFirst\" );\n\n\nvar _api = new HomebridgeAPI(); // object we feed to Plugins\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n\n// ******** TEST isDevDirectivw .*************\n\ndescribe( `Test isDevDirective import`, ( ) =>\n{\n   it( `isDevDirectivw should be a function `, ( ) =>\n   {\n      assert.isFunction( isDevDirective, `isDevDirective is not a function. Found: ${ typeof isDevDirective }` );\n   });\n});\n\ndescribe( `Test isDevDirective`, ( ) =>\n{\n   it( `isDevDirective should identify a device `, ( ) =>\n   {\n      let deviceName = CMD4_DEVICE_TYPE_ENUM.devEnumIndexToC( CMD4_DEVICE_TYPE_ENUM.Switch );\n      let rc = isDevDirective( deviceName );\n      assert.isString( rc.deviceName, `Unexpected result for isDevDirective` );\n      assert.equal( rc.deviceName, deviceName, `Expected result to be \"on\"` );\n      assert.equal( rc.devEnumIndex, CMD4_DEVICE_TYPE_ENUM.Switch, `UnExpected result` );\n   });\n   it( `isDevDirective should NOT identify an lowercase deviceName `, ( ) =>\n   {\n      let deviceName = CMD4_DEVICE_TYPE_ENUM.devEnumIndexToC( CMD4_DEVICE_TYPE_ENUM.Switch );\n      let lcDeviceName = lcFirst( deviceName );\n      let rc =  isDevDirective( lcDeviceName );\n      assert.isNull( rc.devEnumIndex, `Expected result to be null` );\n   });\n   it( `isDevDirective should NOT identify an unknown deviceName `, ( ) =>\n   {\n      let deviceName = \"Blast\";\n      let rc =  isDevDirective( deviceName );\n      assert.isNull( rc.devEnumIndex, `Expected result to be null` );\n   });\n   it( `isDevDirective should identify an lower case deviceName if lowerCase is checked`, ( ) =>\n   {\n      let deviceName = CMD4_DEVICE_TYPE_ENUM.devEnumIndexToC( CMD4_DEVICE_TYPE_ENUM.Switch );\n      let lcDeviceName = lcFirst( deviceName );\n      let rc =  isDevDirective( lcDeviceName, true );\n\n      assert.isString( rc.deviceName, `Unexpected result for isDevDirective` );\n      assert.equal( rc.deviceName, deviceName, `Expected result to be \"on\"` );\n      assert.equal( rc.devEnumIndex, CMD4_DEVICE_TYPE_ENUM.Switch, `UnExpected result` );\n   });\n});\n"
  },
  {
    "path": "test/isJSON.js",
    "content": "'use strict';\n\nvar isJSON = require( \"../utils/isJSON.js\" );\n\ndescribe( \"Testing isJSON\", ( ) =>\n{\n   it( \"isJSON should be a function\", ( ) =>\n   {\n      assert.isFunction( isJSON, \"isJSON is not a function\" );\n   });\n\n   it( \"isJSON should correctly identify a JSON object\", ( ) =>\n   {\n      let data = { \"name\": \"John\"};\n      let expectedResult = true;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isJSON should return false for a string\", ( ) =>\n   {\n      let data = \"abcdef\";\n      let expectedResult = false;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isJSON should return false for a number\", ( ) =>\n   {\n      let data = 12345;\n      let expectedResult = false;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isJSON should return false for a float\", ( ) =>\n   {\n      let data = 3.1415;\n      let expectedResult = false;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isJSON should return false for a boolean\", ( ) =>\n   {\n      let data = false;\n      let expectedResult = false;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isJSON should return false for an array\", ( ) =>\n   {\n      let data = [1,2,3,4];\n      let expectedResult = false;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isJSON should return false for a undefined\", ( ) =>\n   {\n      let data = undefined;\n      let expectedResult = false;\n      let result = isJSON( data );\n      assert.equal( result, expectedResult, \"isJSON( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n})\n\n"
  },
  {
    "path": "test/isNumeric.js",
    "content": "'use strict';\n\nvar isNumeric = require( \"../utils/isNumeric.js\" );\n\ndescribe( \"Testing isNumeric\", ( ) =>\n{\n   it( \"isNumeric should be a function\", ( ) =>\n   {\n      assert.isFunction( isNumeric, \"isNumeric is not a function\" );\n   });\n\n   it( \"isNumeric should correctly identify a string number\", ( ) =>\n   {\n      let data = \"12345\";\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isNumeric should correctly identify a string float\", ( ) =>\n   {\n      let data = \"3.1415\";\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isNumeric should correctly identify a number\", ( ) =>\n   {\n      let data = 12345;\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isNumeric should correctly identify a float\", ( ) =>\n   {\n      let data = 3.1415;\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isNumeric should correctly identify a negative float\", ( ) =>\n   {\n      let data = -3.1415;\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isNumeric should correctly identify a 0\", ( ) =>\n   {\n      let data = 0;\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( `isNumeric should correctly identify a \"0\"`, ( ) =>\n   {\n      let data = \"0\";\n      let expectedResult = true;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n\n\n   it( \"isNumeric should correctly fail a character string\", ( ) =>\n   {\n      let data = \"One\";\n      let expectedResult = false;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"isNumeric should correctly fail an undefined\", ( ) =>\n   {\n      let data = undefined;\n      let expectedResult = false;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n   it( \"isNumeric should correctly fail a null\", ( ) =>\n   {\n      let data = null;\n      let expectedResult = false;\n      let result = isNumeric( data );\n      assert.equal( result, expectedResult, \"isNumeric( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n})\n\n"
  },
  {
    "path": "test/loadPluginTest.js",
    "content": "\"use strict\";\n\n// ***************** TEST LOADING **********************\n\n\nvar pluginModule = require( \"../index\" );\nvar CMD4_ACC_TYPE_ENUM = pluginModule.ACC_DATA.CMD4_ACC_TYPE_ENUM;\nvar CMD4_DEVICE_TYPE_ENUM = pluginModule.DEVICE_DATA.CMD4_DEVICE_TYPE_ENUM;\n\n// While the above method is better, It doesn't check that\n// the key values are sequential.\n// You cannot break out of forEach ....\nfunction getIndexOfValue( obj, value )\n{\n   let count = 0;\n   let found = -1;\n   Object.keys( obj ).forEach( function( key )\n   {\n      // console.log( \"Checking: \" + key + \" count: \" + count + \" obj[key]: \" + obj[key] + \" for: \" + value + \" t1: \" + typeof obj[key] + \" t2: \" + typeof value );\n      if ( obj[key] == value && value == count ) { found = value }\n      count+=1;\n   });\n   return found;\n}\n\n// ************ TEST PLUGIN WAS Loaded Successfully **************\ndescribe( \"Testing load of index.js\", ( ) =>\n{\n   it( \"Testing require of index.js\", ( ) =>\n   {\n      expect( pluginModule ).not.to.be.a( \"null\", \"loaded plugin was null\" );\n   });\n\n   it( \"index.js default initializer should be found\", ( ) =>\n   {\n      expect( pluginModule.default ).to.be.a( \"function\", \"plugin has no default init function t: \" + typeof pluginModule.default);\n   });\n});\n\n// ************ TEST UNINITIALIZED PLUGIN **************\ndescribe( \"Testing uninitialized plugin\", ( ) =>\n{\n   // DEVICE_TYPE Testing\n   it( \"CMD4_DEVICE_TYPE_ENUM is defined\", ( ) =>\n   {\n      expect( CMD4_DEVICE_TYPE_ENUM ).not.to.be.a( \"null\", \"CMD4_DEVICE_TYPE_ENUM is null\" );\n   });\n   it( \"CMD4_DEVICE_TYPE_ENUM has EOL\", ( ) =>\n   {\n      expect( CMD4_DEVICE_TYPE_ENUM.EOL ).not.to.be.a( \"null\", \"CMD4_DEVICE_TYPE_ENUM.EOL is null\" );\n   });\n\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL = \" + DEVICE_EOL, ( ) =>\n   {\n      expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL, \"CMD4_DEVICE_TYPE_ENUM.EOL. Expected: \" + DEVICE_EOL + \" found: \" + CMD4_DEVICE_TYPE_ENUM.EOL );\n   });\n\n   it( \"CMD4_DEVICE_TYPE_ENUM[ 0-\" +  CMD4_DEVICE_TYPE_ENUM.EOL + \" ] to have a valid value\", ( ) =>\n   {\n      for ( let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++)\n      {\n         let keyIndex = getIndexOfValue( CMD4_DEVICE_TYPE_ENUM, index );\n         expect( keyIndex ).to.equal( index, \"Expected value at index: \" + index + \" to be: \" + index + \" found: \" + keyIndex );\n      }\n   });\n\n   // ACC_TYPE Testing\n   it( \"CMD4_ACC_TYPE_ENUM is defined\", ( ) =>\n   {\n      expect( CMD4_ACC_TYPE_ENUM ).not.to.be.a( \"null\", \"CMD4_ACC_TYPE_ENUM is null\" );\n   });\n   it( \"CMD4_ACC_TYPE_ENUM has EOL\", ( ) =>\n   {\n      expect( CMD4_ACC_TYPE_ENUM.EOL ).not.to.be.a( \"null\", \"CMD4_ACC_TYPE_ENUM.EOL is null\" );\n   });\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n      expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL, \"CMD4_ACC_TYPE_ENUM.EOL. Expected: \" + ACC_EOL + \" found: \" + CMD4_ACC_TYPE_ENUM.EOL );\n   });\n\n   it( \"CMD4_ACC_TYPE_ENUM[ 0-\" + CMD4_ACC_TYPE_ENUM.EOL + \" ] to have a valid value\", ( ) =>\n   {\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n      {\n         let keyIndex = getIndexOfValue( CMD4_ACC_TYPE_ENUM, index );\n         expect( keyIndex ).to.equal( index, \"Expected ACC ENUM at index: \" + index + \" to be: \" + index + \" found: \" + keyIndex );\n      }\n   });\n});\n"
  },
  {
    "path": "test/mocha-setup",
    "content": "// Define common functions and values for all unit tests.\n\nconst which = require('which');\nconst path = require( \"path\" );\n\n// Get the real path of homebridge instead of a dev dependancy,\n// which caused issues if you forget to update dependancies but\n// upgrade homebridge.\nconst homebridgePath = which.sync( 'homebridge', { nothrow: true } )\n\nlet apiPath;\nif ( homebridgePath )\n{\n   let dirname = path.dirname( homebridgePath );\n\n   console.log( \"Found homebridge in path %s\", dirname );\n   apiPath = `${ dirname }/../lib/node_modules/homebridge/lib/api`;\n   global.HomebridgeAPI = require( apiPath ).HomebridgeAPI;\n\n   if ( ! global.HomebridgeAPI )\n   {\n      console.log( \"homebridgeAPI not available !!!\" );\n      process.exit( 10 );\n   }\n\n   // For serializing/deserializing arrays of accessories\n   let platformAccessoryPath = `${ dirname }/../lib/node_modules/homebridge/lib/platformAccessory`;\n   global.platformAccessory_1 = require( platformAccessoryPath );\n\n} else\n{\n   console.log( \"homebridge not found !!!\" );\n   process.exit( 10 );\n}\nconsole.log( \"Found api in %s\", apiPath );\n\n// IMPORTANT - ALL GLOBALS MUST BE DEFINED IN .eslintrc.json for lint to work\nglobal.fs = require( 'fs' );\nglobal.assert = require( \"chai\" ).assert;\nglobal.expect = require( \"chai\" ).expect;\nglobal.sinon  = require( \"sinon\" );\n\nglobal.ACC_EOL = 255;\nglobal.DEVICE_EOL = 81;\nglobal.FORMAT_EOL = 11;\nglobal.UNITS_EOL = 5;\nglobal.PERMS_EOL = 9;\nglobal.ACCESS_EOL = 3;\n\n// These would be the uninitialized values, used for unit testing\nglobal.ACC_DATA = require( '../lib/CMD4_ACC_TYPE_ENUM' );\nglobal.CMD4_ACC_TYPE_ENUM = ACC_DATA.CMD4_ACC_TYPE_ENUM;\n\nglobal.DEVICE_DATA = require( '../lib/CMD4_DEVICE_TYPE_ENUM' );\nglobal.CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.CMD4_DEVICE_TYPE_ENUM;\n\nglobal.CHAR_DATA = require( `../lib/CMD4_CHAR_TYPE_ENUMS` );\nglobal.CMD4_CHAR_TYPE_ENUMS = CHAR_DATA.CMD4_CHAR_TYPE_ENUMS;\n\n\nglobal.Logger = require(\"../utils/Logger\");\n\n\n// A true sleep ( blocking ).\nconst moment = require( \"moment\" );\nglobal.sleep = function( secondsToSleep = 1 )\n{\n   let sleepUntill = moment( ).add( secondsToSleep, 'seconds');\n   while( moment ( ).isBefore( sleepUntill ) ) { /* block the process */ }\n}\n\nglobal.accEnumIndexToC = function( index )\n{\n   return CMD4_ACC_TYPE_ENUM.properties[ index ].type;\n}\nglobal.devEnumIndexToC = function( index )\n{\n   return CMD4_DEVICE_TYPE_ENUM.properties[ index ].deviceName;\n}\n\n// How it's used\n// sleep( 10 );\n\nglobal.cleanStatesDir = function( )\n{\n   const os = require( \"os\" );\n   const cmd4StateDir = os.homedir( ) + \"/.homebridge/Cmd4Scripts/Cmd4States/\"\n\n   var glob = require( \"glob\" );\n\n\n   glob( cmd4StateDir + \"Status_Device_*\", null, function ( er, files )\n   {\n      for ( var file of files )\n      {\n         // To use the promise of unlink, it must be in an async function\n         // so put it in one.  Why not unLinkSync, because for whatever reason\n         // some files were notbremoved synchronously.\n         ( async( ) =>\n         {\n            await fs.unlink( file, function( err, result )\n            {\n                  if ( err && err.code != 'ENOENT' )\n                     console.log( 'file not removed err: ' + err + \" result: \" + result );\n            });\n         });\n      }\n   })\n}\n\n"
  },
  {
    "path": "test/pollingTest.js",
    "content": "#!node\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\nlet constants = require( \"../cmd4Constants\" );\n\nlet Cmd4Accessory = require( \"../Cmd4Accessory\" ).Cmd4Accessory;\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\nlet Cmd4PriorityPollingQueue = require( \"../Cmd4PriorityPollingQueue\" ).Cmd4PriorityPollingQueue;\n\n\n// Hierarchy variables\nlet HV = require( \"../utils/HV\" );\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\ndescribe('Testing Cmd4Accessory polling', ( ) =>\n{\n   beforeEach(function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   afterEach(function( )\n   {\n      if (this.currentTest.state == 'failed')\n      {\n         // Clear any timers created for any polling queue\n         Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n         {\n            let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n            Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n            {\n               let timer = queue.listOfRunningPolls[ key ];\n               clearTimeout( timer );\n            });\n         });\n      }\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n   });\n   let cmd4Accessory;\n\n   it( \"Test if Cmd4Accessory exists\", function ( )\n   {\n      expect( Cmd4Accessory ).not.to.be.a( \"null\", \"Cmd4Accessory was null\" );\n   });\n\n   it( \"Test init Cmd4Accessory has default polling messages\", function( done )\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         on:                           0,\n         polling:                      true,\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1 };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      expect( cmd4Accessory ).to.be.a.instanceOf( Cmd4Accessory, \"Cmd4Accessory is not an instance of Cmd4Accessory\" );\n\n      assert.include( log.logBuf, \"[90mPolling config is Default Polling. Nothing to check for unset polling characteristics\\u001b\" , `Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.logBuf, \"[90mSetting up which characteristics will be polled for MySwitch\\u001b\" , `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\" , `Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n\n   it('cmd4Accessory determineCharacteristicsToPollForAccessory works for non queued polling characteristics.', ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         on:                           0,\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1 };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      cmd4Accessory[\"polling\"] = [ { characteristic: \"on\", \"timeout\":3000, \"interval\": 1 } ];\n\n      cmd4Accessory.determineCharacteristicsToPollForAccessory( cmd4Accessory );\n      assert.equal( Object.keys(cmd4Accessory.listOfPollingCharacteristics).length, 1, `Incorrect number of listOfPollingCharacteristics` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"Q:MySwitch\" ];\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PriorityPollingQueue\" );\n      assert.equal( queue.lowPriorityQueue.length, 1, `Incorrect number of lowPriorityQueue Entries` );\n\n\n      assert.include( log.logBuf, `[90mSetting up accessory: MySwitch for polling of: On timeout: 3000 interval: 1000 queueName: \"Q:MySwitch\"\\u001b` , `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\" , `Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('cmd4Accessory characteristic polling interval/timeout changes recognized.', ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         on:                           0,\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1 };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      cmd4Accessory[\"polling\"] = [ { characteristic: \"on\", \"timeout\":1234, \"interval\": 99 } ];\n\n      cmd4Accessory.determineCharacteristicsToPollForAccessory( cmd4Accessory );\n\n\n      assert.include( log.logBuf, `[90mSetting up accessory: MySwitch for polling of: On timeout: 1234 interval: 99000 queueName: \"Q:MySwitch\"\\u001b` , `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\" , `Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('cmd4Accessory characteristic polling recognizes default accessory interval/timeout.', ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         timeout:                      5500,\n         interval:                     44,\n         on:                           0,\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1 };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      cmd4Accessory[\"polling\"] = [ { characteristic: \"on\" } ];\n\n      cmd4Accessory.determineCharacteristicsToPollForAccessory( cmd4Accessory );\n\n\n      assert.include( log.logBuf, `[90mSetting up accessory: MySwitch for polling of: On timeout: 5500 interval: 44000 queueName: \"Q:MySwitch\"\\u001b` , `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\" , `Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('cmd4Accessory characteristic polling recognizes parent interval/timeout.', ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         on:                           0,\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let hV = new HV();\n      hV.timeout = 77000;\n      hV.interval = 22000;\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1, \"hV\": hV };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      cmd4Accessory[\"polling\"] = [ { characteristic: \"on\" } ];\n\n      cmd4Accessory.determineCharacteristicsToPollForAccessory( cmd4Accessory );\n\n\n      assert.include( log.logBuf, `[90mSetting up accessory: MySwitch for polling of: On timeout: 77000 interval: 22000 queueName: \"Q:MySwitch\"\\u001b` , `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\" , `Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('cmd4Accessory default polling recognizes parent interval/timeout.', ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         on:                           0,\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let hV = new HV();\n      hV.timeout = 88000;\n      hV.interval = 41000;\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1, \"hV\": hV };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      cmd4Accessory[\"polling\"] = true;\n\n      cmd4Accessory.determineCharacteristicsToPollForAccessory( cmd4Accessory );\n\n\n      assert.include( log.logBuf, `[90mAdding MySwitch On  record.timeout: 88000 record.interval: 41000  to Polled Queue Q:MySwitch\\u001b` , `Incorrect stdout: ${ log.logBuf }` );\n      assert.equal( log.errBuf, \"\" , `Unexpected stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('cmd4Accessory characteristic polling short timeout generates warning.', ( done ) =>\n   {\n      let config =\n      {\n         name:                         \"MySwitch\",\n         displayName:                  \"MySwitch\",\n         statusMsg:                    true,\n         type:                         \"Switch\",\n         on:                           0,\n         polling:                      [ { characteristic: \"on\", timeout: 2, interval: 99 } ],\n         state_cmd:                    \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n      }\n      let parentInfo={ \"CMD4\": constants.PLATFORM, \"LEVEL\": -1 };\n\n      const log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      cmd4Accessory = new Cmd4Accessory( log, config, _api, [ ], parentInfo );\n\n      assert.include( log.logBuf, `[90mSetting up accessory: MySwitch for polling of: On timeout: 2 interval: 99000 queueName: \"Q:MySwitch\"` , `Incorrect stdout: ${ log.logBuf }` );\n      assert.include( log.errBuf, `[33mTimeout for: MySwitch is in milliseconds. A value of: 2 seems pretty low.\\u001b[39m` , `Incorrect stderr: ${ log.errBuf }` );\n\n      done( );\n   });\n\n   it('Cmd4Platform starts polling of 1 characteristic.', ( done ) =>\n   {\n      let platformConfig =\n      {\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            polling:                   [ { characteristic: \"on\", interval: 310 } ],\n            state_cmd:                 \"node ./Extras/Cmd4Scripts/Examples/AnyDevice\"\n         }]\n      }\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of listOfCreatedPriorityPollingQueues` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"Q:MySwitch\" ];\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PriorityPollingQueue\" );\n      assert.equal( queue.lowPriorityQueue.length, 1, `Incorrect number of lowPriorityQueue Entries` );\n\n\n      // For unit testing, start te polling now\n      cmd4Platform.startPolling( 0 );\n\n      // Staggered Polling takes 3 seconds to start\n      setTimeout( () =>\n      {\n\n         assert.include( log.logBuf, `[90mKicking off polling for: MySwitch On interval:310000, staggered:3000\\u001b` , `Incorrect stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, \"Started staggered kick off of 1 polled characteristics\" , `Incorrect stdout: ${ log.logBuf }` );\n\n\n         // Clear any timers created for any polling queue\n         Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n         {\n            let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n            Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n            {\n               let timer = queue.listOfRunningPolls[ key ];\n               clearTimeout( timer );\n            });\n         });\n\n         done( );\n\n      }, 6000);\n   }).timeout(7000);\n});\n"
  },
  {
    "path": "test/sanityTests",
    "content": "test/Cmd4Storage.js\ntest/HV.js\ntest/cmd4Constants.js\ntest/CMD4_CHAR_TYPE_ENUMS.js\ntest/CMD4_ACC_TYPE_ENUM.js\ntest/CMD4_DEVICE_TYPE_ENUM.js\ntest/isAccDirective.js\ntest/isDevDirective.js\ntest/isCmd4Directive.js\ntest/configTest.js\ntest/loadPluginTest.js\ntest/Cmd4Accessory.js\ntest/internalRelatedTargetTests.js\ntest/Cmd4Platform.js\ntest/Cmd4AccessoryGetValue.js\ntest/Cmd4AccessorySetValue.js\ntest/Cmd4Mode.js\ntest/Cmd4PriorityPollingQueue.js\ntest/initPluginTest.js\ntest/fakeGato.js\ntest/pollingTest.js\ntest/Cmd4PlatformRestartTests.js\n"
  },
  {
    "path": "test/systemTest.js",
    "content": "#!node\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\nlet constants = require( \"../cmd4Constants\" );\n\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\nlet Cmd4PriorityPollingQueue = require( \"../Cmd4PriorityPollingQueue\" ).Cmd4PriorityPollingQueue;\n\n\n// Duplicated from Cmd4PriorityPollingQueue.js\nlet HIGH_PRIORITY_SET = 0;\n//let HIGH_PRIORITY_GET = 1;\n//let LOW_PRIORITY_GET = 2;\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\ndescribe('WoRM - Testing Cmd4PriorityPollingQueue recovery correction', ( ) =>\n{\n   before( ( ) =>\n   {\n      sinon.stub( process, `exit` );\n\n      cleanStatesDir();\n\n   });\n   after( ( ) =>\n   {\n      process.exit.restore( );\n   });\n   beforeEach( function( )\n   {\n      settings.arrayOfAllStaggeredPollingCharacteristics = [ ];\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n\n   });\n\n   it( `Worm Test HighPriority \"Set\" Entry passes without errors`, ( done ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         statusMsg:                    true,\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"./test/echoScripts/justExitWithRCof0\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false ); // Not to be turned on !!\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( 0, log.errLineCount, ` Unexpected number of stderr lines:  ${ log.errBuf }` );\n\n      log.reset( );\n      log.setOutputEnabled( true );\n      log.setDebugEnabled( false );\n\n      // The queue setValue will just return successful\n      // and do the actual setValue later\n      var dummyCallback = function( rc )\n      {\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n      };\n\n      // Call the setValue bound function, which is prioritySetValue\n      //cmd4SwitchAccessory.service.getCharacteristic(\n      //                      CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.On ]\n      //                      .characteristic ).setValue( true, dummyCallback );\n\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: 1, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_SET, cmd4PriorityPollingQueue );\n\n      // Only 1 line since statusMsg: true\n      assert.equal( 1, log.logLineCount, ` Unexpected number of stdout lines:  ${ log.logBuf }` );\n      assert.include( log.logBuf, `[34mSetting MySwitch On\\u001b` , `expected stdout: ${ log.logBuf }` );\n\n      assert.equal( 0, log.errLineCount, ` Unexpected number of stderr lines:  ${ log.errBuf }` );\n      assert.equal( log.errBuf, \"\", ` Unexpected stderr:  ${ log.errBuf }` );\n\n      done( );\n\n   });\n\n   it( `Worm Test HighPriority \"Get\" Entry passes without errors`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false ); // Not to be turned on !!\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n      assert.equal( queue.queueRetryCount, 0, `Incorrect queueRetryCount` );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n      queue.lowPriorityQueue = [];\n\n      //Make sure no polling happens\n      assert.equal( queue.lowPriorityQueue.length, 0, `Incorrect number of low level polling characteristics` );\n      Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n      {\n         let timer = queue.listOfRunningPolls[ key ];\n         clearTimeout( timer );\n      });\n\n      clearTimeout( queue.pauseTimer );\n      queue.pauseTimerTimeout = 0;\n\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      assert.equal( 0, log.errLineCount, ` Unexpected number of stderr lines:  ${ log.errBuf }` );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false ); // Not to be turned on !!\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      var allDoneCallback = function( allDoneCount )\n      {\n         assert.equal( allDoneCount, 0, ` startQueue incorrect allDoneCount` );\n      };\n\n      assert.equal( cmd4PriorityPollingQueue.queueType, constants.DEFAULT_QUEUE_TYPE, ` incorrect default queue type. Should be WoRm` );\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      //cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n      cmd4PriorityPollingQueue.startQueue( cmd4PriorityPollingQueue, allDoneCallback );\n\n      // Wait for the entry in the Queue to be processed\n      setTimeout( ( ) =>\n      {\n\n         assert.equal( 0, log.logLineCount, ` Unexpected number of stdout lines:  ${ log.logBuf }` );\n         assert.equal( 0, log.errLineCount, ` Unexpected number of stderr lines:  ${ log.errBuf }` );\n         assert.equal( log.errBuf, \"\", ` Unexpected stderr:  ${ log.errBuf }` );\n\n\n\n         // A quick way to stop the queue. For whatever reason, if the above fails,\n         // the testcase will not do this command and the testcase runs forever\n         cmd4SwitchAccessory.queue.inProgressSets = 10;\n\n         done( );\n\n      }, 2500 );\n\n   }).timeout( 3000 );\n\n   it( `Worm Test lowPriority \"Get\" Entry passes without errors`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"./test/echoScripts/echo_true\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false ); // Not to be turned on !!\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n      //cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.On, \"On\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n      //cmd4PriorityPollingQueue.addLowPriorityGetPolledQueueEntry( cmd4SwitchAccessory, CMD4_ACC_TYPE_ENUM.Active, \"Active\", constants.DEFAULT_INTERVAL, constants.DEFAULT_TIMEOUT );\n\n      //assert.equal( cmd4PriorityPollingQueue.lowPriorityQueue.length, 4, `Polled Get added to low prority queue` );\n\n      assert.equal( 0, log.errLineCount, ` Unexpected number of stderr lines:  ${ log.errBuf }` );\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( false ); // Not to be turned on !!\n\n      // Process 1 entry from the polling queue\n      cmd4PriorityPollingQueue.processEntryFromLowPriorityQueue( cmd4PriorityPollingQueue.lowPriorityQueue[ 0 ] );\n\n      setTimeout( () =>\n      {\n         assert.equal( 0, log.logLineCount, ` Unexpected number of stdout lines:  ${ log.logBuf }` );\n         assert.equal( 0, log.errLineCount, ` Unexpected number of stderr lines:  ${ log.errBuf }` );\n         assert.equal( log.errBuf, \"\", ` Unexpected stderr:  ${ log.errBuf }` );\n\n         done( );\n\n      }, 1000);\n\n   }).timeout( 3000 );\n});\n"
  },
  {
    "path": "test/testAdvAirGetSet.js",
    "content": "#!node\n\n\n// Settings, Globals and Constants\nlet settings = require( \"../cmd4Settings\" );\nlet constants = require( \"../cmd4Constants\" );\n\nlet Cmd4Platform = require( \"../Cmd4Platform\" ).Cmd4Platform;\nlet Cmd4PriorityPollingQueue = require( \"../Cmd4PriorityPollingQueue\" ).Cmd4PriorityPollingQueue;\n\n\n// Duplicated from Cmd4PriorityPollingQueue.js\n//let HIGH_PRIORITY_SET = 0;\nlet HIGH_PRIORITY_GET = 1;\n//let LOW_PRIORITY_GET = 2;\n\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_DEVICE_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_DEVICE_TYPE_ENUM.EOL =\" + DEVICE_EOL, ( ) =>\n   {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( \"Quick Test of CMD4_ACC_TYPE_ENUM\", ( ) =>\n{\n   it( \"CMD4_ACC_TYPE_ENUM.EOL =\" + ACC_EOL, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n\n\ndescribe('AdvAir test of Cmd4PriorityPollingQueue polling', ( ) =>\n{\n   before( ( ) =>\n   {\n      sinon.stub( process, `exit` );\n\n      cleanStatesDir();\n   });\n   after( ( ) =>\n   {\n      process.exit.restore( );\n\n   });\n   beforeEach( function( )\n   {\n      settings.listOfCreatedPriorityQueues = { };\n   });\n\n   afterEach( function( )\n   {\n      // Clear any timers created for any polling queue\n      Object.keys(settings.listOfCreatedPriorityQueues).forEach( (queueName) =>\n      {\n         let queue = settings.listOfCreatedPriorityQueues[ queueName ];\n         Object.keys(queue.listOfRunningPolls).forEach( (key) =>\n         {\n            let timer = queue.listOfRunningPolls[ key ];\n            clearTimeout( timer );\n         });\n\n         clearTimeout( queue.pauseTimer );\n      });\n\n      // Put back the polling queues\n      settings.listOfCreatedPriorityQueues = { };\n\n      // MaxListenersExceededWarning: Possible EventEmitter memory leak detected\n      _api.removeAllListeners();\n   });\n\n   it( `AdvAir - Test \"Get\" Cmd From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./test/AdvAir.sh\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: cmd4SwitchAccessory.hV.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Get\" entry: ${ CMD4_ACC_TYPE_ENUM.On } isUpdate: false length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch cmd: node ./test/AdvAir.sh Get \"MySwitch\" 'On' timeout: 60000` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: On function for: MySwitch returned: 1` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `AdvAir - Test \"Get\" Cmd Quotes From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"Mia'sSwitch\",\n            displayName:               \"Mia'sSwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./test/AdvAir.sh\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue getValue will just return the cached value\n      // and call updateValue later\n      var dummyCallback = function( rc, result )\n      {\n         assert.equal( rc, 0, ` getValue incorrect rc: ${ rc }` );\n         assert.equal( result, true, ` getValue incorrect result: ${ result }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: false, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: cmd4SwitchAccessory.hV.timeout, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: null, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Get\" entry: ${ CMD4_ACC_TYPE_ENUM.On } isUpdate: false length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: Mia'sSwitch cmd: node ./test/AdvAir.sh Get \"Mia'sSwitch\" 'On' timeout: 60000` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90mgetValue: On function for: Mia'sSwitch returned: 1` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `AdvAir - Test \"Set\" Cmd From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"MySwitch\",\n            displayName:               \"MySwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./test/AdvAir.sh\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue setValue will just return successful\n      // and do the actual setValue later\n      var dummyCallback = function( rc )\n      {\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: true, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Set\" entry: ${ CMD4_ACC_TYPE_ENUM.On } length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90msetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: MySwitch 1  cmd: node ./test/AdvAir.sh Set \"MySwitch\" 'On' '1'` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n   it( `AdvAir - Test \"Set\" Cmd Quotes From High Priority Queue`, ( done  ) =>\n   {\n      let platformConfig =\n      {\n         queueTypes:                   [ { queue: \"A\", queueType: \"WoRm\" } ],\n         accessories: [\n         {\n            name:                      \"Mia'sSwitch\",\n            displayName:               \"Mia'sSwitch\",\n            statusMsg:                 true,\n            type:                      \"Switch\",\n            on:                        0,\n            active:                    0,\n            queue:                     \"A\",\n            polling:                   [ { characteristic: \"on\" },\n                                         { characteristic: \"active\" } ],\n            state_cmd:                 \"node ./test/AdvAir.sh\"\n         }]\n      };\n\n      let log = new Logger( );\n      log.setBufferEnabled( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n\n      let cmd4Platform = new Cmd4Platform( log, platformConfig, _api );\n\n      expect( cmd4Platform ).to.be.a.instanceOf( Cmd4Platform, \"cmd4Platform is not an instance of Cmd4Platform\" );\n\n      cmd4Platform.discoverDevices( );\n\n      assert.equal( Object.keys(settings.listOfCreatedPriorityQueues).length, 1, `Incorrect number of polling queues created` );\n\n      let queue = settings.listOfCreatedPriorityQueues[ \"A\" ];\n\n      expect( queue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"queue is not an instance of Cmd4PollingQueue\" );\n\n      assert.equal( queue.lowPriorityQueue.length, 2, `Incorrect number of low level polling characteristics` );\n\n\n      let cmd4SwitchAccessory = cmd4Platform.createdCmd4Accessories[0];\n\n      let cmd4PriorityPollingQueue = cmd4SwitchAccessory.queue;\n      expect( cmd4PriorityPollingQueue ).to.be.a.instanceOf( Cmd4PriorityPollingQueue, \"Cmd4PriorityPollingQueue is not an instance of Cmd4Accessory\" );\n\n\n      log.reset( );\n      log.setOutputEnabled( false );\n      log.setDebugEnabled( true );\n\n      // The queue setValue will just return successful\n      // and do the actual setValue later\n      var dummyCallback = function( rc )\n      {\n         assert.equal( rc, 0, ` setValue incorrect rc: ${ rc }` );\n      };\n\n      cmd4PriorityPollingQueue.highPriorityQueue.push( { [ constants.IS_SET_lv ]: true, [ constants.QUEUE_GET_IS_UPDATE_lv ]: false, [ constants.ACCESSORY_lv ]: cmd4SwitchAccessory, [ constants.ACC_TYPE_ENUM_INDEX_lv ]: CMD4_ACC_TYPE_ENUM.On, [ constants.CHARACTERISTIC_STRING_lv ]: \"On\", [ constants.TIMEOUT_lv ]: constants.DEFAULT_TIMEOUT, [ constants.STATE_CHANGE_RESPONSE_TIME_lv ]: null, [ constants.VALUE_lv ]: true, [ constants.CALLBACK_lv ]: dummyCallback } );\n\n      cmd4PriorityPollingQueue.processQueueFunc( HIGH_PRIORITY_GET, cmd4PriorityPollingQueue );\n\n      // Wait for the Queue to be processed\n      setTimeout( ( ) =>\n      {\n         assert.include( log.logBuf, `[90mProcessing high priority queue \"Set\" entry: ${ CMD4_ACC_TYPE_ENUM.On } length: 0` , `expected stdout: ${ log.logBuf }` );\n         assert.include( log.logBuf, `[90msetValue: accTypeEnumIndex:( ${ CMD4_ACC_TYPE_ENUM.On } )-\"On\" function for: Mia'sSwitch 1  cmd: node ./test/AdvAir.sh Set \"Mia'sSwitch\" 'On' '1'` , `expected stdout: ${ log.logBuf }` );\n\n         done( );\n\n      }, 1000 );\n   });\n\n});\n"
  },
  {
    "path": "test/testOurConfig.json.js",
    "content": "'use strict';\n\nvar fs = require('fs'),\nParser = require('jsonparse');\n\n\nvar json = fs.readFileSync(\"Extras/config.json\");\n\n\n\ndescribe( \"Testing our config.json\", ( ) =>\n{\n   it( \"isJSON should be a function\", ( ) =>\n   {\n      assert.isFunction( Parser, \"Parser is not a function\" );\n   });\n\n   it( \"If our config.json is valid\", ( ) =>\n   {\n      JSON.parse(json);\n      var p = new Parser();\n\n      p.onError = function (value) {\n          assert(\"Our config.json is invalid value:\", value);\n      };\n\n      p.write( json );\n\n   });\n})\n"
  },
  {
    "path": "test/transposeCMD4Props.js",
    "content": "'use strict';\n\n// ***************** TEST LOADING **********************\n\nvar { transposeConstantToValidValue,\n      transposeValueToValidConstant,\n      extractKeyValue } = require( \"../utils/transposeCMD4Props\" );\n\n\n// ***************** TEST Plugin Initialized Variables ***************\n\ndescribe( `Initializing our CMD4 Libraries`, ( ) => { } );\n\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n // Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\n// ******** QUICK TEST CMD4_ACC_TYPE_ENUM *************\ndescribe( `Quick Test load of CMD4_ACC_TYPE_ENUM`, ( ) =>\n{\n   it( `CMD4_ACC_TYPE_ENUM.EOL = ${ ACC_EOL }`, ( ) =>\n   {\n     expect( CMD4_ACC_TYPE_ENUM.EOL ).to.equal( ACC_EOL );\n   });\n});\n\n// ******** QUICK TEST CMD4_DEVICE_TYPE_ENUM *************\ndescribe( `Quick Test load of CMD4_DEVICE_TYPE_ENUM`, ( ) =>\n{\n   it( `CMD4_DEVICE_TYPE_ENUM.EOL =${ DEVICE_EOL }`, ( ) =>\n  {\n     expect( CMD4_DEVICE_TYPE_ENUM.EOL ).to.equal( DEVICE_EOL );\n  });\n});\n\n// ******** TEST extractKeyValue.*************\ndescribe( `Testing extractKeyValue`, ( ) =>\n{\n   it( `extractKeyValue should be a function`, ( ) =>\n   {\n      expect( extractKeyValue).to.be.a( \"function\", `extractKeyValue is not a function. found: ${ typeof extractKeyValue }`);\n   });\n\n   it( `extractKeyValue should return correct key`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.CurrentDoorState;\n      let expectedKey = \"CLOSING\";\n      let value = 3;\n      let result = extractKeyValue( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].validValues, value );\n      expect( result ).to.equal( expectedKey, `Test 1 extractKeyValue( ${ value } ) returned:${ result } expected:${ expectedKey }` );\n   });\n\n   it( `extractKeyValue should return undefined for no value`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.CurrentDoorState;\n      let expectedKey = undefined;\n      let value = undefined;\n      let result = extractKeyValue( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].validValues, value );\n      expect( result ).to.equal( expectedKey, `Test 2 extractKeyValue( ${ value } ) returned:${ result  } expected:${  expectedKey }` );\n   });\n\n   it( `extractKeyValue For last index should reterun last key`, ( ) =>\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.CurrentDoorState;\n      let keys = Object.keys( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].validValues );\n      let keyCount = keys.length;\n      let expectedKey =  keys[keyCount -1 ];\n      let value = keyCount -1;\n      let result = extractKeyValue( CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].validValues, value );\n      expect( result ).to.equal( expectedKey, `Test 3 extractKeyValue( ${ value } ) returned:${ result } expected:${ expectedKey }` );\n   });\n\n});\n\ndescribe( `Testing transposeConstantToValidValue`, ( ) =>\n{\n   it( `transposeConstantToValidValue should return originalfor no translation`, ( ) =>\n   {\n      // has {} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AccessControlLevel;\n      let constantToBeChecked = \"DUMMY\";\n      let expectedResult = constantToBeChecked;\n\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, constantToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeConstantToValidValue from ${ constantToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeConstantToValidValue should return correct constant for 0-INACTIVE `, ( ) =>\n   {\n      // has { \"INACTIVE\" & \"ACTIVE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let constantToBeChecked = \"INACTIVE\";\n      let expectedResult = 0;\n\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, constantToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeConstantToValidValue from ${ constantToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeConstantToValidValue should return correct constant for 0-iNACTIVE`, ( ) =>\n   {\n      // has { \"INACTIVE\" & \"ACTIVE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let constantToBeChecked = \"INACTIVE\";\n      let expectedResult = 0;\n\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, constantToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeConstantToValidValue from ${ constantToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeConstantToValidValue should return correct constant for 1-ACTIVE `, ( ) =>\n   {\n      // has { \"INACTIVE\" & \"ACTIVE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let constantToBeChecked = \"ACTIVE\";\n      let expectedResult = 1;\n\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, constantToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeConstantToValidValue from ${ constantToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeConstantToValidValue should return correct value 1 for constant \"TRUE\"`, ( ) =>\n   {\n      // has { \"FALSE\" & \"TRUE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AdministratorOnlyAccess;\n      let constantToBeChecked = \"TRUE\";\n      let expectedResult = 1;\n\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, constantToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeConstantToValidValue from ${ constantToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeConstantToValidValue should return correct value 4 for constant \"INTERUPTED\"`, ( ) =>\n   {\n      // has { \"FALSE\" & \"TRUE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AdministratorOnlyAccess;\n      let constantToBeChecked = \"TRUE\";\n      let expectedResult = 1;\n\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, constantToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeConstantToValidValue from ${ constantToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n});\n\n\ndescribe( `Testing transposeValueToValidConstant`, ( ) =>\n{\n   it( `transposeValueToValidConstant should return original for no translation`, ( ) =>\n   {\n      // has {} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AccessControlLevel;\n      let valueToBeChecked = \"DUMMY\";\n      let expectedResult = valueToBeChecked;\n\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, valueToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeValueToValidConstant from ${ valueToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeValueToValidConstant should return correct constant for 0-INACTIVE`, ( ) =>\n   {\n      // has { \"INACTIVE\" & \"ACTIVE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let valueToBeChecked = 0;\n      let expectedResult = \"INACTIVE\";\n\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, valueToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeValueToValidConstant from ${ valueToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeValueToValidConstant should return correct constant for 1-ACTIVE`, ( ) =>\n   {\n      // has { \"INACTIVE\" & \"ACTIVE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let valueToBeChecked = 1;\n      let expectedResult = \"ACTIVE\";\n\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, valueToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeValueToValidConstant from ${ valueToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n\n   it( `transposeValueToValidConstant should return correct constant for value 1`, ( ) =>\n   {\n      // has { \"FALSE\" & \"TRUE\"} for validValues\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.AdministratorOnlyAccess;\n      let valueToBeChecked = 1;\n      let expectedResult = \"TRUE\";\n\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, valueToBeChecked );\n\n      expect( transposed ).to.equal( expectedResult, `transposeValueToValidConstant from ${ valueToBeChecked } returned ${ transposed } instead of ${ expectedResult } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n   });\n});\n\n\n// TEST all Possible validValues for transposeValueToValidConstant\ndescribe( `Testing all Possible validValues for  transposeValueToValidConstant`, ( ) =>\n{\n   for ( let index = 0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n   // for ( let index = CMD4_ACC_TYPE_ENUM.EOL -1 ; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n   {\n      if ( Array.isArray( CMD4_ACC_TYPE_ENUM.properties[ index ].validValues ))\n      {\n         let numberOfValues =\n            CMD4_ACC_TYPE_ENUM.properties[ index ].values.length;\n         for ( let vindex = 0; vindex < numberOfValues; vindex ++ )\n         {\n            // testTransposeValueTo( CMD4_ACC_TYPE_ENUM.properties, index,\n            //    CMD4_ACC_TYPE_ENUM.properties[ index ].validValues[ vindex ], true );\n            testTransposeValueTo( CMD4_ACC_TYPE_ENUM.properties, index, vindex, true );\n         }\n      } else {\n\n         //testTransposeValueTo( CMD4_ACC_TYPE_ENUM.properties, index,\n         //      CMD4_ACC_TYPE_ENUM.properties[ index ].validValues, true );\n         testTransposeValueTo( CMD4_ACC_TYPE_ENUM.properties, index, index, true );\n      }\n   }\n\n   // Test a failing one\n   //testTransposeValueTo( CMD4_ACC_TYPE_ENUM.properties, 0, {\"one\": \"1\", \"two\": \"2\"}, false );\n   testTransposeValueTo( CMD4_ACC_TYPE_ENUM.properties, 0, 7, false );\n});\n\n// TEST all Possible transposeConstantToValidValue\ndescribe( `Testing all Possible transposeConstantToValidValue`, ( ) =>\n{\n   for ( let index =0 ; index < CMD4_ACC_TYPE_ENUM.EOL; index ++ )\n   {\n      if ( Array.isArray( CMD4_ACC_TYPE_ENUM.properties[ index ].validValues ))\n      {\n         let numberOfValues =\n            CMD4_ACC_TYPE_ENUM.properties[ index ].validValues.length;\n         for ( let vindex = 0; vindex < numberOfValues; vindex ++ )\n         {\n            //testTransposeConstantTo( CMD4_ACC_TYPE_ENUM.properties, index,\n            //   CMD4_ACC_TYPE_ENUM.properties[ index ].validValues[ vindex ], true );\n            testTransposeConstantTo( CMD4_ACC_TYPE_ENUM.properties, index, vindex, true );\n         }\n      } else {\n\n         //testTransposeConstantTo( CMD4_ACC_TYPE_ENUM.properties, index,\n         //      CMD4_ACC_TYPE_ENUM.properties[ index ].validValues, true );\n         testTransposeConstantTo( CMD4_ACC_TYPE_ENUM.properties, index, index, true );\n      }\n   }\n\n   // Test a failing one\n   //testTransposeConstantTo( CMD4_ACC_TYPE_ENUM.properties, 0, {\"one\": \"1\", \"two\": \"2\"}, false );\n   testTransposeConstantTo( CMD4_ACC_TYPE_ENUM.properties, 0, 7, false );\n\n   // Test constantToValidValue CELSIUS (Correctly spelled )\n   it( `transposeConstantToValidValue for correctly spelled \"CELSIUS\" should return expected value`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, \"CELSIUS\");\n      expect( transposed ).to.equal( _api.hap.Characteristic.TemperatureDisplayUnits.CELSIUS, `transposeConstantTo from CELSIUS returned incorrect value`  );\n   });\n   // Test constantToValidValue mispelled CELSIUS - CELcIUS\n   it( `transposeConstantToValidValue for incorrectly spelled \"CELciUS\" should fail`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let badInput = \"CELcIUS\";\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, badInput );\n      expect( transposed ).to.equal( badInput, `transposeConstantTo from ${ badInput } returned incorrect value` );\n   });\n\n   it( `transposeConstantToValidValue for: \"FAHRENHEIT\" should return expected value`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, \"FAHRENHEIT\");\n      expect( transposed ).to.equal( _api.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT, `transposeConstantTo from \"FAHRENHEIT\" returned incorrect value`  );\n   });\n\n   it( `transposeValueToValidConstant for: 1 should return expected \"FAHRENHEIT\"`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, _api.hap.Characteristic.TemperatureDisplayUnits.FAHRENHEIT);\n      expect( transposed ).to.equal( \"FAHRENHEIT\", `transposeValueTo from 1 returned incorrect constant` );\n   });\n\n   it( `transposeValueToValidConstant for: 3 should fail as expected`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let badInput = 3;\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, badInput);\n      expect( transposed ).to.equal( badInput, `transposeValueTo from ${ badInput } returned incorrect value` );\n   });\n\n   it( `transposeValueToValidConstant SENDING \"FAHRENHEIT\", should return \"FAHRENHEIT\" and say already transposed`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, \"FAHRENHEIT\");\n      expect( transposed ).to.equal( \"FAHRENHEIT\", `transposeValueTo from 1 returned incorrect constant` );\n   });\n\n   it( `transposeConstantToValidValue SENDING \"1\", should return \"1\" (FAHRENHEIT) and say already transposed`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.TemperatureDisplayUnits;\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, 1);\n      expect( transposed ).to.equal( 1, `transposeConstantTo from 1 returned incorrect value` );\n   });\n\n   it( `transposeConstantToValidValue To characteristic with no valid values should fail approperiately.`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.ActiveIdentifier;\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, 1);\n      expect( transposed ).to.equal( 1, `transposeConstantTo from 1 returned incorrect value` );\n   });\n\n   it( `transposeValueToValidConstant To characteristic with no valid values should fail approperiately.`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.ActiveIdentifier;\n      let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, \"BLAST\");\n      expect( transposed ).to.equal( \"BLAST\", `transposeValueTo from \"BLAST\" returned incorrect value` );\n   });\n\n   it( `transposeConstantToValidValue for: \"1\" should pass as expected`, ( ) =>\n   {\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, \"1\");\n      expect( transposed ).to.equal( \"1\", `transposeValueTo from \"1\" returned incorrect value` );\n   });\n\n   it( `transposeConstantToValidValue for: \"ENABLED\" should fail as expected`, ( ) =>\n   {\n      // Active allows \"ACTIVE\" and \"INACTIVE\", not \"ENABLED\"\n      let  accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.Active;\n      let data = \"ENABLED\"\n      let transposed = transposeConstantToValidValue( CMD4_ACC_TYPE_ENUM.properties, accTypeEnumIndex, data);\n      expect( transposed ).to.equal( data, `transposeValueTo from \"${ data } \" returned incorrect value: ${ transposed }` );\n   });\n});\n\n\n\n\n// ***************** Common way of testing functions above **********************\n\n\nfunction testTransposeConstantTo( CMD4_ENUM_properties_obj, accTypeEnumIndex, vindex, shouldPass )\n{\n   // if ( ! obj )\n   if ( ! CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues )\n   {\n      // Nothing to do\n      return;\n   }\n   //let numberOfKeyValuePairs = Object.keys( obj );\n   let numberOfKeyValuePairs = Object.keys( CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues );\n\n   if ( numberOfKeyValuePairs < 0 )\n   {\n      // Nothing to do\n      return;\n   }\n\n   //for ( let key in obj )\n   for ( let key in CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues )\n   {\n      let valueThatShouldBeReturned = CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues[ key ];\n\n      let transposed = transposeConstantToValidValue( CMD4_ENUM_properties_obj, accTypeEnumIndex, key);\n\n      it( `transposeConstantToValidValue for: ${ CMD4_ENUM_properties_obj[accTypeEnumIndex].type } should return expected value: ${ transposed } for key: ${ key }`, ( ) =>\n      {\n         if ( shouldPass )\n         {\n            expect( valueThatShouldBeReturned ).to.equal( transposed, `transposeConstantTo from ${ key } returned ${ transposed } instead of ${ valueThatShouldBeReturned } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n         } else\n         {\n            expect( valueThatShouldBeReturned ).to.not.equal( transposed, `transposeConstantTo from ${ key } returned ${ transposed } instead of ${ valueThatShouldBeReturned } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n         }\n      });\n\n   }\n}\n\nfunction testTransposeValueTo( CMD4_ENUM_properties_obj, accTypeEnumIndex, vindex, shouldPass )\n{\n   //let numberOfKeyValuePairs = Object.keys( obj );\n   let numberOfKeyValuePairs = Object.keys( CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues );\n\n   if ( numberOfKeyValuePairs < 0 )\n   {\n      // Nothing to do\n      return;\n   }\n\n   // for ( let key in obj )\n   for ( let key in CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues )\n   {\n      //let constantToBeChecked = obj[ key ];\n      let constantToBeChecked = CMD4_ENUM_properties_obj[accTypeEnumIndex].validValues[ key ];\n\n      let transposed = transposeValueToValidConstant( CMD4_ENUM_properties_obj, accTypeEnumIndex, constantToBeChecked );\n\n      //it( `transposeValueToValidConstant should return expected constant`, ( ) =>\n      it( `transposeValueToValidConstant should return expected constant: ${ constantToBeChecked } for key: ${ key }`, ( ) =>\n      {\n         if ( shouldPass )\n         {\n            expect( key ).to.equal( transposed, `transposeValueTo from ${ constantToBeChecked } returned ${ transposed } instead of ${ key } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n         } else\n         {\n            expect( key ).to.not.equal( transposed, `transposeValueTo from ${ constantToBeChecked } returned ${ transposed } instead of ${ key } for ${ CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type }` );\n         }\n      });\n   }\n}\n"
  },
  {
    "path": "test/trueTypeOf.js",
    "content": "'use strict';\n\nvar trueTypeOf = require( \"../utils/trueTypeOf.js\" );\n\ndescribe( \"Testing trueTypeOf\", ( ) =>\n{\n   it( \"trueTypeOf should be a function\", ( ) =>\n   {\n      assert.isFunction( trueTypeOf, \"trueTypeOf is not a function\" );\n   });\n\n   it( \"trueTypeOf should correctly identify a String object\", ( ) =>\n   {\n      let data = \"Cmd4\";\n      let expectedResult = String;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a Boolean false object\", ( ) =>\n   {\n      let data = false;\n      let expectedResult = Boolean;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a Boolean true object\", ( ) =>\n   {\n      let data = true;\n      let expectedResult = Boolean;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a Number object\", ( ) =>\n   {\n      let data = 42;\n      let expectedResult = Number;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a Array object\", ( ) =>\n   {\n      let data = [ 1, 2, 3 ];\n      let expectedResult = Array;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a polling config\", ( ) =>\n   {\n      let data = [ { \"characteristic\": \"active\", \"timeout\": 5, \"interval\": 3},\n                   { \"characteristic\": \"On\", \"timeout\": 8, \"interval\": 4}\n                 ];\n      let expectedResult = Array;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify an empty object \", ( ) =>\n   {\n      let data = undefined\n      let expectedResult = undefined;\n      let result = trueTypeOf( );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a undefined object \", ( ) =>\n   {\n      let data = undefined\n      let expectedResult = undefined;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a null object\", ( ) =>\n   {\n      let data = null;\n      let expectedResult = null;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a 0 as a Number\", ( ) =>\n   {\n      let data = 0;\n      let expectedResult = Number;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a \\\"0\\\" as a String\", ( ) =>\n   {\n      let data = \"0\";\n      let expectedResult = String;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n\n   it( \"trueTypeOf should correctly identify a \\\"1\\\" as a String\", ( ) =>\n   {\n      let data = \"0\";\n      let expectedResult = String;\n      let result = trueTypeOf( data );\n      assert.equal( result, expectedResult, \"trueTypeOf( \" + data + \" ) returned: \" + result  + \" expected: \" +  expectedResult );\n   });\n})\n\n"
  },
  {
    "path": "test/versionChecker.js",
    "content": "'use strict';\n\nconst { isUpgrade, getLatestVersion, isVersionNewerThanPackagedVersion, getPackagedVersion } = require( \"../utils/versionChecker\" );\n\ndescribe( `Testing versionChecker init`, ( ) =>\n{\n   it( `isUpgrade should be a function`, ( ) =>\n   {\n      assert.isFunction( isUpgrade, `isUpgrade is not a function` );\n   });\n\n   it( `getLatestVersion should be a function`, ( ) =>\n   {\n      assert.isFunction( getLatestVersion, `getLatestVersion is not a function` );\n   });\n\n   it( `isVersionNewerThanPackagedVersion should be a function`, ( ) =>\n   {\n      assert.isFunction( isVersionNewerThanPackagedVersion, `isVersionNewerThanPackagedVersion is not a function` );\n   });\n\n   it( `getPackagedVersion should be a function`, ( ) =>\n   {\n      assert.isFunction( getPackagedVersion, `getPackagedVersion is not a function` );\n   });\n});\n\n\ndescribe( `Testing versionChecker functionality`, ( ) =>\n{\n   it( `getPackagedVersion should return an string`, ( ) =>\n   {\n      let result = getPackagedVersion( );\n      assert.isString( result, `getPackagedVersion failed: ${ typeof result }` );\n   });\n\n   it( `getLatestVersion should return an string`, async ( ) =>\n   {\n      let result = await getLatestVersion( );\n      assert.isString( result, `getLatestVersion failed: ${ typeof result }` );\n   }).timeout(5000);\n\n   it( `isVersionNewerThanPackagedVersion should return true for a high version`, ( ) =>\n   {\n      let result = isVersionNewerThanPackagedVersion( \"9.0.0\" );\n      assert.isTrue( result, `isVersionNewerThanPackagedVersion expected: true: found: ${ result }` );\n   });\n   it( `isVersionNewerThanPackagedVersion should return false for a lower version`, ( ) =>\n   {\n      let result = isVersionNewerThanPackagedVersion( \"1.0.0\" );\n      assert.isFalse( result, `isVersionNewerThanPackagedVersion expected: false: found: ${ result }` );\n   });\n\n   it( `isVersionNewerThanPackagedVersion should return false for same version`, async ( ) =>\n   {\n      let latest = await getLatestVersion( );\n      let result = isVersionNewerThanPackagedVersion( latest );\n      assert.isFalse( result, `isVersionNewerThanPackagedVersion expected: false: found: ${ result }` );\n   }).timeout(5000);\n\n})\n\n"
  },
  {
    "path": "tools/Cmd4AccDocGenerator",
    "content": "#!/usr/bin/env node\n\n// Note:\n// Must read https://docs.github.com/en/rest/reference/markdown#render-an-arbitrary-markdown-document\n// https://gist.github.com\n//\n// Good Learning sites:\n// https://www.w3schools.com/jquery/jquery_get_started.asp\n// https://www.w3schools.com/howto/howto_css_sidebar_icons.asp\n//\n// Node.js Manuals & Documentation\n// https://nodejs.org/docs/v0.4.0/api/all.html\n\n//            * Cmd4 Body Layout *\n//            ====================\n//\n//    =====================================\n//   | class=\"header fixed-top\"\n//   |  __________________________________\n//   | | class=\"container-fluid\"\n//   | |  _______________________________\n//   | | | class=\"site-logo\"\n//   | | |_______________________________\n//   | | | Search - tba\n//   | | |_______________________________\n//   | |__________________________________\n//   |\n//   |=====================================\n//   | class=\"content\"\n//   |  _________________________________\n//   | | class=\"sidenav\"\n//   | |  - device links\n//   | |  - characteristic links\n//   | |  - cmd4Directive links\n//   | |   .\n//   | |   .\n//   | |   .\n//   | |_________________________________\n//   | | class=\"main\"\n//   | | - class=\"section\" - device pages\n//   | | - class=\"section\" - characteristic pages\n//   | | - class=\"section\" - directive pages\n//   | |   .\n//   | |   .\n//   | |   .\n//   | |_________________________________\n//   |=====================================\n//   | Javascript\n//    =====================================\n\n\n\n//                * HTML Layout *\n//                ===============\n//    _______________________________________\n//   |                 Margin                |\n//   |   _________________________________   |\n//   |  |              Border             |  |\n//   |  |   ___________________________   |  |\n//   |  |  |           Padding         |  |  |\n//   |  |  |   _____________________   |  |  |\n//   |  |  |  |                     |  |  |  |\n//   |  |  |  |        Content      |  |  |  |\n//   |  |  |  |_____________________|  |  |  |\n//   |  |  |                           |  |  |\n//   |  |  |___________________________|  |  |\n//   |  |                                 |  |\n//   |  |_________________________________|  |\n//   |                                       |\n//   |_______________________________________|\n\n\n\nconst which = require('which');\nconst path = require( \"path\" );\n\nconst settings = require( \"../cmd4Settings\" );\n\n// Get the real path of homebridge instead of a dev dependancy,\n// which caused issues if you forget to update dependancies but\n// upgrade homebridge.\nconst homebridgePath = which.sync( 'homebridge', { nothrow: true } )\n\nlet apiPath;\nlet HomebridgeAPI;\nif ( homebridgePath )\n{\n   let dirname = path.dirname( homebridgePath );\n\n   console.log( \"Found homebridge in path %s\", dirname );\n   apiPath = `${ dirname }/../lib/node_modules/homebridge/lib/api`;\n   HomebridgeAPI = require( apiPath ).HomebridgeAPI;\n\n   if ( ! HomebridgeAPI )\n   {\n      console.log( \"homebridgeAPI not available !!!\" );\n      process.exit( 10 );\n   }\n\n} else\n{\n   console.log( \"homebridge not found !!!\" );\n   process.exit( 10 );\n}\nconsole.log( \"Found api in %s\", apiPath );\n\n\n\n// Cmd4 Constants and Settings\nconst constants = require( \"../cmd4Constants\" );\n//const settings = require( \"../cmd4Settings\" );\n\n// For changing validValue Constants to Values and back again\nvar { transposeValueToValidConstant } = require( \"../utils/transposeCMD4Props\" );\n\n// Required to initialize CMD4 Accessory & Device lookup tables.\nlet _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n// These would be the uninitialized values.\nlet ACC_DATA = require('../lib/CMD4_ACC_TYPE_ENUM');\nlet DEVICE_DATA = require('../lib/CMD4_DEVICE_TYPE_ENUM');\n\n// Init the library for all to use\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic, _api.hap.Formats, _api.hap.Units, _api.hap.Perms );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\nlet Characteristic = _api.hap.Characteristic;\n\n// File System utilities\nlet fs = require( \"fs\" );\n\nlet CMD4_DOC_FILE_PATH = \"./docs/\";\nlet AUTO_GENERATED_SUB_PATH = \"autoGenerated/\";\nlet CMD4_ACC_DOC_FILE = \"CMD4_AccessoryDescriptions.html\";\n\n// Scripts we embed\nlet CMD4_SCRIPTS = [\n   { \"file\": \"ExampleJavaScript_template.js\",\n     \"filePath\": \"./Extras/Cmd4Scripts/Examples/\",\n     \"link\": \"JS Template\",\n     \"description\": \"Example Cmd4 JavaScript Template\"\n   },\n   { \"file\": \"ExampleShellScript_template.sh\",\n     \"filePath\": \"./Extras/Cmd4Scripts/Examples/\",\n     \"link\": \"Bash Template\",\n     \"description\": \"Example Cmd4 Shell Script Template\"\n   }\n];\n\n// The fid of the document.\nvar fid;\n\nvar divLevel=0;\nconst INDENT = 3;\n\n// Since v6.2 the Accessory characteristics are not sorted. This\n// is because peoples saved status per characteristic is done by index.\n// changing this would mean the values would be mixed up.\nfunction sortACCByType( )\n{\n   var keysAndIndexes = [];\n   var sorted_obj = { properties: [],\n                      indexOfEnum: CMD4_ACC_TYPE_ENUM.indexOfEnum,\n                      EOL: CMD4_ACC_TYPE_ENUM.EOL\n                    };\n   let characteristicNames = [];\n   let characteristicName = \"\";\n\n   for ( let accTypeEnumIndex = 0 ; accTypeEnumIndex < CMD4_ACC_TYPE_ENUM.EOL; accTypeEnumIndex++ )\n   {\n      // Set the old characteristic name and value\n      characteristicName = Object.keys(CMD4_ACC_TYPE_ENUM).find(key => CMD4_ACC_TYPE_ENUM[key] === accTypeEnumIndex );\n      characteristicNames.push( characteristicName );\n\n      keysAndIndexes.push( { \"key\": CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].type, \"index\": accTypeEnumIndex }  );\n   }\n\n   // sort the keys ( types )\n   keysAndIndexes.sort( function(a, b)\n   {\n      //return a.key < b.key;\n      if  (a.key < b.key) return -1\n      return a.key > b.key ? 1:0\n   });\n\n   // create new array based on Sorted Keys\n   for ( let index = 0 ; index < keysAndIndexes.length; index++ )\n   {\n      let pair = keysAndIndexes[ index ];\n      let oldIndex = pair.index;\n      sorted_obj.properties[index] = CMD4_ACC_TYPE_ENUM.properties[oldIndex];\n\n      characteristicName = pair.key;\n      // This would be the new index\n      sorted_obj[ characteristicName ] = index;\n   }\n\n   return sorted_obj;\n}\n\n// Since v6.2 the Device names are not sorted. This\n// is because I'm lazy to change any documentation referencing an index\nfunction sortDevByDeviceName( )\n{\n   var keysAndIndexes = [];\n   var sorted_obj = { properties: [],\n                      indexOfEnum: CMD4_DEVICE_TYPE_ENUM.indexOfEnum,\n                      EOL: CMD4_DEVICE_TYPE_ENUM.EOL\n                    };\n\n   let deviceNames = [];\n   let deviceName = \"\";\n\n   for ( let devTypeEnumIndex = 0 ; devTypeEnumIndex < CMD4_DEVICE_TYPE_ENUM.EOL; devTypeEnumIndex++ )\n   {\n      // Set the old device name and value\n      deviceName = Object.keys(CMD4_DEVICE_TYPE_ENUM).find(key => CMD4_DEVICE_TYPE_ENUM[key] === devTypeEnumIndex );\n      deviceNames.push( deviceName );\n\n      keysAndIndexes.push( { \"key\": CMD4_DEVICE_TYPE_ENUM.properties[ devTypeEnumIndex ].deviceName, \"index\": devTypeEnumIndex }  );\n   }\n\n   // sort the keys ( deviceName )\n   keysAndIndexes.sort( function(a, b)\n   {\n      //return a.key < b.key;\n      if  (a.key < b.key) return -1\n      return a.key > b.key ? 1:0\n   });\n\n   // create new array based on Sorted Keys\n   for ( let index = 0 ; index < keysAndIndexes.length; index++ )\n   {\n      let pair = keysAndIndexes[ index ];\n      let oldIndex = pair.index;\n      sorted_obj.properties[index] = CMD4_DEVICE_TYPE_ENUM.properties[oldIndex];\n\n      deviceName = pair.key;\n      // This would be the new index\n      sorted_obj[ deviceName ] = index;\n   }\n\n   return sorted_obj;\n}\n\nlet CMD4_Sorted_ACC = sortACCByType( );\nlet CMD4_Sorted_DEV = sortDevByDeviceName( );\n\n\nfunction createHTMLCmd4AccDocument( )\n{\n   let file = CMD4_DOC_FILE_PATH +\n              AUTO_GENERATED_SUB_PATH +\n              CMD4_ACC_DOC_FILE;\n\n   // Open the document for writing\n   fid = fs.createWriteStream( file,\n          { flags: \"w\" // Open for write\n        });\n\n   fid.on(\"error\", ( ) =>\n   {\n      console.log(`error fs.creatingWriteStream: ${ file }` );\n      process.exit( 666 );\n   });\n\n   startHTML_AndHead( );\n\n   addSytlesAndLeftSideNav_WithinHead ( );\n   endHead( );\n\n   addBody( );\n\n   wfs( `</HTML>\\n` );\n\n   fid.close( );\n\n}\n\nfunction startHTML_AndHead ()\n{\n   wfs(\n`<!DOCTYPE HTML>\n<HTML LANG=\"en\">\n<HEAD>\n<META CHARSET=\"utf-8\">\n<META NAME=\"viewport\" CONTENT=\"width=device-width, initial-scale=1\">\n<!-- Needed for unicode fa-caret-down -->\n<link rel=\"stylesheet\" href=\"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css\">\n<META NAME=\"robots\" CONTENT=\"index,follow\">\n<META NAME=\"Description\" CONTENT=\"CMD4 Characteristics.\">\n<META PROPERTY=\"og:url\" CONTENT=\"https://github.com/ztalbot2000/homebridge-cmd4/docs/${ AUTO_GENERATED_SUB_PATH }${ CMD4_ACC_DOC_FILE }\">\n\n<TITLE>CMD4 Devices</TITLE>\\n` );\n\n}\n\nfunction addSytlesAndLeftSideNav_WithinHead( )\n{\n   wfs(\n`<META NAME=\"viewport\" CONTENT=\"width=device-width, initial-scale=1\">\n<STYLE>\n\n/* Fallback styling */\nBODY {\n   font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;\n   font-size: 1rem;\n   font-weight: 400;\n   line-height: 1.5;\n   color: #252930;          /* blackish */\n   text-align: left;\n   background-color: white;\n}\n\n/* Common styling used inline */\n.fixed-bottom, .fixed-top {\n   POSITION: fixed;\n   LEFT: 0;\n   z-index: 1030;\n   background-color: white;\n}\n.fixed-top {\n   TOP: 0;\n}\n.position-relative {\n   position: relative;\n}\n.float-left {\n   float: left;\n}\n.flex {\n   display: flex;\n}\n.align-items-center {\n   align-items: center;\n}\n\n\n.header {\n   /* The header div goes all across the top */\n   WIDTH: 100%;\n   box-shadow: 0 1px 4px 0 rgba(0,0,0,.1);\n}\n\n/* This houses the Logo */\n.container-fluid {\n   width: 100%;\n   padding-right:15px;\n   padding-left:15px;\n   margin-right:auto;\n   margin-left:auto;\n}\n\n\n.site-logo {\n  box-shadow: 0 1px 4px 0 rgba(0,0,0,.1);\n  BACKGROUND: white;\n  display: inline-block;\n}\n.site-text {\n  BACKGROUND: white;\n  position: relative;\n  display: inline-block;\n  transform: translate( 0, 25% );\n}\n\n.nav-link:before {\n   background-color: #fbf5ff;\n   content: \" \";\n   display: inline-block;\n   height: inherit;\n   left: 0;\n   margin-top: -.5rem;\n   position: absolute;\n   width: 3px;\n   height: 100%;\n   border-radius: 1rem;\n}\n\n/* Fixed sidenav */\n.sidenav\n{\n  WIDTH: 130px;\n  POSITION: fixed;\n  Z-INDEX: 1;\n  MARGIN-LEFT: 10px;\n  /* Must be below Logo */\n  MARGIN-TOP: 50px;\n  BACKGROUND: #eee;\n  OVERFLOW-X: hidden;\n  OVERFLOW-Y: auto;\n  max-height: calc( 100vh - 9rem);\n}\n\n/* Style the sidenav links and the dropdown button */\n.sidenav a, .dropdown-btn, .accordion {\n  PADDING: 6px 8px 6px 16px;  /* Top, Right, Bottom,Left */\n  TEXT-DECORATION: none;\n  FONT: 10.5px Poppins;\n  COLOR: #4b5465;           /* Blueish Gray */\n  DISPLAY: block;\n  -webkit-text-stroke: #4b546;\n  TEXT-ALIGN: left;\n  CURSOR: pointer;\n  OUTLINE: none;\n  BACKGROUND: none;\n  /* Border around button */\n  BORDER: none;\n}\n\n/* On mouse-over */\n.sidenav a:hover, .dropdown-btn: hover, .accordion: hover\n{\n  COLOR: #064579;   /* darker blue */\n}\n\n.accordion\n{\n  transition: 0.4s;\n}\n\n/* accordion type divs */\n.panel {\n  padding: 0 0px;\n  display: none;\n  background-color: white;\n  overflow: hidden;\n}\n\n.main {\n  MARGIN-LEFT: 148px; /* Same width as the sidebar + left position in px */\n  PADDING: 55px 10px; /* Top, Right, Bottom, Left */\n}\n\n/* Div within main, holding page information */\n/* This is also used to hide all the sections at startup */\n.section {\n  display: none; /* initially hidden */\n}\n\n/* Common paragraph sytling */\nh1 {\n   FONT-SIZE: 2.5rem;\n   padding-top: 4rem;\n}\nh2 {\n   FONT-SIZE: 1.5rem;\n}\nh1, h2, h3, h4, h5 {\n  COLOR: #252930;\n  FONT-WEIGHT: 600;\n}\nh1, h2, h3, h4, h5, note, p {\n   FONT-FAMILY: Poppins,sans-serif;\n   MARGIN-TOP: 0;\n   MARGIN-BOTTOM: .5rem;\n   font-weight: 500;\n   line-height: 1.2;\n}\nnote {\n   FONT-STYLE: italic;\n   FONT-SIZE: 1rem;\n   COLOR: #5d6778;   /* blue-ish gray */\n   PADDING: 2rem;\n}\n\n\n/* Table styling */\ntable {\n   display: table;\n   border-collapse: collapse;\n   -webkit-border-horizontal-spacing: 2px;\n   -webkit-border-vertical-spacing: 2px;\n   width: 100%;\n   margin-bottom: 1rem;\n}\nth {\n   FONT-WEIGHT: bold;\n   border: 1px solid #e7e9ed;\n   text-align: center;\n}\ntd {\n   padding: .75rem;\n   vertical-align: top;\n   border-top: 1px solid #e7e9ed;\n   FONT-WEIGHT: normal;\n}\ntr:nth-child(even) { background-color: #f2f2f2 }  /* off white */\n\nblock-warning a {\n   color: #d09c13;     /* Orange-ish */\n}\n\n/* Add an active class to the active dropdown button */\n.active, .accordion: hover {\n\n  /* The background color of the active buttons */\n  background-color: #ccc;   /* light gray */\n\n  /* The width of item is the width of the div */\n  /* Otherwise buttons appear half blocked */\n  width: 100%;\n}\n\n/* Optional: Style the caret down icon */\n.fa-caret-down {\n  float: right;\n}\n\n/* Apply box-sizing to everything */\n* {\n   box-sizing: border-box;\n}\n\n/* Some media queries for responsiveness */\n@media screen and (max-height: 450px) {\n  .sidenav {PADDING-TOP: 15px;}\n  .sidenav a {FONT-SIZE: 12px;}  /* height of items in accordion dropdown */\n}\n</STYLE>\\n` );\n\n}\nfunction endHead( )\n{\n   wfs( `</HEAD>\\n` );\n}\n\nfunction addBody ()\n{\n   wfs( `<BODY>\\n` );\n\n   addFixedHeader_WithinBody();\n\n   addContentDiv_WithinBody( );\n\n   addAccordionScript_WithinEndOfBody();\n\n   addDropDownScript_WithinEndOfBody();\n\n   addToggleVisibilityScript_WithinEndOfBody( );\n\n   wfs( `</BODY>\\n` );\n}\n\nfunction addFluidHeader_WithinFixedHeader()\n{\n   wf( \"+\", `<div class=\"container-fluid position-relative\">\\n` );\n\n      addLogoDiv_WithinFluidHeader( );\n\n   endDiv( \"container-fluid\" );\n}\nfunction addFixedHeader_WithinBody()\n{\n   wf( \"+\", `<HEADER class=\"header fixed-top\">\\n` );\n\n      addFluidHeader_WithinFixedHeader();\n\n   wf( \"-\", `</HEADER>\\n` );\n}\n\n\nfunction addContentDiv_WithinBody( )\n{\n   wf( \"+\", `<div class=\"content\">\\n` );\n\n      addSideNav_WithinContentDiv( )\n\n      addIntroductionPage_WithinContentDiv( )\n\n      addMain_withinContentDiv( );\n\n   endDiv( \"content\" );\n\n}\nfunction addMain_withinContentDiv( )\n{\n   wf( \"+\", `<div class=\"main\">\\n` );\n\n      addDevicePages_WithinMain( )\n\n      addCharacteristicPages_WithinMain( );\n\n      addCmd4DirectivePages_WithinMain( );\n\n      addCmd4AccessoryDirectivePages_WithinMain( );\n\n      addCustomCharacteristicPages_withinMain( );\n\n      addScriptTemplatePages_WithinMain( );\n\n   endDiv( \"main\" );\n}\n\n\nfunction addLogoDiv_WithinFluidHeader( )\n{\n   wf( \"+\", `<div class=\"site-logo\">\\n` );\n\n      wfs( `<img class=\"float-left\" src=\"assets/images/Cmd4_icon.svg\" width=\"40px\" alt=\"logo\">\\n` );\n\n      wf( \"+\", `<div class=\"site-text\">\\n` );\n        wfs(`Cmd4\\n`);\n      endDiv( \"site-text\" );\n\n   endDiv( \"site-logo\" );\n}\n\n// For this to work, it must be at the end of the Body\nfunction addAccordionScript_WithinEndOfBody( )\n{\n   wf( \"+\", `<script>\\n` );\n   wfs(\n`var acc = document.getElementsByClassName(\"accordion\");\nvar i;\n\nfor (i = 0; i < acc.length; i++) {\n  acc[i].addEventListener(\"click\", function() {\n    this.classList.toggle(\"active\");\n    var panel = this.nextElementSibling;\n    if (panel.style.display === \"block\") {\n      panel.style.display = \"none\";\n    } else {\n      panel.style.display = \"block\";\n    }\n  });\n}\n` );\n   wf( \"-\", `</script>\\n` );\n}\n\n// For this to work, it must be at the end of the Body\nfunction addToggleVisibilityScript_WithinEndOfBody( )\n{\n   wf( \"+\", `<script type=\"text/javascript\">\\n` );\n   wfs(\n`\nfunction toggleVisibility( id )\n{\n   var e = document.getElementById( id );\n   /* Hide the last one off */\n   if ( window.lastToggledE !== undefined )\n   {\n      window.lastToggledE.style.display = \"none\";\n   }\n\n   /* Show the new one on */\n   if ( e.style.display = \"none\" )\n   {\n      e.style.display = \"block\";\n   }\n\n   /* Set the last one to this one */\n   window.lastToggledE = e;\n}\n` );\n   wf( \"-\", `</script>\\n` );\n}\n\n// For this to work, it must be at the end of the Body\nfunction addDropDownScript_WithinEndOfBody( )\n{\n   wf( \"+\", `<script>\\n` );\n   wfs( `\n// Loop through all dropdown buttons to toggle between hiding and\n// showing its dropdown content - This allows the user to have\n// multiple dropdowns without any conflict\n\nvar dropdown = document.getElementsByClassName(\"dropdown-btn\");\n\nfor (let i = 0; i < dropdown.length; i++)\n{\n  dropdown[i].addEventListener(\"click\", function()\n  {\n     this.classList.toggle(\"active\");\n     var dropdownContent = this.nextElementSibling;\n     if (dropdownContent.style.display === \"block\")\n     {\n        dropdownContent.style.display = \"none\";\n     } else {\n        dropdownContent.style.display = \"block\";\n     }\n  });\n}\\n` );\n\n   wf( \"-\", `</script>\\n` );\n\n}\n\nfunction addSideNav_WithinContentDiv( )\n{\n   wf( \"+\", `<div class=\"sidenav\">\\n` );\n\n      addSideNavIntroductionLinks_WithinSideNav ();\n\n      addSideNavDevicesLinks_WithinSideNav( );\n\n      addSideNavCharacteristicsLinks_WithinSideNav( );\n\n      addSideNavCmd4DirectivesLinks_WithinSideNav( );\n\n      addSideNavCmd4AccessoryDirectivesLinks_WithinSideNav( );\n\n      addSideNavCustomCharacteristicsLinks_WithinSideNav( );\n\n      addSideNavScriptTemplateLinks_WithinSideNav( );\n\n      wfs( `<a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/Developers.md>Developers Guide</a>\\n` );\n\n      wfs( `<a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/docs/AdvancedTroubleShooting.md>Advanced TroubleShooting</a>\\n` );\n\n   endDiv( \"sidenav\" );\n}\nfunction addSideNavDevicesLinks_WithinSideNav( )\n{\n\n   // Accordion button for Devices\n   wf( \"+\", `<button class=\"accordion\">Devices\\n` );\n      wfs( `<i class=\"fa fa-caret-down\"></i>\\n` );\n   wf( \"-\", `</button>\\n` );\n\n\n   wf( \"+\", `<div class=\"panel\">\\n` );\n\n      for ( let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_Sorted_DEV.properties[ index ].deprecated == true)\n            continue;\n\n         // We just need the index to look sorted\n         let deviceName = CMD4_Sorted_DEV.properties[ index ].deviceName;\n\n         wfs( `<a href=\"#${ deviceName }\" onclick=\"toggleVisibility( '${ deviceName }');\">${ deviceName }</a>\\n` );\n      }\n\n   endDiv( \"panel\" );\n}\nfunction addSideNavIntroductionLinks_WithinSideNav ()\n{\n}\n\nfunction addSideNavCharacteristicsLinks_WithinSideNav( )\n{\n   // Accordion button for Characteristics\n   wf( \"+\", `<button class=\"accordion\">Characteristics\\n` );\n      wfs( `<i class=\"fa fa-caret-down\"></i>\\n` );\n   wf( \"-\", `</button>\\n` );\n\n\n   wf( \"+\", `<div class=\"panel\">\\n` );\n      // We just need the index to look sorted\n      for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n      {\n         if ( CMD4_Sorted_ACC.properties[ index ].deprecated == true)\n            continue;\n\n         // Lower case characteristic\n         let characteristic = CMD4_Sorted_ACC.properties[ index ].sche;\n\n         wfs( `<a href=\"#${ characteristic }\" onclick=\"toggleVisibility( '${ characteristic }');\">${ characteristic }</a>\\n` );\n      }\n   endDiv( \"panel\" );\n\n}\nfunction addSideNavCmd4DirectivesLinks_WithinSideNav( )\n{\n   // Accordion button for Directives\n   wf( \"+\", `<button class=\"accordion\">Directives\\n` );\n      wfs( `<i class=\"fa fa-caret-down\"></i>\\n` );\n   wf( \"-\", `</button>\\n` );\n\n   wf( \"+\", `<div class=\"panel\">\\n` );\n      wfs( `<a href=\"#${ constants.DEBUG }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.DEBUG }</a>\\n` );\n      wfs( `<a href=\"#${ constants.OUTPUTCONSTANTS }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.OUTPUTCONSTANTS }</a>\\n` );\n      wfs( `<a href=\"#${ constants.STATUSMSG }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.STATUSMSG }</a>\\n` );\n      wfs( `<a href=\"#${ constants.INTERVAL }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.INTERVAL }</a>\\n` );\n      wfs( `<a href=\"#${ constants.TIMEOUT }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.TIMEOUT }</a>\\n` );\n      wfs( `<a href=\"#${ constants.QUEUETYPES }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.QUEUETYPES }</a>\\n` );\n      wfs( `<a href=\"#${ constants.DEFINITIONS }_D\" onclick=\"toggleVisibility( 'Directives');\">${ constants.DEFINITIONS }</a>\\n` );\n   endDiv( \"panel\" );\n\n}\n\nfunction addSideNavCmd4AccessoryDirectivesLinks_WithinSideNav( )\n{\n   // Accordion button for Characteristics\n   wf( \"+\", `<button class=\"accordion\">Accessory Directives\\n` );\n      wfs( `<i class=\"fa fa-caret-down\"></i>\\n` );\n   wf( \"-\", `</button>\\n` );\n\n\n   wf( \"+\", `<div class=\"panel\">\\n` );\n      wfs( `<a href=\"#${ constants.SUBTYPE }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.SUBTYPE }</a>\\n` );\n      wfs( `<a href=\"#${ constants.FAKEGATO }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.FAKEGATO }</a>\\n` );\n      wfs( `<a href=\"#${ constants.PUBLISHEXTERNALLY }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.PUBLISHEXTERNALLY }</a>\\n` );\n      wfs( `<a href=\"#${ constants.STATE_CMD_PREFIX }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.STATE_CMD_PREFIX }</a>\\n` );\n      wfs( `<a href=\"#${ constants.STATE_CMD_SUFFIX }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.STATE_CMD_SUFFIX }</a>\\n` );\n      wfs( `<a href=\"#${ constants.STATE_CMD }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.STATE_CMD }</a>\\n` );\n      wfs( `<a href=\"#${ constants.POLLING }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.POLLING }</a>\\n` );\n      wfs( `<a href=\"#${ constants.INTERVAL }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.INTERVAL }</a>\\n` );\n      wfs( `<a href=\"#${ constants.TIMEOUT }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.TIMEOUT }</a>\\n` );\n      wfs( `<a href=\"#${ constants.QUEUE }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.QUEUE }</a>\\n` );\n      wfs( `<a href=\"#${ constants.STATECHANGERESPONSETIME }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.STATECHANGERESPONSETIME }</a>\\n` );\n      wfs( `<a href=\"#${ constants.LINKEDTYPES }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.LINKEDTYPES }</a>\\n` );\n      wfs( `<a href=\"#${ constants.OUTPUTCONSTANTS }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.OUTPUTCONSTANTS }</a>\\n` );\n      wfs( `<a href=\"#${ constants.STATUSMSG }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.STATUSMSG }</a>\\n` );\n   endDiv( \"panel\" );\n\n}\n\nfunction addSideNavCustomCharacteristicsLinks_WithinSideNav( )\n{\n   // Accordion button for Characteristics\n   wf( \"+\", `<button class=\"accordion\">Custom Characteristics\\n` );\n      wfs( `<i class=\"fa fa-caret-down\"></i>\\n` );\n   wf( \"-\", `</button>\\n` );\n\n   wf( \"+\", `<div class=\"panel\">\\n` );\n      wfs( `<a href=\"#CUSTOM_CHARACTERISTICS\" onclick=\"toggleVisibility( 'CustomCharacteristics');\">Custom Characteristics</a>\\n` );\n   endDiv( \"panel\" );\n}\n\nfunction addSideNavScriptTemplateLinks_WithinSideNav( )\n{\n   // Accordion button for ScriptTemplates\n   wf( \"+\", `<button class=\"accordion\">Script Templates\\n` );\n      wfs( `<i class=\"fa fa-caret-down\"></i>\\n` );\n   wf( \"-\", `</button>\\n` );\n\n   wf( \"+\", `<div class=\"panel\">\\n` );\n\n      CMD4_SCRIPTS.forEach( ( script ) =>\n      {\n         //wfs( `<a href=\"#${ script.link }\">${ script.link }</a>\\n` );\n         wfs( `<a href=\"#${ script.link }\" onclick=\"toggleVisibility( '${ script.link }');\">${ script.link }</a>\\n` );\n      });\n\n   endDiv( \"panel\" );\n\n}\n\nfunction addIntroductionPage_WithinContentDiv( )\n{\n   wf( \"+\", `<div class=\"main\">\\n` );\n   wfs( `<h2>CMD4 Portal</h2>\\n` );\n   wfs( `<p>This auto generated document replaces much of the hard coded definitions and is the portal to everything that is Cmd4.</p>\\n` );\n   wfs( `<p>Enjoy</p>\\n` );\n   wfs( `<p>&nbsp;&nbsp;&nbsp;John Talbot</p>\\n` );\n\n   endDiv( \"main\" );\n}\n\nfunction addDevicePages_WithinMain( )\n{\n   //wfs( `<h2>CMD4 Device Properties</h2>\\n` );\n   //wfs( `<p>This auto generated document replaces the hard coded, impossible to maintain definitions in what was the State.js script and other locations.</p>\\n` );\n\n   for ( let index=0; index < CMD4_DEVICE_TYPE_ENUM.EOL; index ++)\n   {\n      if ( CMD4_DEVICE_TYPE_ENUM.properties[ index ].deprecated == true)\n         continue;\n\n      let deviceName = CMD4_DEVICE_TYPE_ENUM.properties[ index ].deviceName;\n\n      addSingleDeviceContent( index, deviceName );\n   }\n\n}\n\nfunction addSingleDeviceContent(device_type_enum, deviceName )\n{\n   let definition = CMD4_DEVICE_TYPE_ENUM.properties[ device_type_enum ];\n   let requiredCharacteristics = definition.requiredCharacteristics;\n   let optionalCharacteristics = definition.optionalCharacteristics;\n   let defaultPollingCharacteristics = definition.defaultPollingCharacteristics;\n   let commaNeeded = true;\n\n   // Start deviceName Div\n   // The <div id> is used to show/hide the section.\n   // The <class> is used for css formatting, including initial hide.\n   // The <a name> is used to jump here when nav item clicked.\n   wf( \"+\", `<div id=\"${ deviceName }\" class=\"section\">\\n` );\n   wfs( `<a name=\"${ deviceName }\"></a>\\n` );\n   wfs( `<header><h1>${ deviceName }</h1></header>\\n` );\n   wfs( `<p>UUID:${ definition.UUID }</p>\\n` );\n\n   // Required Characteristics\n   wfs( `<H3>Required Characteristics</H3>\\n` );\n   if ( requiredCharacteristics && requiredCharacteristics.length > 0 )\n   {\n      wf( \"+\", `<table>\\n` );\n      wfs( `<TD> </TD><TD> Default Value </TD><TD> Constant </TD>\\n` );\n\n      requiredCharacteristics.forEach( ( characteristic ) =>\n      {\n         // Look up the characteristic index given, to its string value\n         let characteristicString = CMD4_ACC_TYPE_ENUM.properties[ characteristic.type ].sche;\n         let defaultValue = characteristic.defaultValue;\n\n         let transposed = transposeValueToValidConstant( CMD4_ACC_TYPE_ENUM.properties, characteristic.type, defaultValue );\n\n         if ( transposed == defaultValue )\n            transposed = \"n/a\";\n\n         wfs( `<tr><TD><UL><LI><a href=\"#${ characteristicString }\">${ characteristicString }</a></UL></TD><TD> ${ defaultValue } </TD><TD> ${ transposed } </TD>\\n` );\n      });\n      wf( \"-\", `</Table>\\n` );\n   }\n\n\n   // Optional Characteristics\n   wfs( `<H3>Optional Characteristics</H3>\\n` );\n   if ( optionalCharacteristics && optionalCharacteristics.length > 0 )\n   {\n      wf( \"+\", `<UL>\\n` );\n      optionalCharacteristics.forEach( ( characteristic ) =>\n      {\n         let characteristicString = CMD4_ACC_TYPE_ENUM.properties[ characteristic ].sche;\n        wfs( `<LI><a href=\"#${ characteristicString }\">${ characteristicString }</a>\\n` );\n      });\n      wf( \"-\", `</UL>\\n` );\n   }\n\n   // Default Polling  Characteristics\n   if ( defaultPollingCharacteristics && defaultPollingCharacteristics.length > 0 )\n   {\n      wfs( `<H3>Default Polling Characteristics</H3>\\n` );\n      wfs( `<note> Default polling characteristics are characteristics that would automatically be polled if Accessory Polling is configured ( polling:true ) instead of characteristic polling where each characteristic is set individually.\\n` );\n      wf( \"+\", `<UL>\\n` );\n\n      defaultPollingCharacteristics.forEach( ( characteristic ) =>\n      {\n         let characteristicString = CMD4_ACC_TYPE_ENUM.properties[ characteristic ].sche;\n         wfs( `<LI><a href=\"#${ characteristicString }\">${ characteristicString }</a>\\n` );\n      });\n\n      wf( \"-\", `</UL>\\n` );\n   }\n   wfs( `<H3>Example config.json entry</H3>\\n` );\n   commaNeeded = true;\n\n   // This is pre-formatted text\n   wfs( `<pre>\\n` );\n\n   // The stuff in the brace will be indented\n   wf( \"+\", `{\\n` );\n   wfs( `${ constants.TYPE }: ${ definition.deviceName },\\n` );\n   let nameCharacteristicString = CMD4_ACC_TYPE_ENUM.properties[ CMD4_ACC_TYPE_ENUM.Name ].sche;\n   wfs( `${ nameCharacteristicString }: \"MY_${ definition.deviceName }\",\\n` );\n   wfs( `${ constants.DISPLAYNAME }: \"MY_${ definition.deviceName }\"` );\n   if ( requiredCharacteristics && requiredCharacteristics.length > 0 )\n   {\n      requiredCharacteristics.forEach( ( characteristic ) =>\n      {\n         let requiredDefinition = CMD4_ACC_TYPE_ENUM.properties[ characteristic.type ];\n         if ( commaNeeded )\n            w( `,\\n` );\n\n         // Look up the characteristic index given, to its string value\n         let characteristicString = requiredDefinition.sche;\n         let defaultValue = characteristic.defaultValue;\n         wfs( `${ characteristicString }: \"${ defaultValue}\"` );\n      });\n   }\n\n   if ( optionalCharacteristics && optionalCharacteristics.length > 0 )\n   {\n      optionalCharacteristics.forEach( ( characteristic ) =>\n      {\n         let optionalDefinition = CMD4_ACC_TYPE_ENUM.properties[ characteristic ];\n         let characteristicString = optionalDefinition.sche;\n\n         if ( optionalDefinition.type == CMD4_ACC_TYPE_ENUM.Name )\n            return;\n\n         // Do not show TLV8 characteristics\n         let format = optionalDefinition.props.format;\n         switch( format )\n         {\n            case Characteristic.Formats.TLV8:\n               return;\n            case Characteristic.Formats.INT:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < INT >` );\n               break;\n            case Characteristic.Formats.UINT8:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < UINT8 >` );\n               break;\n            case Characteristic.Formats.UINT16:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < UINT16 >` );\n               break;\n            case Characteristic.Formats.UINT32:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < UINT32 >` );\n               break;\n            case Characteristic.Formats.UINT64:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < UINT64 >` );\n               break;\n            case Characteristic.Formats.STRING:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: \"< STRING> \"` );\n               break;\n            case Characteristic.Formats.BOOL:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < BOOLEAN >` );\n               break;\n            case Characteristic.Formats.ARRAY:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < ARRAY >` );\n               break;\n            case Characteristic.Formats.DATA:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < DATA >` );\n               break;\n            case Characteristic.Formats.DICTIONARY:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `${ characteristicString }: < DICTIONARY >` );\n               break;\n            default:\n               if ( commaNeeded ) w( `,\\n` );\n               wfs( `Unknown format ${ format }` );\n         }\n      });\n   }\n\n   if ( commaNeeded ) w( `,\\n` );\n      wfs( `<a href=\"#${ constants.STATE_CMD }\">${ constants.STATE_CMD }</a>: < \"STRING\" >,\\n` );\n   wfs( `<a href=\"#${ constants.POLLING }\">${ constants.POLLING }</a>: < POLLING>\\n` );\n   // The last carriage return before the close brace\n   w( `\\n` );\n\n   // End of the indented stuff in the brace\n   wf( \"-\", `}\\n` );\n\n   // End of pre-formatted text\n   wfs( `</pre>\\n` );\n\n   wfs( `See additional <a href=\"#CMD4 Accessory Directives\">CMD4 Accessory Directives</a>\\n` );\n\n   endDiv( deviceName );\n}\n\nfunction addCharacteristicPages_WithinMain( )\n{\n   //\n   // Add the characteristic content within the HTML body\n   //\n   for ( let index=0; index < CMD4_ACC_TYPE_ENUM.EOL; index ++)\n   {\n      if( CMD4_ACC_TYPE_ENUM.properties[ index ].deprecated == true )\n             continue;\n\n      let characteristic = CMD4_ACC_TYPE_ENUM.properties[ index ].sche;\n\n      addSingleCharacteristicContent( index, characteristic );\n\n   }\n}\n\nfunction addSingleCharacteristicContent( acc_type_enum, characteristic )\n{\n   let definition = CMD4_ACC_TYPE_ENUM.properties[ acc_type_enum ];\n   let props = CMD4_ACC_TYPE_ENUM.properties[ acc_type_enum ].props;\n\n   // Start characteristic div\n   // The <div id> is used to show/hide the section.\n   // The <class> is used for css formatting, including initial hide.\n   // The <a name> is used to jump here when nav item clicked.\n   wf( \"+\", `<div id=\"${ characteristic }\" class=\"section\" >\\n` );\n   wfs( `<a name=\"${ characteristic }\"></a>\\n` );\n   wfs( `<header><h1>${ characteristic }</h1></header>\\n` );\n   wfs( `<h3>Properties</h3>\\n` );\n   wf( \"+\", \n      `<table>\\n` );\n   wfs( `<tr><TD> Type: </TD><TD> ${ characteristic }</TD></tr>\\n` );\n\n   if ( definition.UUID )\n      wfs( `<tr><TD> UUID: </TD><TD> ${ definition.UUID }</TD></tr>\\n` );\n\n   if ( props.format )\n      wfs( `<tr><TD> Format: </TD><TD> ${ props.format }</TD></tr>\\n` );\n\n   if ( props.unit )\n      wfs( `<tr><TD> Unit: </TD><TD>  ${ props.unit }</TD></tr>\\n` );\n\n   if ( props.minValue )\n      wfs( `<tr><TD> Min Value: </TD><TD>  ${ props.minValue }</TD></tr>\\n` );\n\n   if ( props.maxValue )\n      wfs( `<tr><TD> Max Value: </TD><TD>  ${ props.maxValue }</TD></tr>\\n` );\n\n   if ( props.minStep )\n      wfs( `<tr><TD> Min Step: </TD><TD>  ${ props.minStep }</TD></tr>\\n` );\n\n   if ( props.perms )\n   {\n      let output = \"\";\n      let comma = \"\";\n      props.perms.forEach( ( perm ) =>\n      {\n         switch( perm )\n         {\n            case \"pr\":\n               output = output + comma + \"Paired Read\";\n               break;\n            case \"pw\":\n               output = output + comma + \"Paired Write\";\n               break;\n            case \"ev\":\n               output = output + comma + \"Events\";\n               break;\n            case \"tw\":\n               output = output + comma + \"Timed Write\";\n               break;\n            case \"wr\":\n               output = output + comma + \"Write Response\";\n               break;\n            default:\n               console.log( \"Unknown perm: %s\", perm );\n               process.exit(333);\n         }\n         comma = \", \";\n      });\n      wfs( `<tr><TD> Perms: </TD><TD>  ${ output }</TD></tr>\\n` );\n\n   }\n   wf( \"-\", `</table>\\n` );\n\n   // Constants definition Table\n   let defs = Object.keys( definition.validValues );\n   if ( defs.length > 0 )\n   {\n      wfs( `<h3>Constants</h3>\\n` );\n      wf( \"+\", `<table>\\n` );\n      wfs( `<TD> Value </TD><TD> String </TD>\\n` );\n\n      defs.forEach( ( def ) =>\n      {\n        wfs( `<tr><TD> ${ definition.validValues[ def ] } </TD><TD> \"${ def }\" </TD></tr>\\n` );\n      });\n\n      wf( \"-\", `</table>\\n` );\n   }\n\n   // Verify Chsracteristic Notes\n   let verify = definition.verifyCharacteristic;\n   if ( verify )\n   {\n      wfs( `<h4>Note:</h4>\\n` );\n      wfs( `<note>Setting this characteristic will automstically trigger a \"Get\" of the characteristic: <a href=\"#${ verify.name }\">${ verify.name }</a></note>\\n` );\n\n   }\n\n   endDiv( characteristic ); // Closing DIV of Characteristic\n\n}\n\nfunction addCmd4DirectivePages_WithinMain( )\n{\n   // Start Directives div\n   // The <div id> is used to show/hide the section.\n   // The <class> is used for css formatting, including initial hide.\n   // The <a name> is used to jump here when nav item clicked.\n   wf( \"+\", `<div id=\"Directives\" class=\"section\">\\n` );\n\n   wfs( `<h2>CMD4 Directives</h2>\\n` );\n   wfs( `<p>These directives appear within the \"Cmd4\" plugin header and reflect how Cmd4 will behave overall.</p>\\n` );\n\n\n   wf( \"+\", `<TABLE WIDTH=\"100%\">\\n` );\n   wfs( `<TR ALIGN=\"left\"><TH>Cmd4Directive<TH>Type<TH PADDING=\"50px\">Default<TH>Description</TR>\\n` );\n\n   // debug - CMD4 Directives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.DEBUG }_D\">${ constants.DEBUG }</a><TD>  < Bool >  <TD>    false    <TD> Output Debug messages. Can also be accomplished with setenv DEBUG=${ settings.PLATFORM_NAME}</TR>\\n` );\n\n   // outputConstants - CMD4 Directives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.OUTPUTCONSTANTS }_D\">${ constants.OUTPUTCONSTANTS }</a><TD>  < Bool >  <TD>    false    <TD> If Cmd4 will send Strings like \"TRUE\" or \"FALSE\" instead of 0 | 1 for all Accessories</TR>\\n` );\n\n   // statusMsg - CMD4 Directives - See cmd4Constants as why we do this\n   let  defaultStatusMsg = constants.DEFAULT_STATUSMSG;\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.STATUSMSG }_D\"> ${ constants.STATUSMSG }</a><TD> < Bool > <TD> ${ defaultStatusMsg } <TD> Cmd4 will log a Set Status Message for all Accessories.</TR>\\n` );\n\n   // Interval - CMD4 Directives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.INTERVAL }_D\"> ${ constants.INTERVAL }</a><TD> ${ constants.INTERVAL } <TD> ${ constants.DEFAULT_INTERVAL * .001 } < seconds > <TD> How long before killing the state command of all polled characteristics. See <a href=\"#${ constants.INTERVAL }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.INTERVAL }</a> in Accessory Directives for full description as it can also be set per accessory or per characteristic.</TR>\\n` );\n\n   // Timeout - CMD4 Directives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.TIMEOUT }_D\"> ${ constants.TIMEOUT }</a><TD> ${ constants.TIMEOUT } <TD> ${ constants.DEFAULT_TIMEOUT } < msec > <TD> How long before killing the state command of all polled characteristics. See <a href=\"#${ constants.TIMEOUT }\" onclick=\"toggleVisibility( 'AccessoryDirectives');\">${ constants.TIMEOUT }</a> in Accessory Directives for full description as it can also be set per accessory or per characteristic.</TR>\\n` );\n\n   // QueueTypes - CMD4 Directives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.QUEUETYPES }_D\"> ${ constants.QUEUETYPES }</a><TD> < Array of { \"${ constants.QUEUE }\": < \"SomeName\" >, \"${ constants.QUEUETYPE }\": < \"${ constants.QUEUETYPE_SEQUENTIAL }\" | \"${ constants.QUEUETYPE_WORM }\" > \"${ constants.QUEUE_RETRIES}\": < ${ constants.DEFAULT_WORM_QUEUE_RETRY_COUNT } > } <TD> none <TD> Pre-defines Queue types. This Directive can also be per queue as noted by its presence as an accessory directive.</TR>\\n` );\n\n   // Definitions - Custom Characteristics - CMD4 Directives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.DEFINITIONS }_D\"> ${ constants.DEFINITIONS }</a><TD> < Array > <TD> <TD> An Array of new Characteristic Objects. See <a href=\"#CUSTOM_CHARACTERISTICS\" onclick=\"toggleVisibility( 'CustomCharacteristics');\">Custom Characteristics, around line 339</a> for more information</TR>\\n` );\n\n   wf( \"-\", `</TABLE>\\n` );\n   endDiv( \"main\" );\n\n}\n\nfunction addCmd4AccessoryDirectivePages_WithinMain( )\n{\n   // Start AccessoryDirectives div\n   // The <div id> is used to show/hide the section.\n   // The <class> is used for css formatting, including initial hide.\n   // The <a name> is used to jump here when nav item clicked.\n   wf( \"+\", `<div id=\"AccessoryDirectives\" class=\"section\">\\n` );\n\n   wfs( `<h2><a name=\"CMD4 Accessory Directives\">CMD4 Accessory Directives</a></h2>\\n` );\n   wfs( `<p>These directives appear within the characteristic section of the Cmd4 Accessory</p>\\n` );\n\n   wf( \"+\", `<TABLE WIDTH=\"100%\" border: 1px solid black >\\n` );\n   wfs( `<TR cols=\"4\" ALIGN=\"left\"><TH>Cmd4Directive<TH>Type<TH PADDING=\"50px\">Default<TH>Description</TR>\\n` );\n\n   // subType\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.SUBTYPE }\">${ constants.SUBTYPE }</a><TD> < unique string > <TD> accessory.name <TD> Used to distinguish accessories that have same Type and Name.</TR>\\n` );\n\n   // outputConstants - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.OUTPUTCONSTANTS }\">${ constants.OUTPUTCONSTANTS }</a><TD>  < Bool >  <TD>    false    <TD> If Cmd4 will send Strings like \"TRUE\" or \"FALSE\" instead of 0 | 1 </TR>\\n` );\n\n   // statusMsg - AccessoryDirectives\n   let defaultStatusMsg = constants.DEFAULT_STATUSMSG;\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.STATUSMSG }\">${ constants.STATUSMSG }</a><TD>  < Bool >  <TD>  ${ defaultStatusMsg } <TD>Cmd4 will log a Set Status Message</TR>\\n` );\n\n   // publishExternally - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.PUBLISHEXTERNALLY }\">${ constants.PUBLISHEXTERNALLY }</a><TD>  < Bool >  <TD>    false     <TD> Tell Homebridge to publish the device as its own bridge. </TR>\\n` );\n\n   // stateChangeResponseTime - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.STATECHANGERESPONSETIME }\">${ constants.STATECHANGERESPONSETIME }</a><TD> < seconds > <TD> 60 <TD> How long to wait between a Set and Get command.</TR>\\n` );\n\n   // interval - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.INTERVAL }\">${ constants.INTERVAL }</a><TD> < seconds > <TD> ${ constants.DEFAULT_INTERVAL * .001 } < seconds > <TD> How long between polls of all polled characteristics.</TR>\\n` );\n\n   // timeout - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.TIMEOUT }\">${ constants.TIMEOUT }</a><TD> < msec > <TD> ${ constants.DEFAULT_TIMEOUT } < msec > <TD> How long before killing the state command of all polled characteristics.</TR>\\n` );\n\n   // polling - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.POLLING }\">${ constants.POLLING }</a><TD> < Bool > <TD> false <TD> If the characteristics should be polled for state change.</TR>\\n` );\n\n   wfs( `<TR><TD><TD COLSPAN=3> or  [{\"characteristic\" < characteristic >, [ \"interval\": < sec >, \"timeout\": < msec > ] }] The timeout and interval override any higher directive.</TR>\\n` );\n\n   // Queue - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.QUEUE }\"> ${ constants.QUEUE }</a><TD> ${ constants.QUEUE } <TD> < String > <TD> Defines which Queue polled characteristics will be placed.</TR>\\n` );\n\n   // state_cmd - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.STATE_CMD }\">${ constants.STATE_CMD }</a><TD>  < ${ constants.STATE_CMD } > <TD> See Description <TD> The command used to Get/Set Device characteristic State.</TR>\\n` );\n   wfs( `<TR><TD COLSPAN=\"4\">The ${ constants.STATE_CMD } represents the path to your script. Cmd4 appends the Get/Set shown.<BR>\\n` );\n   wfs( `${ constants.STATE_CMD } Get < DisplayName > < characteristic ><BR>\\n` );\n   wfs( `${ constants.STATE_CMD } Set < DisplayName > < characteristic > < value ></TD></TR>\\n` );\n\n   // state_cmd_prefix - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.STATE_CMD_PREFIX }\">${ constants.STATE_CMD_PREFIX }</a><TD>  < String > <TD> <TD> A String prepended to the < ${ constants.STATE_CMD } >.</TR>\\n` );\n\n   // state_cmd_suffix - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.STATE_CMD_SUFFIX }\">${ constants.STATE_CMD_SUFFIX }</a><TD> < String > <TD> <TD> A String appended to the < ${ constants.STATE_CMD } >.</TR>\\n` );\n\n   // props - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.PROPS }\">${ constants.PROPS }</a><TD>  < Bool >  <TD>    false     <TD> A way to override Hap Characteristiic Properties<BR>\\n` );\n   wfs( `         Only used to set min/max temperatures, for instance:</TR>\\n` );\n   wfs( `<TR ALIGN=\"Left\"><TD><TD COLSPAN=3>\"${ constants.PROPS }\" : { \"currentTemperature\": { \"maxValue\":100, \"minValue\": -100, \"minStep\": 0.1}}</TR>\\n` );\n\n   // category - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.CATEGORY }\">${ constants.CATEGORY }</a><TD> < CATEGORY > <TD> <TD> See <a href=\"https://developers.homebridge.io/#/categories\">Homebridge Categories</a> for a complete list of possible categories.  </TR>\\n` );\n\n   // fakegato - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.FAKEGATO }\">${ constants.FAKEGATO }</a><TD>  < JSON >  <TD> <TD> See the section, <a href=\"https://github.com/ztalbot2000/homebridge-cmd4/docs/Developers.md#fakegatotag\"> \"Adding in Fakegato history\"</a> below.</TR>\\n` );\n\n   // linkedTypes - AccessoryDirectives\n   wfs( `<TR ALIGN=\"left\"><TD><a name=\"${ constants.LINKEDTYPES }\">${ constants.LINKEDTYPES }</a><TD>  < JSON >  <TD> <TD> Other Cmd4 Accessories like Input Source for HDMI inputs. </TR>\\n` );\n\n\n   wf( \"-\", `</TABLE>\\n` );\n   endDiv( \"main\" );\n\n}\n\nfunction addCustomCharacteristicPages_withinMain( )\n{\n   wf( \"+\", `<div id=\"CustomCharacteristics\" class=\"section\">\\n` );\n\n   wfs( `<h2><a name=\"CUSTOM_CHARACTERISTICS\">Custom Characteristics</a></h2>\\n` );\n   wfs( `<p>These directives appear within the Cmd4 Platform section</p><BR>\\n` );\n   wfs( `<p>IMPORTANT - It is unlikely that adding custom characteristics will be supported by any GUI or SIRI<BR>\\n` );\n   wfs( `<BR><BR>\\n` );\n   wfs( `<p>Custom characteristics in Cmd4 do not stray far from how Homebridge uses them from HAP-NodeJS. To create a custom characteristic an object entry is programmatically added to <a href=\"https://github.com/ztalbot2000/homebridge-cmd4/blob/master/lib/CMD4_ACC_TYPE_ENUM.js\">lib/CMD4_ACC_TYPE_ENUM.js</a> via an entry you define in your config.json. The best way to show how to define a custom characteristic is through an example</p>.\\n` );\n   wf( \"+\", `<pre>\\n` );\n   wfs( `{\\n` );\n   wfs( `   \"platform\": \"Cmd4\",\\n` );\n   wfs( `   \"outputConstants\": false,\\n` );\n   wfs( `   \"statusMsg\": true,\\n` );\n   wfs( `   \"Definitions\": [\\n` );\n   wfs( `      { \"type\": \"PointX\",\\n` );\n   wfs( `        \"description\": \"An X Coordinate\",\\n` );\n   wfs( `        \"props\": { \"format\": \"uint32\",\\n` );\n   wfs( `                   \"minValue\": 0,\\n` );\n   wfs( `                   \"minStep\": 1,\\n` );\n   wfs( `                   \"perms\": [ \"ev\", \"pr\", \"pw\" ]\\n` );\n   wfs( `                 }\\n` );\n   wfs( `      }\\n` );\n   wfs( `   ],\\n` );\n   wfs( `   \"accessories\": [\\n` );\n   wfs( `      { \"type\": \"Switch\",\\n` );\n   wfs( `        \"name\": \"PS_4\",\\n` );\n   wfs( `        \"PointX\": 3267,\\n` );\n   wfs( `        \"on\": false,\\n` );\n   wfs( `        \"polling\": [ { \"characteristic\": \"on\", \"interval\": 50 },\\n` );\n   wfs( `                     { \"characteristic\": \"pointX\", \"interval\": 5 }\\n` );\n   wfs( `                   ],\\n` );\n   wfs( `        \"state_cmd\": \"node .homebridge/Cmd4Scripts/AnyDevice.js\"\\n` );\n   wfs( `      }\\n` );\n   wfs( `   ]\\n` );\n   wfs( `}\\n` );\n   wf( \"-\", `</pre>\\n` );\n   wfs( `<BR><BR>\\n` );\n   wfs( `<p>The definitions for \"props\" can be found at: <a href=\"https://github.com/homebridge/HAP-NodeJS/blob/master/src/lib/Characteristic.ts\">HAP Characteristics - line 259</a></p>\\n` );\n\n\n\n   endDiv( \"CustomCharacteristics\" );\n}\n\nfunction addScriptTemplatePages_WithinMain( )\n{\n   CMD4_SCRIPTS.forEach( ( script ) =>\n   {\n      addScriptPage_WithinMain( script );\n   });\n}\n\nfunction addScriptPage_WithinMain( script )\n{\n   // Start script.link div\n   // The <div id> is used to show/hide the section.\n   // The <class> is used for css formatting, including initial hide.\n   // The <a name> is used to jump here when nav item clicked.\n   wf( \"+\", `<div id=\"${ script.link }\" class=\"section\">\\n` );\n\n   wfs( `<h2><a name=\"${ script.link }\">${ script.description }</a></h2>\\n` );\n   // Create the full path to the file.\n   let file = script.filePath +  script.file;\n\n   wfs( `<p> This script is auto generated from: <a href=https://github.com/ztalbot2000/homebridge-cmd4/blob/master/${ file }>${ file } </a></p>\\n` );\n   wf( \"+\", `<pre>\\n` );\n\n\n   let readStream = fs.readFileSync( file, {encoding: 'utf8'} );\n   w( readStream );\n\n   wf( \"-\", `</pre>\\n` );\n\n   endDiv( \"main\" );\n}\n\nfunction endDiv( comment )\n{\n   let div = \"</DIV>\";\n   if ( comment )\n      div = div + `   <!-- ${comment} -->`;\n\n   div = div + \"\\n\";\n\n   wf( \"-\" , div );\n}\n\n\n// Write to fid the given text, increasing or decreasing divLevel.\nfunction wf( level, text )\n{\n   // Subtract now\n   if ( level == \"-\" )\n      divLevel--;\n\n   fid.write( \" \".repeat( divLevel * INDENT ).concat( text ) );\n\n   // Add later \n   if (level == \"+\" )\n      divLevel++;\n}\n\n// Convenience function for wfs. writing to same level.\nfunction wfs( text )\n{\n   wf( \"nc\", text );\n}\n// Convenience function to write to fid, no formatting, as is.\nfunction w( text )\n{\n   fid.write( text );\n}\n\ncreateHTMLCmd4AccDocument( );\n\nif ( divLevel == 0)\n{\n   console.log( \"Yahoo !  All lined up. \" );\n   return 0;\n} else {\n   console.log( \"Booo ... alignment failed: %s\", ['','+'][Number(divLevel > 0)] + divLevel );\n}\nreturn divLevel;\n"
  },
  {
    "path": "tools/generateChangeLog",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\n// File System utilities\nlet fs = require( \"fs\" );\nlet readline = require( \"readline\" );\n\n// Command line parser\nconst { Command } = require( \"commander\" );\nconst program = new Command;\n\n// Tool to get changelog information\nlet Changelog = require( 'generate-changelog' );\n\nlet CHANGELOG = \"CHANGELOG\";\nlet RUNNING_CHANGELOG = \"RUNNING_CHANGELOG\";\n// Wondering why ${ fn }_SAVE.ext instead of ${ fn }.SAVE ?\n// Between git and npm you cannot ignore special files if you\n// stick an extension on them. So put the extension in the file name itself.\nlet RUNNING_CHANGELOG_NEW = `${ RUNNING_CHANGELOG }_new.md`;\nlet RUNNING_CHANGELOG_BAK = `${ RUNNING_CHANGELOG }_bak.md`;\nlet CHANGELOG_NEW = `${ CHANGELOG }_new.md`;\nlet CHANGELOG_BAK = `${ CHANGELOG }_bak.md`;\n\nlet CHANGELOG_tag = \"## ChangeLog\";\n\nlet PACKAGE = \"package\";\nlet PACKAGE_NEW = `${ PACKAGE }_new.json`;\nlet PACKAGE_BAK = `${ PACKAGE }_bak.json`;\n// Get the package information\nconst pkg = require( `../${ PACKAGE }.json` );\n\n\n// A nice little getOpt node.js package\nprogram\n  .description( 'Generate an indexed changelog from git commits.' )\n  .option( '-t, --type <type>', 'flavour of changelog < patch | minor | major >' )\n  .option( '-d, --dryRun', 'Do not overwrite existing CHANGELOG.md>' )\n  .option( '-r, --cleanup', 'After completion, remove created backup files.' );\n\n// Parse the arguments passed into this program.\nprogram.parse( process.argv );\n\n// Get the options passed in based on the commander getOpts definitions.\nlet options = program.opts( );\n\nif ( options.dryRun === undefined )\n{\n   options.dryRun = false;\n   console.log( `Option \"dryRun\" Not specified. Backup files will be created.` );\n} else\n{\n   options.dryRun = true;\n   console.log( `dryRun specified. No files will be overwritten` );\n}\n\nif ( options.type === undefined )\n{\n   options.type = \"patch\";\n   console.log( `No --type given. Using default: ${ options.type }`);\n} else\n{\n   switch ( options.type )\n   {\n      case \"patch\":\n      case \"minor\":\n      case \"major\":\n         break;\n      default:\n         console.log( `Error: unknown ChangeLogType: ${ options.type }` );\n         process.exit( 666 );\n   }\n   console.log( `Using options.type: ${ options.type }` );\n}\nif ( options.cleanup === undefined )\n{\n   options.cleanup = false;\n   console.log( `Option \"cleanup\" after completion Not specified. Backup files will not be removed.` );\n} else\n{\n   options.cleanup = true;\n   console.log( `Option \"cleanup\" specified. Created backup files will be removed after completion` );\n}\n\n\n// Check for any leftover arguments passed in.\nif ( program.args.length >= 1 )\n{\n   console.log( `Unknown options: ${ program.args[ 0 ] }` );\n   process.exit( 666 );\n}\n\n// We do not start from scratch\nif ( pkg.version === undefined )\n{\n   console.log( `No existing version in ${ PACKAGE }.json to change from.` );\n   console.log( `Cannot update ${ PACKAGE }.json`);\n   process.exit( 666 );\n}\n\n\nfunction overwriteFileWithBackup( origFile, newFile, backupFile, cleanup )\n{\n   if ( fs.existsSync( backupFile ) )\n   {\n      console.log( `Error: backup file ${ backupFile } already exists. Aborting` );\n      process.exit( fs.COPYFILE_EXCL );\n   }\n\n   // move the original file to a backup file\n   return fs.rename( origFile, backupFile, function ( err )\n   {\n      if ( err )\n      {\n         console.log( `Could not rename ${ origFile } to ${ newFile }` );\n         process.exit( err );\n      }\n\n      // move the new file to the existing.\n      fs.rename( newFile, origFile, function ( err )\n      {\n         if ( err )\n         {\n            console.log( `Could not rename ${ newFile } to ${ origFile }` );\n            process.exit( err );\n         }\n\n         console.log( `Renamed ${ newFile } to ${ origFile } with backup of ${ backupFile }` );\n\n         if ( cleanup == true )\n         {\n            fs.unlink( backupFile, function ( err )\n            {\n               if ( err )\n               {\n                  console.log( `Could not unlink ${ backupFile }` );\n                  process.exit( err );\n               }\n               console.log( `Removed ${ backupFile }` );\n            });\n         }\n\n      });\n\n   });\n}\n\nfunction updateChangeLog( changelog, newVersionString, options )\n{\n   let newIndexEntryToBeWritten = false;\n   let indexBeingWritten = false;\n   let newBodyEntryToBeWritten = false;\n   let changeLogTagFound = false;\n   let dashedVersionString = newVersionString.replace( /\\./g, \"-\" );\n\n   // Open the new RUNNING_CHANGELOG for writing\n   let newRunningChangeLog_fid = fs.createWriteStream( RUNNING_CHANGELOG_NEW,\n      { flags: \"w\" // Open for write\n      }\n   );\n\n   newRunningChangeLog_fid.on( \"error\", ( ) =>\n   {\n      console.log( `error fs.creatingWriteStream: ${ RUNNING_CHANGELOG_NEW }` );\n      process.exit( 666 );\n   });\n\n   // Open the new CHANGELOG for writing\n   let newChangeLog_fid = fs.createWriteStream( CHANGELOG_NEW,\n      { flags: \"w\" // Open for write\n      }\n   );\n   newChangeLog_fid.on( \"error\", ( ) =>\n   {\n      console.log( `error fs.creatingWriteStream: ${ CHANGELOG_NEW }` );\n      process.exit( 666 );\n   });\n\n   const fileStream = fs.createReadStream( `${ RUNNING_CHANGELOG }.md` );\n\n   let rd = readline.createInterface(\n   {\n      input: fileStream,\n      crlfDelay: Infinity\n   });\n\n   rd.on( \"line\", function( line )\n   {\n      if ( newIndexEntryToBeWritten  == true )\n      {\n         // Write the new index line to the running CHANGELOG\n         newRunningChangeLog_fid.write( `* <a href=\"#Whats-new-in-${ dashedVersionString }\">**Whats new in ${ newVersionString }**</a>\\n` );\n\n         // Write a header to the CHANGELOG\n         newChangeLog_fid.write( `# Homebridges-cmd4 - CMD4 Plugin for Homebridge - Supports ~All Accessory Types and now all Characteristics too!!\\n` );\n\n         // The new Index line has been written\n         newIndexEntryToBeWritten = false;\n\n         // Currently writing index entries. Looking for Body\n         indexBeingWritten = true;\n      }\n\n      if ( newBodyEntryToBeWritten == true )\n      {\n         //Write the new Changelog\n         newRunningChangeLog_fid.write( `<a name=\"Whats-new-in-${ dashedVersionString }\">## Whats new in ${ newVersionString }</a>\\n` );\n         newRunningChangeLog_fid.write( `${ changelog }\\n` );\n\n         newChangeLog_fid.write( `${ changelog }\\n` );\n         newBodyEntryToBeWritten = false;\n      }\n\n      if ( line.includes( CHANGELOG_tag ) && changeLogTagFound == false )\n      {\n         newIndexEntryToBeWritten = true;\n         changeLogTagFound = true;\n      }\n\n      // An empty line signifies the end of the index\n      if ( indexBeingWritten == true && line == \"\" )\n      {\n         indexBeingWritten = false;\n         newBodyEntryToBeWritten = true;\n      }\n\n      // Write the line\n      newRunningChangeLog_fid.write( `${ line }\\n` );\n   });\n\n   newRunningChangeLog_fid.on( \"close\", function( )\n   {\n      if ( options.dryRun == true )\n      {\n         console.log( `New ${ RUNNING_CHANGELOG }.md is ${ RUNNING_CHANGELOG_NEW }` );\n         console.log( `Original left unchanged.` );\n         return;\n      }\n\n      overwriteFileWithBackup( `${ RUNNING_CHANGELOG }.md`, RUNNING_CHANGELOG_NEW, RUNNING_CHANGELOG_BAK, options.cleanup, function ( )\n      {\n         console.log( `Successfully created ${ RUNNING_CHANGELOG }` );\n\n         console.log( `You may now wish to run:` );\n         console.log( `git tag -a v${ newVersionString }` );\n         console.log( `and` );\n         console.log( `git push -f ${ pkg.repository.url } master` );\n         console.log( `or` );\n         console.log( `git push origin master` );\n\n      });\n   });\n\n   newChangeLog_fid.on( \"close\", function( )\n   {\n      if ( options.dryRun == true )\n      {\n         console.log( `New ${ CHANGELOG }.md is ${ CHANGELOG_NEW }` );\n         console.log( `Original left unchanged.` );\n         return;\n      }\n\n      overwriteFileWithBackup( `${ CHANGELOG }.md`, CHANGELOG_NEW, CHANGELOG_BAK, options.cleanup, function ( )\n      {\n         console.log( `Successfully created ${ CHANGELOG }` );\n\n      });\n   });\n\n   rd.on( \"close\", function( )\n   {\n      // Close the CHANGELOG files\n      newRunningChangeLog_fid.close( );\n\n      newChangeLog_fid.close( );\n   });\n\n}\n\nfunction updatePackageDotJson( currentVersion, newVersionString, options )\n{\n   pkg.version = newVersionString;\n\n   fs.writeFile( `${ PACKAGE_NEW }`, JSON.stringify( pkg, null, 3 ), ( err ) =>\n   {\n      if ( err ) process.exit( err );\n\n      if ( options.dryRun == true )\n      {\n         console.log( `New ${ PACKAGE }.json is ${ PACKAGE_NEW }` );\n         console.log( `Original left unchanged.` );\n         return;\n      }\n\n      overwriteFileWithBackup( `${ PACKAGE }.json`, PACKAGE_NEW, PACKAGE_BAK, options.cleanup, function ( )\n      {\n         console.log( `Successfully created ${ PACKAGE_NEW }` );\n\n      });\n   });\n}\n\nChangelog.generate(\n   { [ options.type ]: true\n   } ).then( function ( changelog )\n{\n   let words = changelog.split( \" \" );\n   let newVersionString = words[ 1 ];\n   updateChangeLog( changelog, newVersionString, options );\n\n   updatePackageDotJson( pkg.version, newVersionString, options );\n\n});\n"
  },
  {
    "path": "tools/whereIsConstant",
    "content": "#!/usr/bin/env node\n\"use strict\";\n\n// File System utilities\nlet fs = require(\"fs\");\n\n// Command line parser\nconst { Command } = require( \"commander\" );\nconst program = new Command;\n\nconst constants = require( \"../cmd4Constants\" );\n\nvar cmd4Files = [ \"./Cmd4Platform.js\",\n                  \"./Cmd4Accessory.js\",\n                  \"./Cmd4PriorityPollingQueue.js\",\n                  \"./utils/HV.js\",\n                  \"./index.js\",\n                  \"./lib/CMD4_DEVICE_TYPE_ENUM.js\",\n                  \"./tools/Cmd4AccDocGenerator\"];\n\n// A nice little getOpt node.js package\nprogram\n  .description( 'Determine where a given constant is in our source.' )\n  .requiredOption( '-c, --constant <constant value>', 'Constant to search for>' )\n  .option( '-r, --reverse', 'Look for key of constant' )\n  .option( '-v, --verbose', 'Show verbose search results' );\n\n// Parse the arguments passed into this program.\nprogram.parse( process.argv );\n\n\n// Get the options passed in based on the commander getOpts definitions.\nlet options = program.opts( );\n\n// This is the count of the found constants in result\nlet foundCount=0;\n\n// Stop after finding this many\nconst MAX_FOUND_BEFORE_EXIT = 3\n\n// The regex to find the constant in the source files\n// A great regex site:\n// https://regex101.com/r/bE3c0x/5\nlet reg;\n\nlet lookingFor = \"\";\n\nif ( options.reverse )\n{\n   // WORKS. Ex:   whereIsConstant -r -v -c PUBLISHEXTERNALLY\n   lookingFor = constants[ options.constant ];\n   if ( lookingFor == undefined )\n   {\n      console.error( `Constant key: ${ options.constant } not defined in cmd4Constants.js` );\n      process.exit( 1 );\n   }\n   reg = `.*constants.${ options.constant }.*$`;\n   // My logic seems reversed, but that is not true\n   console.log( `Looking for: constants.${ options.constant }` );\n   if ( options.verbose )\n      console.log( `using regex: ${ reg }` );\n} else\n{\n   // Works. Ex:   whereIsConstant -r -v -c publishExternally\n   lookingFor = Object.keys( constants ).find(key => constants[ key ] === options.constant );\n   if ( lookingFor == undefined )\n   {\n      console.error( `Constant value: ${ options.constant } not defined in cmd4Constants.js` );\n      process.exit( 1 );\n   }\n   reg = `\\\\w*.${ options.constant }.*$`;\n   // My logic seems reversed, but that is not true\n   console.log( `Looking for: <word>.${ lookingFor }` );\n   if ( options.verbose )\n      console.log( `using regex: ${ reg }` );\n}\nconst regex = new RegExp( reg );\n\n\n// The constant must be in one of the Cmd4 source files\nfor ( let fileIndex = 0;\n          (fileIndex < cmd4Files.length );\n          fileIndex++ )\n{\n   let cmd4File = cmd4Files[ fileIndex ];\n   if ( options.verbose )\n      console.log( `Checking file: ${ cmd4File }` );\n\n   // Read in all the code from the source file\n   let code =  fs.readFileSync( cmd4File, \"utf8\" );\n\n   // If I could grep the source file I would, so\n   // check the regex against each line\n   var codeLines = code.split( '\\n' );\n   let lineCount = 0;\n   for ( let lineIndex = 0;\n             lineIndex < codeLines.length;\n             lineIndex++, lineCount++ )\n   {\n      let line = codeLines[ lineIndex ];\n\n      // Check the regex\n      let t = regex.test( line );\n      if ( t == true )\n      {\n         foundCount++;\n         if ( foundCount == 1 )\n         {\n            process.stdout.write( `Found in ${ cmd4File }` );\n         }\n         else if ( foundCount <= MAX_FOUND_BEFORE_EXIT )\n         {\n            process.stdout.write( `, ${ cmd4File }` );\n         }\n         else\n         {\n            process.stdout.write(` ...\\n` );\n            process.exit( 0 );\n         }\n      }\n   }\n   if (foundCount == MAX_FOUND_BEFORE_EXIT )\n      break;\n}\nif (foundCount == 0 )\n{\n   console.log( `constant: ${ options.constant } not found in Cmd4 source files` );\n   process.exit( 1 );\n} else\n{\n   // Trailing \\n\n   console.log(\"\");\n}\nprocess.exit( 0 );\n\n"
  },
  {
    "path": "utils/Cmd4Storage.js",
    "content": "'use strict';\n\n// These would already be initialized by index.js\nlet CMD4_ACC_TYPE_ENUM = require( \"../lib/CMD4_ACC_TYPE_ENUM\" ).CMD4_ACC_TYPE_ENUM;\n\nclass Cmd4Storage\n{\n   constructor( log, cmd4Storage )\n   {\n      this.CLASS_VERSION = 1;\n      this.DATA = [ ];\n\n      if ( cmd4Storage == undefined )\n      {\n         log.debug(\"Init new cmd4Storage\" );\n\n         // init new\n         this.DATA = new Array( CMD4_ACC_TYPE_ENUM.EOL ).fill( null );\n\n      } else if ( cmd4Storage instanceof Cmd4Storage )\n      {\n         log.debug(\"Class is Cmd4Storage version: %s\", cmd4Storage.version );\n         if ( cmd4Storage.CLASS_VERSION == this.CLASS_VERSION )\n         {\n            // The same. I can just load its data\n            this.loadLatestData( cmd4Storage.DATA );\n         } else {\n            throw new Error( `Do not know how to handle Cmd4_Storage Class version: ${ cmd4Storage.CLASS_VERSION }` );\n         }\n      } else if ( Array.isArray( cmd4Storage ) )\n      {\n         log.debug(\"Cmd4Storage is Array\" );\n         // Init original unversioned\n         let data = this.upgradeDataArray( 0, cmd4Storage );\n         this.loadLatestData( data );\n\n      } else if ( cmd4Storage.constructor === Object )\n      {\n         log.debug(\"Cmd4Storage is Object version %s\", cmd4Storage.CLASS_VERSION );\n         if ( cmd4Storage.CLASS_VERSION == this.CLASS_VERSION )\n         {\n            // The same. I can just load its data\n            this.loadLatestData( cmd4Storage.DATA );\n         } else {\n            throw new Error( `Do not know how to handle Cmd4_Storage Class version: ${ cmd4Storage.CLASS_VERSION }` );\n         }\n      } else\n      {\n         // Woops init new\n         log.error( \"cmd4Storage is %s\", cmd4Storage );\n         console.error( \"cmd4Storage.constructor.name is %s\", cmd4Storage.constructor.name );\n         throw new Error( `Do not know how to handle typeof: ${ typeof cmd4Storage } Cmd4_Storage parm: ${ cmd4Storage }` );\n      }\n   }\n\n   upgradeDataArray( fromVersion, fromData)\n   {\n      let data = [ ];\n\n      if ( fromVersion != 0 )\n         throw new Error( `Do not know how to handle Cmd4_Storage version: ${ fromVersion }` );\n\n      // Version 0 ACC_DATA went from 0-122\n      // This version goes from 1-123 and changes to\n      // Assoc array so that index changes like this will no longer\n      // impact the storage schema as much\n      let i=0;\n      for ( i=0; i < CMD4_ACC_TYPE_ENUM.ListPairings; i++ )\n      {\n         data[ i ] = fromData[ i ];\n      }\n      data[ CMD4_ACC_TYPE_ENUM.ListPairing ] = null;\n      for ( i = CMD4_ACC_TYPE_ENUM.ListPairings +1; i < CMD4_ACC_TYPE_ENUM.EOL; i++ )\n      {\n         data[ i ] = fromData[ i - 1 ];\n      }\n      return data;\n   }\n\n   loadLatestData( data )\n   {\n      this.DATA = data;\n   }\n\n   getStoredValueForIndex( accTypeEnumIndex )\n   {\n      if ( accTypeEnumIndex < 0 || accTypeEnumIndex >= CMD4_ACC_TYPE_ENUM.EOL )\n         throw new Error( `getStoredValue - Characteristic index: ${ accTypeEnumIndex } not between 0 and ${ CMD4_ACC_TYPE_ENUM.EOL }\\nCheck your config.json file for unknown characteristic.` );\n\n\n      return this.DATA[ accTypeEnumIndex ];\n   }\n\n   getStoredValueForCharacteristic( characteristicString )\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.indexOfEnum( characteristicString );\n\n      return this.getStoredValueForIndex( accTypeEnumIndex );\n   }\n   setStoredValueForIndex( accTypeEnumIndex, value )\n   {\n      if ( accTypeEnumIndex < 0 || accTypeEnumIndex >= CMD4_ACC_TYPE_ENUM.EOL )\n         throw new Error( `setStoredValue - Characteristic index: ${ accTypeEnumIndex } not between 0 and ${ CMD4_ACC_TYPE_ENUM.EOL }\\nCheck your config.json file for unknown characteristic.` );\n\n      this.DATA[ accTypeEnumIndex  ] = value;\n   }\n   setStoredValueForCharacteristic( characteristicString, value )\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.indexOfEnum( characteristicString );\n\n      this.setStoredValueForIndex( accTypeEnumIndex, value );\n   }\n\n   // Unlike get/set, testStoredValueForIndex does not call process.exit,\n   // but undefined for an illegal range, in the case that rogue runtime data\n   // dies not take down CMD4.\n   testStoredValueForIndex( accTypeEnumIndex )\n   {\n      if ( accTypeEnumIndex < 0 || accTypeEnumIndex > CMD4_ACC_TYPE_ENUM.EOL )\n         return undefined;\n\n      return this.DATA[ accTypeEnumIndex ];\n   }\n   testStoredValueForCharacteristic( characteristicString )\n   {\n      let accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.indexOfEnum( characteristicString );\n\n      return this.testStoredValueForIndex( accTypeEnumIndex );\n   }\n}\n\nmodule.exports = Cmd4Storage;\n"
  },
  {
    "path": "utils/HV.js",
    "content": "'use strict';\n\nconst constants = require( \"../cmd4Constants\" );\n\n// These would already be initialized by index.js\nlet CMD4_DEVICE_TYPE_ENUM = require( \"../lib/CMD4_DEVICE_TYPE_ENUM\" ).CMD4_DEVICE_TYPE_ENUM;\n\nclass HV\n{\n   constructor ()\n   {\n      this.allowTLV8 = constants.DEFAULT_ALLOW_TLV8;\n      this.debug = constants.DEFAULT_DEBUG;\n      this.outputConstants = constants.DEFAULT_OUTPUTCONSTANTS;\n      this.interval = constants.DEFAULT_INTERVAL;\n      this.stateChangeResponseTime = constants.DEFAULT_STATE_CHANGE_RESPONSE_TIME;\n      this.statusMsg = constants.DEFAULT_STATUSMSG;\n      this.timeout = constants.DEFAULT_TIMEOUT;\n\n      this.stateChangeResponseTimeHasBeenUpdated = false;\n   }\n\n   update( entity )\n   {\n      // Heirarchy Next the Device Properties\n      if ( entity.typeIndex != undefined &&\n           this.stateChangeResponseTimeHasBeenUpdated == false )\n      {\n         this.stateChangeResponseTime = CMD4_DEVICE_TYPE_ENUM.properties[ entity.typeIndex ].devicesStateChangeDefaultTime;\n      }\n\n      // FakeGato Hierarchy\n      if ( entity.storage != undefined )\n         this.storage = entity.storage;\n      if ( entity.storagePath != undefined )\n         this.storagePath = entity.storagePath;\n      if ( entity.folder != undefined )\n         this.folder = entity.folder;\n      if ( entity.keyPath != undefined )\n         this.keyPath = entity.keyPath;\n\n      // Heirarchy\n      if ( entity.allowTLV8 != undefined )\n         this.allowTLV8 = entity.allowTLV8;\n\n\n      if ( entity.debug != undefined )\n           this.debug = entity.debug;\n      if ( entity.definitions != undefined )\n           this.definitions = entity.definitions;\n      if ( entity.interval != undefined )\n           this.interval = entity.interval;\n      if ( entity.outputConstants != undefined )\n           this.outputConstants = entity.outputConstants;\n      if ( entity.queueTypes != undefined )\n           this.queueTypes = entity.queueTypes;\n      if ( entity.stateCmd != undefined )\n           this.stateCmd = entity.stateCmd;\n      if ( entity.state_cmd_prefix != undefined )\n           this.state_cmd_prefix = entity.state_cmd_prefix;\n      if ( entity.stateCmdSuffix != undefined )\n           this.state_cmd_suffix = entity.state_cmd_suffix;\n      if ( entity.stateChangeResponseTime != undefined )\n      {\n           this.stateChangeResponseTimeHasBeenUpdated = true;\n           this.stateChangeResponseTime = entity.stateChangeResponseTime;\n      }\n      if ( entity.statusMsg != undefined )\n           this.statusMsg = entity.statusMsg;\n      if ( entity.timeout != undefined )\n           this.timeout = entity.timeout;\n   }\n\n}\n\nmodule.exports = HV;\n"
  },
  {
    "path": "utils/Logger.js",
    "content": "\"use strict\";\nvar __importDefault = (this && this.__importDefault) || function ( mod ) {\n    return (mod && mod.__esModule) ? mod : { \"default\": mod };\n};\n\nconst settings = require( \"../cmd4Settings\" );\n\nconst util_1 = __importDefault( require( \"util\" ) );\nconst chalk_1 = __importDefault( require( \"chalk\" ) );\n//\n// Log levels to indicate importance of the logged message.\n// Every level corresponds to a certain color.\n//\n// - INFO: no color\n// - WARN: yellow\n// - ERROR: red\n// - DEBUG: gray\n//\n\n//\n// Gets the prefix\n// @param prefix\n//\nfunction getLogPrefix( prefix )\n{\n    return chalk_1.default.cyan( `[${prefix}]` );\n}\n\n//\n// Logger class\n//\nclass Logger\n{\n   constructor( )\n   {\n      // Note: log.info goes to logBuf\n      this.logLineCount = 0;\n      this.logBuf = \"\";\n      // Note: log.warn goes to errBuf\n      this.errLineCount = 0;\n      this.errBuf = \"\";\n\n      this.outputEnabled = true;\n      this.bufferEnabled = false;\n      this.debugEnabled = false;\n\n      // Added as was set outside the class\n      this.timestampEnabled = true;\n      this.prefix = settings.PLATFORM_NAME;\n      this.forceColor( );\n   }\n   //\n   // Turns on debug level logging. Off by default.\n   //\n   // @param enabled { boolean }\n   //\n   setDebugEnabled( enabled = true )\n   {\n      this.debugEnabled = enabled;\n      settings.cmd4Dbg = enabled;\n   }\n   setOutputEnabled( enabled = true )\n   {\n      this.outputEnabled = enabled;\n   }\n   //\n   // Turns on buffered logging. Off by default.\n   //\n   // @param enabled { boolean }\n   //\n   setBufferEnabled( enabled = true )\n   {\n      this.bufferEnabled = enabled;\n   }\n   //\n   // Turns on inclusion of timestamps in log messages. On by default.\n   //\n   // @param enabled { boolean }\n   //\n   setTimestampEnabled( enabled = true )\n   {\n      this.timestampEnabled = enabled;\n   }\n   //\n   // Forces color in logging output, even if it seems like color is unsupported.\n   //\n   forceColor( )\n   {\n      chalk_1.default.level = 1; // `1` - Basic 16 colors support.\n   }\n   info( message, ...parameters )\n   {\n      this.log( \"info\" /* INFO */, message, ...parameters );\n   }\n   warn( message, ...parameters )\n   {\n      this.log( \"warn\" /* WARN */, message, ...parameters );\n   }\n   error( message, ...parameters )\n   {\n      this.log( \"error\" /* ERROR */, message, ...parameters );\n   }\n   debug( message, ...parameters )\n   {\n      if ( this.debugEnabled )\n         this.log( \"debug\" /* DEBUG */, message, ...parameters );\n   }\n   log( level, message, ...parameters )\n   {\n      if ( level === \"debug\" /* DEBUG */ && ! this.debugEnabled )\n      {\n         return;\n      }\n      message = util_1.default.format( message, ...parameters );\n      switch ( level )\n      {\n         case \"warn\":\n             message = chalk_1.default.yellow( message );\n             break;\n         case \"error\":\n             message = chalk_1.default.red( message );\n             break;\n         case \"debug\":\n             message = chalk_1.default.gray( message );\n             break;\n      }\n      if ( this.prefix )\n      {\n         message = getLogPrefix( this.prefix ) + \" \" + message;\n      }\n      if ( this.timestampEnabled )\n      {\n         const date = new Date();\n         message = chalk_1.default.white( `[${date.toLocaleString()}] ` ) + message;\n      }\n      switch ( level )\n      {\n         // Homebridge puts warninggs to errorbuf, so do the same.\n         case \"error\":\n         case \"warn\":\n           if ( this.bufferEnabled == true )\n           {\n              this.errLineCount++;\n              this.errBuf += message;\n              this.errBuf += \"\\n\";\n           }\n           if ( this.outputEnabled == true )\n              console.log( message );\n           break;\n         case \"debug\":\n         case \"info\":\n         default:\n           if ( this.bufferEnabled == true )\n           {\n              this.logLineCount++;\n              this.logBuf += message;\n              this.logBuf += \"\\n\";\n           }\n           if ( this.outputEnabled == true )\n              console.log( message );\n      }\n\n   }\n   reset()\n   {\n      this.logLineCount = 0;\n      this.logBuf = \"\";\n      this.errLineCount = 0;\n      this.errBuf = \"\";\n   }\n}\nmodule.exports=Logger;\n"
  },
  {
    "path": "utils/VariableTimer.js",
    "content": "'use strict';\n\n/* Orig\nvar variableTimer = {\n    running: false,\n    iv: 5000,\n    timeout: false,\n    cb : function(){},\n    start : function(cb,iv){\n        var elm = this;\n        clearInterval(this.timeout);\n        this.running = true;\n        if(cb) this.cb = cb;\n        if(iv) this.iv = iv;\n        this.timeout = setTimeout(function(){elm.execute(elm)}, this.iv);\n    },\n    execute : function(e){\n        if(!e.running) return false;\n        e.cb();\n        e.start();\n    },\n    stop : function(){\n        this.running = false;\n    },\n    set_interval : function(iv){\n        clearInterval(this.timeout);\n        this.start(false, iv);\n    }\n};\n*/\n\n// Taken from https://stackoverflow.com/questions/1280263/changing-the-interval-of-setinterval-while-its-running\n//\n// timer.start(function(){\n//     console.debug('go');\n// }, 2000);\n//\n// timer.set_interval(500);\n//\n// timer.stop();\n//\n\nclass VariableTimer\n{\n   constructor ()\n   {\n      this.running = false;\n      this.iv = 0;\n      this.timeout = false;\n      this.cb = function( ){ };\n   }\n   start( cb , iv )\n   {\n      var elm = this;\n      clearInterval( this.timeout );\n      this.running = true;\n      if ( cb ) this.cb = cb;\n      if ( iv ) this.iv = iv;\n      this.timeout = setTimeout( function( ){ elm.execute( elm ) }, this.iv );\n   }\n\n   execute( e )\n   {\n      if ( ! e.running ) return false;\n      e.cb( );\n      e.start( );\n   }\n\n   stop( )\n   {\n       this.running = false;\n   }\n\n   set_interval( iv )\n   {\n      // You can't change an interval when timer is not running\n      if ( this.running == false )\n      {\n         this.iv = iv;\n         return;\n      }\n\n      // Do not change interval if less than .5 seconds difference\n      let round = Math.trunc( iv / 500) * 500;\n      if (round !=  this.iv )\n      {\n         clearInterval( this.timeout );\n         this.start( false, round );\n      }\n   }\n}\n\n//module.exports.VariableTimer = VariableTimer;\nmodule.exports = VariableTimer;\n"
  },
  {
    "path": "utils/createAccessorysInformationService.js",
    "content": "'use strict';\n\nmodule.exports = function createAccessorysInformationService( accessory )\n{\n   // Standalone accessories do not have platforms\n   if ( accessory.platform )\n   {\n      // Platform accessories may already have information sercices if\n      // they are restored from cache by Homebridge.\n      let informationService = accessory.platform.getService( accessory.api.hap.Service.AccessoryInformation )\n      if ( informationService )\n      {\n         accessory.log.debug( `Using Existing ( cached ) accessory information service for: ${ accessory.displayName }` );\n         accessory.informationService = informationService;\n      }\n   }\n\n   if ( ! accessory.informationService )\n   {\n      accessory.log.debug( `Creating new accessory information service for: ${ accessory.displayName }` );\n\n      // Create accessory's Information Service\n      accessory.informationService = new accessory.api.hap.Service.AccessoryInformation( );\n   }\n\n\n   // Add/update the Model characteristic, if it is defined.\n   if ( accessory.model )\n      accessory.informationService\n         .setCharacteristic( accessory.api.hap.Characteristic.Model, accessory.model );\n\n   // Add/update the Manufacturer characteristic, if it is defined.\n   if ( accessory.manufacturer )\n      accessory.informationService\n         .setCharacteristic( accessory.api.hap.Characteristic.Manufacturer, accessory.manufacturer );\n\n   // Add/update the serialNumber characteristic, if it is defined.\n   if ( accessory.serialNumber )\n      accessory.informationService\n         .setCharacteristic( accessory.api.hap.Characteristic.SerialNumber, accessory.serialNumber );\n\n   if ( accessory.services )\n      accessory.services.push( accessory.informationService );\n}\n"
  },
  {
    "path": "utils/extractKeyValue.js",
    "content": "'use strict';\n\n// Description:\n//    Extracts a key from an object given a value.\n//\n// @param obj - The object to get the key from.\n// @param value - The value to find.\n//\n// @returns key or undefined\n//\n\nvar extractKeyValue = function (obj, value) {\n    return Object.keys(obj)[Object.values(obj).indexOf(value)];\n}\n\nmodule.exports = extractKeyValue;\n"
  },
  {
    "path": "utils/getAccessoryNameFunctions.js",
    "content": "'use strict';\n\n// Description:\n//    Routines of which given an Accessory Config. Extract the Accessory Name based on\n//    either it's displayName or name key values.\n//\n// @param config - The Accessories json config.\n//\n// @returns name as a string or dies as all accessories must have a name\n//\n\nvar getAccessoryName = function ( config )\n{\n   if ( config.name ) return config.name;\n   if ( config.Name ) return config.Name;\n   if ( config.displayName ) return config.displayName;\n   if ( config.DisplayName ) return config.DisplayName;\n\n   throw new Error( \"You must have a 'Name' per accessory.\" );\n}\n\nvar getAccessoryDisplayName = function ( config )\n{\n   if ( config.displayName ) return config.displayName;\n   if ( config.DisplayName ) return config.DisplayName;\n\n   if ( config.name ) return config.name;\n   if ( config.Name ) return config.Name;\n\n   throw new Error( \"You must either, 'displayName' and or 'name' per accessory.\" );\n}\n\nmodule.exports = { getAccessoryName,\n                   getAccessoryDisplayName\n                 };\n"
  },
  {
    "path": "utils/getAccessoryUUID.js",
    "content": "'use strict';\n\n// Description:\n//    Get or create a Accessories UUID based on what it is configured as.\n//\n// @param config - The accessories config information.\n// @param UUIDGen - api.hap.uuid\n//\n// @returns - UUID or exits as all Accessories must have a name or displayName.\n//\n// Note: This follows the getAccessoryName logic of getting the Accessories name.\n\nvar getAccessoryUUID = function ( config, UUIDGen )\n{\n   if ( config.UUID )\n      return config.UUID;\n   if ( config.uuid )\n      return config.uuid;\n\n   if ( config.name )\n      return UUIDGen.generate( config.name );\n\n   if ( config.Name )\n      return UUIDGen.generate( config.Name );\n\n   if ( config.displayName )\n      return UUIDGen.generate( config.displayName );\n\n   if ( config.DisplayName )\n      return UUIDGen.generate( config.DisplayName );\n\n   throw new Error( \"You must either, 'displayName' and or 'name' per accessory.\" );\n}\n\nmodule.exports = getAccessoryUUID;\n"
  },
  {
    "path": "utils/indexOfEnum.js",
    "content": "'use strict';\n\n\n// Description:\n//    Create an Object prototype to for getting an index of an enumerated type.\n//\n\nmodule.exports=Object.defineProperty(Object.prototype, \"indexOfEnum\", {\n   value: function( predicate, fromIndex ) {\n      let length = this == null ? 0 : Object.keys( this ).length;\n      if ( !length )\n         return -1;\n\n      let index = fromIndex == null ? 0 : fromIndex;\n      if ( index < 0 )\n      {\n         index = Math.max( length + index, 0 );\n      }\n\n      for ( let i=index; i < length; i++)\n      {\n         if ( predicate( this[ i ], i, this ) )\n         {\n            return i;\n         }\n      }\n      return -1;\n    }\n});\n"
  },
  {
    "path": "utils/indexOfEnumLintTest.js",
    "content": "'use strict';\n\n// This is not a utility. This is a testcase, but not a Unit test either.\n// Lint had picked up an error that indexOfEnum was set, but not used; though\n// the function worked perfectly as proven by unit testing.\n// What I had found is that without the Object.defineProperty within the\n// requiring code, like this one, lint would fail.\n//\n// This test is placed here, just to remember that reason.\n\n\nvar HomebridgeAPI = require( \"../node_modules/homebridge/lib/api\" ).HomebridgeAPI;\nvar _api = new HomebridgeAPI( ); // object we feed to Plugins\n\n\n\nvar { indexOfEnum } = require( \"../utils/indexOfEnum\" );\n\nObject.defineProperty(exports, \"indexOfEnum\", { enumerable: true, get: function () { return indexOfEnum.indexOfEnum; } });\n\nlet ACC_DATA = require('../lib/CMD4_ACC_TYPE_ENUM');\nlet DEVICE_DATA = require('../lib/CMD4_DEVICE_TYPE_ENUM');\n\nlet CMD4_ACC_TYPE_ENUM = ACC_DATA.init( _api.hap.Characteristic );\nlet CMD4_DEVICE_TYPE_ENUM = DEVICE_DATA.init( CMD4_ACC_TYPE_ENUM, _api.hap.Service, _api.hap.Characteristic, _api.hap.Categories );\n\n\nlet i=0;\nlet j = 63;\nlet type;\nlet ucKeyIndex;\n\ntype = CMD4_DEVICE_TYPE_ENUM.properties[ j ].deviceName;\nconsole.log(\"checking type:\" + type );\n\n\nucKeyIndex = CMD4_DEVICE_TYPE_ENUM.properties.indexOfEnum( i => i.deviceName === type);\nif ( ucKeyIndex < 0 )\n{\n   console.log(\"FAIL: Invalid device type:%s\", type );\n} else {\n   console.log(\"PASS (:%s) %s = %s\", type, i, ucKeyIndex );\n}\n\ntype=\"blah\";\nconsole.log(\"checking type:\" + type );\n\n\nucKeyIndex = CMD4_DEVICE_TYPE_ENUM.properties.indexOfEnum( i => i.deviceName === type);\nif ( ucKeyIndex < 0 )\n{\n   console.log(\"PASS: Invalid device type:%s\", type );\n} else {\n   console.log(\"FAIL: (%s) %s = %s\", type, i, ucKeyIndex );\n}\n"
  },
  {
    "path": "utils/isAccDirective.js",
    "content": "'use strict';\n\nlet CMD4_ACC_TYPE_ENUM = require( \"../lib/CMD4_ACC_TYPE_ENUM\" ).CMD4_ACC_TYPE_ENUM;\n\n\n// Description:\n//    Determine if parameter is a Cmd4 accessory characteristic\n//\n// @param type - The characteristic type to check. i.e. \"On\"\n// @param allowUpper - if upper case allowed to be checked.\n// @returns: { type: The CORRECT characteristic type\n//             accTypeEnumIndex: The index of the characteristic\n//           } or null\n//\n\nfunction isAccDirective( type, allowUpper = false )\n{\n   // For backward compatability of testStoredValueForIndex of FakeGato\n   // we must return a null accTypeIndex, which should be checked instead\n   // of just rc.\n   let defaultRc = { \"type\": type,\n                     \"accTypeEnumIndex\": null\n                   };\n\n   if ( ! type )\n   {\n      console.warn( \"No parameter passed to isCmd4Directive\" );\n      return defaultRc;\n   }\n\n   let accTypeEnumIndex;\n\n   // We want lower case to be correct\n   accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.sche === type )\n   if ( accTypeEnumIndex >= 0 )\n      return { \"type\": type,\n               \"accTypeEnumIndex\": accTypeEnumIndex };\n\n   // Note: There are othes like WiFi ... but nobody uses them thankfully !\n   if ( allowUpper == true )\n   {\n       accTypeEnumIndex = CMD4_ACC_TYPE_ENUM.properties.indexOfEnum( i => i.type === type );\n\n      // We return the correct lower case\n      if ( accTypeEnumIndex >= 0 )\n         return { \"type\": CMD4_ACC_TYPE_ENUM.properties[ accTypeEnumIndex ].sche,\n                  \"accTypeEnumIndex\": accTypeEnumIndex };\n   }\n\n   return defaultRc;\n}\n\n\nmodule.exports = isAccDirective;\n"
  },
  {
    "path": "utils/isCmd4Directive.js",
    "content": "'use strict';\n\nconst constants = require( \"../cmd4Constants\" );\nconst lcFirst = require( \"./lcFirst\" );\n\n\n// Description:\n//    Determine if parameter is a Cmd4 directive based on it being\n//    in the cmd4Constants.\n//\n// @param directive - The Cmd4 Directive to check\n// @param allowUpper - if upper case allowed to be checked.\n// @returns: { key: The CORRECT directive\n//             wasLower: If the directive was lowered to make it correct.\n//           } or null\n\n\nfunction isCmd4Directive( directive, allowUpper = false )\n{\n   if ( ! directive )\n   {\n      console.warn( \"No parameter passed to isCmd4Directive\" );\n      return null;\n   }\n\n   if ( Object.values( constants ).indexOf( directive ) >= 0 )\n   {\n      //console.log(\"isCmd4Directive directive: %s returning: %s\", directive, directive );\n      return { key:      directive,\n               wasLower: true };\n   }\n\n   if ( directive == \"UUID\" )\n      return { key:      \"uuid\",\n               wasLower:  false };\n\n   // Note: There are othes like WiFi ... but nobody uses them thankfully !\n   if ( allowUpper == true )\n   {\n\n      let lcDirective = lcFirst( directive );\n      if ( Object.values( constants ).indexOf( lcDirective ) >= 0 )\n      {\n         //console.log(\"isCmd4Directive directive: %s returning: %s\", directive, lcDirective );\n         return { key:      lcDirective,\n                  wasLower: false };\n      }\n   }\n\n   //console.log(\"isCmd4Directive directive: %s returning null\", directive );\n\n   return null;\n}\n\n\nmodule.exports = isCmd4Directive;\n"
  },
  {
    "path": "utils/isDevDirective.js",
    "content": "'use strict';\n\nlet ucFirst = require( \"../utils/ucFirst\" );\n\n\nlet CMD4_DEVICE_TYPE_ENUM = require( \"../lib/CMD4_DEVICE_TYPE_ENUM\" ).CMD4_DEVICE_TYPE_ENUM;\n\n\n// Description:\n//    Determine if type is a Cmd4 device based CMD4_DEVICE_TYPE_ENUM.deviceName\n//\n// @param deviceName - The device name to check. i.e. \"Switch\"\n// @param allowUpper - if upper case allowed to be checked.\n// @returns: { deviceName: The CORRECT device name\n//             devEnumIndex: The index of the characteristic\n//           } or null\n\n\nfunction isDevDirective( deviceName, allowUpper = false )\n{\n   // We return similiar to isAccDirective\n   // We must return a null devTypeIndex, which should be checked instead\n   // of just rc, like isAccDirective\n   let defaultRc = { \"deviceName\": deviceName,\n                     \"devEnumIndex\": null\n                   };\n\n   if ( ! deviceName )\n   {\n      console.warn( \"No parameter passed to isDevDirective\" );\n      return defaultRc;\n   }\n\n   let devEnumIndex;\n\n   // We want lower case to be correct\n   devEnumIndex = CMD4_DEVICE_TYPE_ENUM.indexOfEnum( deviceName );\n   if ( devEnumIndex >= 0 )\n      return { \"deviceName\": deviceName,\n               \"devEnumIndex\": devEnumIndex };\n\n   // Note: There are othes like WiFi ... but nobody uses them thankfully !\n   if ( allowUpper == true )\n   {\n      let ucDeviceName = ucFirst( deviceName );\n      devEnumIndex = CMD4_DEVICE_TYPE_ENUM.indexOfEnum( ucDeviceName );\n\n      // We return the correct upper case\n      if ( devEnumIndex >= 0 )\n         return { \"deviceName\": CMD4_DEVICE_TYPE_ENUM.devEnumIndexToC( devEnumIndex ),\n                  \"devEnumIndex\": devEnumIndex };\n   }\n\n   return defaultRc;\n}\n\n\nmodule.exports = isDevDirective;\n"
  },
  {
    "path": "utils/isJSON.js",
    "content": "'use strict';\n\n// Description:\n//    Determine if parameter is a true JSON object, not an array, but {}\n//\n// @param m - JSON Object to check.\n// @returns: boolean\n\nfunction isJSON( m )\n{\n   if ( ! m )\n   {\n      console.warn( \"No parameter passed to isJSON\" );\n      return false;\n   }\n\n   if ( ! m.constructor )\n   {\n      //console.warn( \"No constructor to isJSON for parameter: %s\", m );\n      return false;\n   }\n\n   if ( m.constructor === Array )\n   {\n      //console.warn( \"It is an array\" );\n      return false;\n   }\n\n   if ( typeof m == \"object\" )\n   {\n      try{ m = JSON.stringify( m ); }\n      catch( err ) { return false; } }\n\n   if ( typeof m == \"string\")\n   {\n      try{ m = JSON.parse( m ); }\n      catch ( err ) { return false; } }\n\n   if ( typeof m != \"object\") { return false; }\n\n   return true;\n}\n\n\nmodule.exports = isJSON;\n"
  },
  {
    "path": "utils/isNumeric.js",
    "content": "'use strict';\n\n// Description:\n//    Determine if a given parameter is numeric.\n//\n// @param num - The number to determine if it is actually numeric.\n// @returns: boolean\n//\n\nvar isNumeric = function( num )\n{\n   num = \"\" + num; // coerce num to be a string\n   return !isNaN( num ) && !isNaN( parseFloat( num ) );\n}\n\nmodule.exports = isNumeric;\n"
  },
  {
    "path": "utils/lcFirst.js",
    "content": "'use strict';\n\n// Description:\n//    Convert the first character of a string to lower case.\n//\n// @param string - The string to convert.\n//\n// @returns: The string with the first letter lower cased.\n//\n//\nvar lcFirst = function( string )\n{\n   switch( typeof string )\n   {\n      case undefined:\n\n         console.log( \"Asked to lower case first character of NULL String\" );\n         return undefined;\n\n      case \"boolean\":\n      case \"number\":\n         return string;\n      case \"string\":\n         return string.charAt( 0 ).toLowerCase() + string.slice( 1 );\n      default:\n         console.log( \"Asked to lower case first character of non String(%s):%s\", typeof string, string );\n         return string;\n   }\n}\n\nmodule.exports = lcFirst;\n"
  },
  {
    "path": "utils/transposeCMD4Props.js",
    "content": "'use strict';\n\n// Description:\n//    Routines to convert Cmd4 values to constants and back.\n//\n// @param CMD4_ACC_TYPE_ENUM - Just that\n// @param accTypeEnumIndex - The Accessory Type Enumerated index.\n// @param constantString - The string to change into a HAP value.\n// @param constantValue - The value to change into a HAP String.\n//\n// @returns Value of transposition or nothing.\n//\n\nvar extractKeyValue = function( obj, value )\n{\n   for ( let key in obj )\n   {\n      // In case value given is a string, compare that as well.\n      if ( obj[ key ] == value || obj[ key ] + \"\" == value )\n         return key;\n   }\n   return undefined;\n}\n\n// Used to convet ValidValus from a Constant to their corresponding value.\nvar transposeConstantToValidValue = function ( CMD4_ENUM_properties_obj, accTypeEnumIndex, constantString )\n{\n   if ( Object.keys( CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues ).length <= 0 )\n   {\n      // Return the original as it should be used instead of nothing\n      // This is not a failure\n      //return { \"value\": constantString, \"rc\": true, \"msg\": `Non Convertible characteristic ${ constantString } for ${ CMD4_ENUM_properties_obj[ accTypeEnumIndex ].type }` };\n      return constantString;\n   }\n\n   // In case constantString is not a string, ie false\n   let lookupString = \"\" + constantString;\n   let ucConstantString = lookupString.toUpperCase();\n\n   if ( Object.prototype.hasOwnProperty.call( CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues, ucConstantString ) )\n   {\n      // let value = CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues[ ucConstantString ];\n      return CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues[ ucConstantString ];\n\n      //return { \"value\": value, \"rc\": true, \"msg\": \"Transpose success\" };\n   }\n\n   // What if it is already transposed correctly?\n   // let constant = extractKeyValue( CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues, constantString );\n   // if ( constant == undefined || constant == null )\n   //     return { \"value\": constantString, \"rc\": false, \"msg\": `Cannot convert ${ constantString } to a value for ${ CMD4_ENUM_properties_obj[ accTypeEnumIndex ].type }` };\n   //else\n   //   return { \"value\": constantString, \"rc\": true, \"msg\": \"Already transposed\" };\n   return constantString;\n}\n\n// Used to convet ValidValues Value to its corresponding Constant.\nvar transposeValueToValidConstant = function ( CMD4_ENUM_properties_obj, accTypeEnumIndex, valueString )\n{\n   if ( Object.keys( CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues ).length <= 0)\n   {\n      // Return the original as it should be used instead of nothing\n      // This is not a failure\n      //return { \"value\": valueString, \"rc\": true, \"msg\": `Non Convertible characteristic ${ valueString } for ${ CMD4_ENUM_properties_obj[ accTypeEnumIndex ].type }` };\n      return valueString;\n   }\n\n   let constant = extractKeyValue( CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues, valueString );\n\n   if ( constant == undefined || constant == null )\n   {\n      // What if it is already transposed correctly?\n      //let value = CMD4_ENUM_properties_obj[ accTypeEnumIndex ].validValues[ valueString ];\n      //if ( value == undefined || value == null )\n      //   return { \"value\": valueString, \"rc\": false, \"msg\": `Cannot convert ${ valueString } to a constant for ${ CMD4_ENUM_properties_obj[ accTypeEnumIndex ].type }` };\n      //else\n      //   return { \"value\": valueString, \"rc\": true, \"msg\": \"Already transposed\" };\n\n      return valueString;\n   }\n\n   // return { \"value\": constant, \"rc\": true, \"msg\": \"Transpose success\" };\n   return constant;\n}\n\n// SendValue does not send true/false for historical reasons\nvar transposeBoolToValue  = function ( valueString )\n{\n   if ( valueString == true )\n      return 1;\n   if ( valueString == false )\n      return 0;\n\n   return valueString;\n}\n\nmodule.exports = {\n   transposeConstantToValidValue,\n   transposeValueToValidConstant,\n   transposeBoolToValue,\n   extractKeyValue\n};\n"
  },
  {
    "path": "utils/trueTypeOf.js",
    "content": "'use strict';\n\n// Description:\n//    Determine the true type of an object, because typeOf is screwy\n//    for null/undefined.\n//\n//\n// NOTE: \"0\" or any qoted number is still a string.\n//       This function just fixes null/undefined.\n//       Use isNumeric if needed.\n//\n// @param m - type to check\n// @returns: Array, Boolean, Number, String, Object, null, undefined\n\nfunction trueTypeOf( m )\n{\n   switch( typeof m )\n   {\n      case \"boolean\":\n         return Boolean;\n      case \"number\":\n         return Number;\n      case \"string\":\n         // If the string is actually a number, let the caller\n         // deal with it as our intent is just to fix undefined\n         // and null issues.\n         return String;\n      case \"object\":\n         // null can be an object\n         if ( m == null )\n            return null;\n         if ( Array.isArray( m ) )\n            return Array;\n\n         return Object;\n      case \"undefined\":\n         return undefined;\n      default:\n         throw new Error(\"OOPS\");\n   }\n\n}\n\nmodule.exports = trueTypeOf;\n"
  },
  {
    "path": "utils/ucFirst.js",
    "content": "'use strict';\n\n// Description:\n//    Convert the first character of a string to upper case.\n//\n// @param string - The string to convert.\n//\n// @returns: The string with the first letter upper cased.\n//\n//\nvar ucFirst = function( string )\n{\n   switch( typeof string )\n   {\n      case undefined:\n\n         console.log( \"Asked to upper case first character of NULL String\" );\n         return undefined;\n\n      case \"boolean\":\n      case \"number\":\n         return string;\n      case \"string\":\n         return string.charAt( 0 ).toUpperCase() + string.slice( 1 );\n      default:\n         console.log( \"Asked to upper case first character of non String(%s):%s\", typeof string, string );\n         return string;\n   }\n}\n\nmodule.exports = ucFirst;\n"
  },
  {
    "path": "utils/versionChecker.js",
    "content": "'use strict';\n\n// These routines are used to get this packages\n// version information.\n// It not only uses Promises but creates Promises\n// and is documented as such.\n\nconst latestVersion = require( \"latest-version\" );\n\n// Retrieve the package information that contains\n// things like the current version.\nconst myPkg = require( \"../package.json\" );\n\n// Split the version into its sub components.\nfunction splitVersion( version )\n{\n   let parts = version.split( \".\" );\n   return { \"version\": parts[ 0 ], \"major\": parts[ 1 ], \"minor\": parts[ 2 ] };\n}\n\n// getLatestVersion could just be defined as:\n//     function getLatestVersion ( )\n// However, defining it this way signifies it\n// returns a Promise. In this case the Promise\n// given to us by latestVersion.\nconst getLatestVersion = async ( ) =>\n{\n   return latestVersion( myPkg.name );\n}\n\nfunction getPackagedVersion( )\n{\n   return myPkg.version;\n}\n\n// Check that there is a possible upgrade out there.\nfunction isVersionNewerThanPackagedVersion( version )\n{\n   // The default return code.\n   let rc = false;\n\n   // Split the version components into their sub components\n   let installedVersionInfo = splitVersion( myPkg.version );\n   let gitVersionInfo = splitVersion( version );\n\n   // Set the return code appropriately\n   if ( Number( gitVersionInfo.version ) > Number( installedVersionInfo.version ) )\n      return true;\n   if ( Number( gitVersionInfo.version ) < Number( installedVersionInfo.version ) )\n      return false;\n   if ( Number( gitVersionInfo.major ) > Number( installedVersionInfo.major ) )\n      return true;\n   if ( Number( gitVersionInfo.major ) < Number( installedVersionInfo.major ) )\n      return false;\n   if ( Number( gitVersionInfo.minor ) > Number( installedVersionInfo.minor ) )\n      return true;\n\n   return rc;\n}\n\n\n// Check that there is a possible upgrade out there.\nfunction isUpgrade( )\n{\n   // Create a new Promise that will be fufilled when we processed the\n   // information provided to us by the Promise of getLatestVersion.\n   // You cannot take an asynchronous call and convert it to a synchronous\n   // call unless you would create a timer and wait forever? for it\n   // to complete, which defeats the purpose of node.js.\n   return new Promise( ( resolve ) =>\n   {\n      // To use the promise of getLatestVersion, it must be in an async function\n      // so put it in one.\n      ( async( ) =>\n      {\n         // Wait for the Promise of getLatestVersion to complete\n         let lv = await getLatestVersion( );\n\n         resolve( isVersionNewerThanPackagedVersion( lv ) );\n      }\n      )( );\n   });\n}\n\n// Export the internal functions we wish to expose.\nmodule.exports = { isUpgrade, getLatestVersion, isVersionNewerThanPackagedVersion, getPackagedVersion };\n"
  }
]