Skip to content

Latest commit

 

History

History
475 lines (412 loc) · 20.6 KB

Developers.md

File metadata and controls

475 lines (412 loc) · 20.6 KB

Homebridges-cmd4 - Cmd4 Developers Guide.

Table of Contents

About CMD4 Developers Guide

    This document will help you understand what is needed to integrate your own scripts into Cmd4.

Where to begin

    Cmd4 comes with a fully populated and documented config.json file, this Developers Guide, an Advanced troubleshoting guide for you the script writer and finally some auto generated device and characteristic description documentation https://ztalbot2000.github.io/homebridge-cmd4.

    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.

Homebridge API

    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. This was everyone anyway and makes homebridge-ui easier to implement for Cmd4..

Platform Accessories

    An example Cmd4 Platform accessory for a Homebridge Television as described by: Homebridge Television is:

{
   "bridge":
   {
      "name": "MAC Test Homebridge",
      "username": "CC:22:3D:E3:CE:30",
      "port": 51826,
      "pin": "555-55-555"
   },
   "platforms" :
   [
      {
         "platform": "Cmd4",
         "debug":                          false,
         "outputConstants":                false,
         "accessories" :
         [
            {
              "type":                      "Television",
              "category":                  "TELEVISION",
              "publishExternally":         true,
              "name":                      "Example TV",
              "active":                    "ACTIVE",
              "activeIdentifier":           1,
              "configuredName":            "Example TV",
              "sleepDiscoveryMode":        "ALWAYS_DISCOVERABLE",
              "accessories":
              [
                 {   "type":                   "TelevisionSpeaker",
                     "displayName":            "My_TelevisionSpeaker",
                     "name":                   "My_TelevisionSpeaker",
                     "active":                 "ENABLED",
                     "volumeSelector":         10,
                     "volumeControlType":      "ABSOLUTE",
                     "state_cmd": "node .homebridge/YourScriptHere.js",
                     "polling": [
                        {"characteristic": "active",         "interval": 50,  "timeout": 5000},
                        {"characteristic": "volumeSelector", "interval": 50,  "timeout": 5000}
                     ]
                  }
              ],
              "LinkedTypes":
              [
                 {"type":                   "InputSource",
                  "displayName":            "HDMI1",
                  "configuredName":         "HDMI 1",
                  "currentVisibilityState": "SHOWN",
                  "inputSourceType":        "HDMI",
                  "isConfigured":           "CONFIGURED",
                  "identifier":              1,
                  "targetVisibilityState":    "SHOWN",
                  "name":                     "HDMI 1"
                 },
                 {"type":                    "InputSource",
                  "displayName":             "HDMI 2",
                   "configuredName":         "HDMI 2",
                   "currentVisibilityState": "SHOWN",
                   "inputSourceType":        "HDMI",
                   "isConfigured":           "CONFIGURED",
                   "identifier":              2,
                   "targetVisibilityState":   "SHOWN",
                   "name":                    "HDMI 2"
                  },
                  {"type":                    "InputSource",
                   "displayName":             "Netflix",
                   "configuredName":          "Netflix",
                   "currentVisibilityState":  "SHOWN",
                   "inputSourceType":         "HDMI",
                   "isConfigured":            "CONFIGURED",
                   "identifier":               3,
                   "targetVisibilityState":    "SHOWN",
                   "name":                     "Netflix"
                  }
               ],
               "displayOrder":              0,
               "currentMediaState":         "STOP",
               "targetMediaState":          "STOP",
               "pictureMode":               "STANDARD",
               "remoteKey":                 "SELECT",
               "polling": [
                  {"characteristic": "active",            "interval": 50,  "timeout": 5000},
                  {"characteristic": "activeIdentifier",  "interval": 50,  "timeout": 5000},
                  {"characteristic": "currentMediaState", "interval": 540, "timeout": 5000}
               ],
               "stateChangeResponseTime":    3,
               "state_cmd": "node .homebridge/YourScriptHere.js"
             }
          ]
       }
   ]
}

Television Accessories

   There are a few special Cmd4 designations for Televisions, implemented since Cmd4 3.0

  • The first is "category"
       "category": "TELEVISION"

    This is the hint to homekit of which icon to use and for Televisions, a TV icon will not show without it.

  • The second new designation is "publishExternally"
       "publishExternally": true (Default is false)

    As per the Homebridge API, this allows the Platform Accessory to be published separately from the bridge and is a requirement for multiple TV's.

See the Cmd4 Developers Guide for further information.

Cmd4 Directives

    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.

Cmd4 Devices and Characteristics

    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.

Priority Queued Polling

    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.

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.
The retries defaults to zero for "Get" commands from homebridge. You can alter this value as you like.
For Example of the default WoRm is:

"queueTypes": [ { "queue": "A", "queueType": "WoRm", "retries": 0 } ],
"accessories": [
{
   "interval": 5,
   "queue:    "A",
   "polling": [ { "characteristic": "currentTemperature"  },
                { "characteristic": "targetTemperature", "interval": 15 }
              ]
}

The interval of the characteristic is defined through the heirarch of the Platform/Accessory and then the Characteristic, as always.
Example 2:

"platforms":
 [ { "platform": "Cmd4",
     "interval": "10",
     "queueTypes: [ { "queue": "A" : "queueType": "WoRm" }
                    { "queue": "B" : "queueType": "Sequential" }
                    { "queue": "C" } // Defaults to "WoRm"
                  ],
     "accessories": [
     {
        "name": "My_Thermostat",
        "type": "Thermostatwitch",
        "interval": 15,
        "queue": "A",
        "polling": [ { "characteristic": "currentTemperature" },
                     { "characteristic": "targetTemperature" },
                     { "characteristic": "currentHeatingCoolingState", "interval": 25 }
                   ],
        ...
     },
     {
        "name": "My_Switch",
        "type": "Switch",
        "queue": "B",
        "polling": [ { "characteristic": "On" } ],
        ...
     },
     {
        "name": "My_Door",
        "type": "Door",
        "queue": "C",
        "polling": true,
        ...
     },
     {
        "name": "Switch2",
        "type": "Switch",
        "queue": "D", // Defaults to WoRm
        "polling": [ { "characteristic": "on" } ],
        ...
     }

Priority Queue Polling Across Multiple accessories ( Same Device )

    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:

    "platforms": [
        {
            "platform": "Cmd4",
            "debug": false,
            "outputConstants": false,
            "timeout": 4000,
            "stateChangeResponseTime": 3,
            "queueTypes:[ { "queue": "A", "queueType": "WoRm" } ],
            "accessories": [
                {
                    "type": "TemperatureSensor",
                    "subType": "tempSensor1",
                    "displayName": "LRoom",
                    "name": "LRoom",
                    "currentTemperature": 25,
                    "statusFault": "NO_FAULT",
                    "manufacturer": "Advantage Air Australia",
                    "model": "e-zone",
                    "serialNumber": "Fujitsu e-zone2",
                    "queue": "A",
                    "polling": [
                        { "characteristic": "currentTemperature" }
                    ],
                    "props": {
                        "currentTemperature": {
                            "maxValue": 100,
                            "minValue": -100,
                            "minStep": 0.1
                        }
                    },
                    "state_cmd": "bash /home/pi/zones.sh",
                    "state_cmd_suffix": "z01"
                },
                {
                    "type": "Switch",
                    "displayName": "TSwitch",
                    "name": "TSwitch",
                    "on": "FALSE",
                    "manufacturer": "Advantage Air Australia",
                    "model": "e-zone",
                    "serialNumber": "Fujitsu e-zone2",
                    "queue": "A",
                    "polling": [
                        { "characteristic": "On" }
                    ],
                    "state_cmd": "bash /home/pi/zones.sh",
                    "state_cmd_suffix": "z05"
                },
                {
                    "type": "Fan",
                    "on": "FALSE",
                    "displayName": "Fan",
                    "name": "Fan",
                    "manufacturer": "Advantage Air Australia",
                    "model": "e-zone",
                    "serialNumber": "Fujitsu e-zone2",
                    "queue": "A",
                    "polling": [
                        { "characteristic": "on" }
                    ],
                    "stateChangeResponseTime": 1,
                    "state_cmd": "bash /home/pi/ezone.sh"
                },
                {
                    "type": "Thermostat",
                    "displayName": "Aircon",
                    "name": "Aircon",
                    "currentHeatingCoolingState": "OFF",
                    "targetHeatingCoolingState": "OFF",
                    "currentTemperature": 25,
                    "targetTemperature": 25,
                    "temperatureDisplayUnits": "CELSIUS",
                    "manufacturer": "Advantage Air Australia",
                    "model": "e-zone",
                    "serialNumber": "Fujitsu e-zone2",
                    "queue": "A",  // All characteristics would go to queue "A"
                    "polling": [
                        { "characteristic": "currentHeatingCoolingState" },
                        { "characteristic": "targetHeatingCoolingState" },
                        { "characteristic": "currentTemperature" },
                        { "characteristic": "targetTemperature" }
                    ],
                    "state_cmd": "bash /home/pi/ezone.sh"
                }
            ]
        }
    ]
}

Developer Notes

Step 1. The provided jsmin differs from others

    The resulting file is still readable. Only C and C++ comments are removed. The included config.json is created via:

   *SHELL*> gcc jsmin.c -o jsmin
   *SHELL*> jsmin < config.min.json > config.json

Step 2. The parameters to the state_cmd

    These are defined as:

   Get < Accessory Name > < Characteristic >
   Set < Accessory Name > < Characteristic > < Value >

Step 3. Polling is supported

    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.

Step 4. Sending constants to your script.

    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.

Step 5. Changing characteristic properties.

    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:

    "platforms": [
        {
            "platform": "Cmd4",
            "debug": false,
            "outputConstants": false,
            "timeout": 4000,
            "stateChangeResponseTime": 3,
            "accessories": [
                {
                    "type": "Thermostat",
                    "displayName": "MyThermostat",
                    "name": "MyThermostat",
                    "currentTemperature": 25,
                    "targetTemperature": 25,
                    "props": {
                        "currentTemperature": {
                            "maxValue": 32,
                            "minValue": 16,
                            "minStep": 1
                        },
                        "targetTemperature": {
                            "maxValue": 32,
                            "minValue": 16,
                            "minStep": 1
                        }
                    }
                }
            ]
        }
    ]
}

Important     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.     Homebridge-cmd4 has always recognized either 0/1 or true/false when receiving the devices value. When in doubt, check the parameters yourself. Thanks Florian for pointing out the original documented bash script was incorrect

    Your now ready to go and try Fans, Switches, Garage Doors, Locks, Sensors ... ✅

Adding in Fakegato history

See fakegato-history

    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.

Step 1. Add fakegato config information

    Edit your homebridge/config.json file and add to the accessory config portion the following lines:

"fakegato":{"eve":"thermo",
            "currentTemp": "currentTemperature",
            "setTemp": "targetTemperature",
            "valvePosition": "0",
            "storage": "fs",
            "storagePath": ".homebridge/FakegatoStorage",
            "folder": "folderName",
            "keyPath": "/place/to/store/my/keys/"
           }

Step 2. Fakegato parameters

    If you notice, the parameters follow the fakegato-history spec.

The 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.

The value "0" should be used for any characteristics value which is not possible to retrieve.

Step 3. History requires polling

    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.

"polling": [{"characteristic": "currentHeatingCoolingState",
             "interval": 540,  "timeout": 4000},
            {"characteristic": "currentTemperature",
             "interval": 60,   "timeout": 4000}
           ],

Unit Testing

    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.

    Unit testing is only possible in a development environment and can be achieved in the following manner.

Step 1. Install homebridge-cmd4 in a local environment

    This is done separate from the global environment and does not impact the global environment.

   *SHELL*> npm install homebridge-cmd4

Step 2. Change to the homebridge-cmd4 directory

   *SHELL*> cd homebridge-cmd4

Step 3. Install homebridge-cmd4 development dependencies

   *SHELL*> npm install --dev

Step 4. Run the provided test cases

   *SHELL*> npm test

Note: 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.

License

See LICENSE