Table of Contents
Plugin API: info.json Defining Unit Types
The info.json file must also contain at least one unit type definition but may contain any number of extra unit types that your plugin can support. These unit types are the selections in the “Device” popup on the Edit Unit dialog. A single interface may support several different types of physical devices with different interface and addressing requirements.
It is important to understand the address space issues with different devices. Each unit in the XTension database must have a unique address path. This is made up from the unique ID of the interface instance, the address prefix which is the unique string you will define in the “tag” property for each unit type you define and then the address which is what the user enters into the Address field.
A good example is to think about X10 wireless devices and our W800 interface. There are 2 types of X10 wireless devices, “wireless” and “security” but they both have the same address space. Without being able to tell XTension which type was which the 2 address spaces would overlap in our index making it impossible to have both a wireless and a security device at address B1. With an address prefix tag defined we can have both a wireless and a security device at the same Address because the tag is different.
When commands are sent to the plugin they will include both the address and the tag associated with the device type so that you can take the proper action. Commands received by you and sent up to XTension must include both the device type tag and the address so that the proper unit to receive the command can be found.
In addition to the tags below you may specify 2 different dynamic interfaces for each device type. See the next section on interface setup for more info.
The device types are a JSON list containing multiple JSON dictionaries for each device type you’re setting up.
deviceTypes
Required: (json list) a list of the JSON data describing any unit types. If your plugin does not define any unit types say for a sharing only plugin then the list must be included but can be empty. Any plugin that provides a unit must include at least one unit type even if it’s just a generic “Register” so that the unit type plugin has something that can be selected and there is a unique address tag.
deviceTypes:[ {"name":"digital output", "tag":"out", "desc":"GPIO outputs on pins 1-7"} {"name":"motor speed", "tag":"speed"} {"name":"Alert LED", "tag":"alert", "allowColor":True} ]
Device Type Keys
Each device type dictionary may use the following keys to describe it’s behavior and interface:
name
REQUIRED: (string) the name of the device as displayed in the device type popup of the Edit Unit dialog.
tag
REQUIRED: (string) the short unique address prefix used to guarantee each device type it's own address space. Also used by the plugin to send the proper command for that device type regardless of the address.
desc
OPTIONAL: (string) a more descriptive string about the device to be displayed in the edit unit dialog if present.
allowColor
OPTIONAL: (boolean) defaults to false. If present and True the color controls will be offered when controlling this unit and color data will be sent with all the on and value commands.
allowColorTemp
OPTIONAL: (boolean) defaults to false. If present and True the color temperature controls will be offered when controlling this unit and color temperature data will be sent with all the on and value commands. NOTE: this is not yet implemented in XTension 9.3.1
address
OPTIONAL: (JSON list of strings or lists, see below) if your device has a reasonably limited number of potential device addresses you can include them here. When the “…” button next to the address field is clicked a menu will be opened to select from this list. The simplest form is just a list of strings:
address:["1", "2", "3”]
any of those strings can be another JSON list which allows you to include a description of the device or function of that address. The first item should be a string that is the address that will be filled into the address field, the second item is a string that is the description. In the popup menu the address will be included in parans followed by the description.
You can combine both individual string elements and list elements.
address:[ ["1", "PWM Channel 1"], ["2", "PWM Channel 2"], ["RATE", "Ramp Rate"], "3", “4" ]
would result in a menu that looked like:
(1) PWM Channel 1 (2) PWM Channel 2 (RATE) Ramp Rate 3 4
The user can always enter anything into the address field that they wish, choosing from the menu is a shortcut for simple devices and not a requirement that the entire address space be included in it to choose from.
dimmable
OPTIONAL: (boolean) Set to true if this unit type should default to dimmable when the user is creating new units.
“dimmable”:true
dimmableType
OPTIONAL: (string) a string describing the dimming behavior when the ON command is sent. The valid choices are “simple”, “smart” and “simulated”. Most modern units should be set to “simulated” This only applies to units with the dimmable flag set to true.
- simulated: in this case the last value the unit visited will be remembered by XTension and sent as a set value command instead of an On command. This is the normal behavior for most modern devices as you want them to return to the level they were last at when they are commanded On. A unit set to simulate will never receive an On command, but only setValue commands with the last On level already set from the XTension database.
- smart: legacy type for “smart” x10 devices. This will send a simple On command and assume the device itself knows what level to go to. This seems like it would be the choice for modern devices as most do remember their own last on level but it isn’t the best choice as the value in the XTension database may not match what the device does.
- simple: XTension will just send a simple On to the device when commanded on and the database will show a level of 100% after sending the on. This is a legacy setting for “dumb” devices that always go to full on when sent an On command.
“dimmableType”:”simulated”
receiveOnly
OPTIONAL: (boolean) If the unit can only receive values but should not get commands when the values are changed in XTension this flag should be set to true. For things like analog inputs or temperature sensors that can only receive values and for whom it makes no sense to try to send a new value to.
“receiveOnly”:true
ignoreClicks
OPTIONAL: (boolean) serves the dual purpose of making it harder to accidentally click on a control in the interface and changing the look of that interface. When set to false or absent a unit will provide by default a toggle control on a unit list. When set to true the paddle of that and all other control toggles will be absent so that you can’t click on it and the toggle background will instead just show the current value. Clicks on the toggle control will not cause any commands to be sent immediately but will instead bring up the detailed controls dialog. From there, or from scripts or events or other ways to control a unit the commands will be sent normally.
This should also be set to true for most receiveOnly units as you do not normally wish to provide a simple interface for controlling something when it cannot be controlled.
“ignoreClicks”:true
menuHandlers
OPTIONAL: (JSON List of lists) Sometimes a device may have other control commands that are not yet included in the applescript dictionary, or for which you'd like to present a simple interface to. Commands entered in this list will show at the top of the contextual menu for the item and also when the gear icon is clicked in either of the popup unit control windows. The value is a JSON list of lists, each embedded list should start with the display name you wish to have in the menu, followed by the actual command name that you want to have called in the script when the menu handler is selected. An optional 3rd entry may be included which will be passed to the script handler in the scriptData parameter as a tuple.
menuHandlers:[ ["Start Color Loop", "startColorLoop", [14, 55, 75]], ["End Color Loop", "endColorLoop"] ]
would add 2 menu entries “Start Color Loop” and “End Color Loop” and if selected a doScriptHandler command will be sent to the plugin. If you have registerd a handler for the handler name “startcolorLoop” then that handler will be called. You can create handlers either in the xtUnit objects or at the xtension level to have a single handler called regardless of the unit that was selected. See the using the plugin includes section for more info on registering callback handlers.
A script handler must have the following definition:
def startColorLoop( self, commandName, positionalParms, dataParms):
The commandName will be the handler name, in this case “startColorLoop” which does not have the be the same name as the actual handler since you can register any handler using that name as a key.
If the third list of values was present in the menuHandlers definition then the positionalParms will contain a tuple containing them. [14, 55, 75] in the above example.
The dataParms will include much more information including units address, tag, uniqueid and any other interface information available at the time of the call. It will contain at least these keys:
xtKeyAddress ("addr") The address of the unit xtKeyTag ("APfx") The tag or address prefix of the unit xtKeyUniqueID ("UnID") The unique ID string of the unit. xtKeyValue (“Valu”) The current value of the unit.
if this info isn't enough to send the command to the device you can use them via the XTGetUnitFromAddress or XTGetUnitFromId commands to get the entire dictionary of unit settings for the unit.
scriptHandlers
OPTIONAL: (JSON list of strings) You can further extend the scripting interface to the unit by listing special commands that can be called from scripting here. Note that in AppleScript it’s not actually necessary to define these here. Any script handler invoked by a user script that isn’t found as a command or handled by another script in the calling chain in XTension will be forwarded to the plugin. It may be added at some point in the future to validate these or to provide a type ahead interface to what is known to be available for that unit so you should supply them whenever possible.
scriptHandlers:[ "startColorLoop", "endColorLoop", "colorFlash", "setColorLoopSpeed”]
after defining them they can be called from any AppleScript in the application for the unit and will allow any number of parameters to be entered and passed such as:
tell xUnit "name of unit" to startColorLoop( 14, 55, 75)
The script handler is registered and executed in the same way as the above Menu Handler is. If any parameters are passed to the call they will be included in the positionalParms tuple but only parameters that can be coerced to strings will be forwarded on and all the parameters you receive will be in the form of strings. Complex structures like lists or records or object references cannot be passed to a plugin.
def startColorLoop( self, commandName, positionalParms, dataParms):
the command name is also supplied in case you might wish to supply a single callback handler for multiple scripting calls.
the dataParms would again have all the same data as is listed in the above menuHandler section.
In the next section we will review the creation of dynamic interfaces and using them for the edit interface window, the edit unit window and the 2 unit control dialogs.
PREVIOUS: Plugin API: info.json and Communication Settings NEXT: Plugin API: Dynamic Interfaces