=====Plugin API: Talking To XTension=====
XTension will call into your script when there is a new action you need to send to a physical device, or when new data has been received on the serial or network port for you to handle. You will create commands in the form of Python dictionaries that contain all the necessary information to send to a unit and send those commands up to XTension.
====XTension Commands:====
XTension adds several commands to the python language for you to use in talking to XTension. Any constant that defines a dictionary key used to create commands to send to XTension or get data out of a dictionary sent to you from XTension will begin with a lower case “xt” for example “xtKeyAddress”\\
\\
Any XTension defined function will begin with an upper case XT for example “XTWriteLog”\\
\\
Both will then follow standard Camel Case. This is important as Python is a case sensitive language.\\
==XTWriteLog==
The equivalent of the AppleScript “write log” command. This writes a line to the XTension log in blue by default.
XTWriteLog( “this is an informational line from your plugin”)
the XTensionHelpers module defines several colors for additional logging:
XTWriteLog( “this is written in red”, xtColorRed)
XTWriteLog( “this is in black”, xtColorBlack)
XTWriteLog( “and lastly in green”, xtColorGreen)
if you wish to log in a custom color you can include it as an HTML color string as the last element of the write log commands parameters:
XTWriteLog( “this is in yellow!”, “FFAA00”)
you can include any number of parameters of different types and XTWriteLog will try to add them together as the python print command does. The caveat is that if you include more than 2 log elements the last parameter must be the color.
XTWriteLog( “the value was”, 15, “ and we replied with”, 45, xtColorBlack)
As a shortcut the function name “XTLog” is also set and can be used instead.\\
\\
Additionally the regular Print command is also sent to the log in blue, so if that is more convenient you can use the print command and it will also end up in the XTension log. The Print() command has the benefit of being able to provide human readable outputs for more complicated structures such as lists or dictionaries to see all the keys. You cannot pass those objects to the writeLog command as it only accepts strings. The print command can be very useful to see what you’re working with in it’s entirety for debugging.
==XTSendData==
Writes the passed data parameters to the currently open TCP port or Serial Port.
XTSendData( “hello=ON\r”)
you can send individual parameters as integers or string in a single send data command. If you send numbers they must be integers and in decimal form and range from 0 to 256. Each one will be converted to a byte before sending down the port.
XTSendData( “yes”, 12, 13, 10, “no”)
==XTStop==
Causes the plugin handler to quit and be re-started by XTension. Call if you cannot recover a valid connection in any other way. All plugin files and all data will be reloaded and the connection will be attempted again.
XTStop( “describe the reason for quitting")
The command takes a single parameter and that is optional. You can describe the reason why the interface is quitting if you wish and this reason will be logged to the XTension log before the interface quits and is restarted.
==XTReconnect==
Attempts to reconnect to the remove host without quitting and restarting. If the connection fails then the interface will be quit and restarted from scratch as if you had called XTStop. If the reconnection is successful then the interface helper app is not restarted. You should attempt this if a ping to your device fails or otherwise the connection goes down and you can no longer reach it. This makes the most sense for outgoing connections or Serial devices. If executed on an incoming connection the connection will be closed and it will begin listening on the incoming port again and wait for the device to re-stablish the connection. This command takes no parameters.
XTReconnect()
==XTMakeTimer==
Registers a function for a repeating or singular callback in a specific number of milliseconds. Since threading doesn’t work inside the python API properly if you need to do things regularly in your code you need to create timers. The call returns a reference to an opaque timer object. You need to keep a reference to this timer object in order for it to continue to function. To stop the timer set the returned timer object reference to nil or an empty set or a new timer object. At the moment only names of functions in the main plugin file can be stored and you cannot use class values or references. There is a tag value that you can set that will be returned when the timer handler is called so you can meter out multiple events that way if necessary. Parameters are:\\
\\
**mode** (XTension Constant value, can be: xtTimerModeOff, xtTimerModeSingle, xtTimerModeMultiple)\\
**interval** (integer value of milliseconds. 1000 milliseconds is 1 seconds. Very fast callbacks may cause performance issues, but you can still call back many times a second into short script handlers if you really need to do so)\\
**callback name** (string, the name of a handler to call back when the timer is up)\\
**tag** (integer or string, a value that will be passed as the first parameter to the timer handler)\\
\\
The callback function should take a single parameter which will be the tag value. If no tag value is specified in the XTMakeTimer call the tag value is still passed but it will be set to the string “timer” to let you know the method is being called by a timer.\\
\\
You can create any number of timers as necessary as long as you keep a reference to them alive in the script until you’re done with them.\\
global myTimer
myTimer = XTMakeTimer( xtTimerModeMultiple, 1000, “logEverySecond”, “some value of meaning to you or empty”)
def logEverySecond( theTagValue):
XTWriteLog( “a python timer has been called with the tag value: “ + theTagValue)
==XTSendCommand==
This is the main entry point for sending data up to XTension units. If you’ve received a change in value or state for a connected device you would create a command with the appropriate data and use this command to send it to XTension. All commands set up to XTension are in the form of Python dictionaries that will contain as many keyed values as necessary to describe the action. This is the same format that is received from XTension when a user or other action wishes to control a unit. Those events are described in the next section. The keys necessary are defined in the XTensionHelpers.py file.\\
\\
Every command must at least contain an xtKeyCommand key in the dictionary that describes the action. If you wish to send data that does not require an actual command you can use the xtCommandNoOp to fill the command value, but this must be present in every command.\\
\\
Every command sent to a unit must include that units **tag** as defined in the info.json file. It must also include the units address as entered in the edit unit dialog. \\
\\
Examples:\\
You have received an ON for a unit via the TCP connection and need to send that command to XTension:\\
workCommand = []
workCommand[ xtKeyTag] = ‘yourUnitTag’
workCommand[ xtKeyAddress] = ‘1234’
workCommand[ xtCommand] = xtCommandOn
XTSendCommand( workCommand)
To send an OFF command you would include the xtCommandOff command constant instead of the On one.\\
\\
To set the value of a unit use the xtCommandSetValue constant and also include a value tag. NOTE: All command values must be sent as strings so convert the value to a string before adding it to the command.\\
newUnitValue = 50
workCommand = []
workCommand[ xtKeyTag] = ‘yourUnitTag’
workCommand[ xtKeyAddress] = ‘1234’
workCommand[ xtCommand] = xtCommandSetValue
workCommand[ xtKeyValue] = str( newUnitValue)
XTSendCommand( workCommand)
There are other supported keys you can include with commands to describe more data or include more information with the new value or state. If you wish to update one of these keys for a unit without changing it’s state you can use the xtCommandNoOp as the command value, but a command must be present in the command.\\
\\
To add boolean flags use the xtTrue and xtFalse constants as the value for the key.\\
...
workCommand[ xtKeyUpdateOnly] = xtTrue
...
\\
* **xtKeyUpdateOnly** (boolean) When you first connect to a device and read out the values for the various units you’ll want to include this flag with that first command. When XTension receives a state or value change for a unit with this flag set it compares the new value or state against the one currently in it’s database. If the values are the same then no action is taken, if the state is different then the unit is updated and the ON or OFF scripts are run. If you are making regular measurements that might not change but you don’t wish to keep track of the current value in your script and compare yourself you can simply always set this key and XTension will take no action unless the value has changed. If you do not include this flag then the ON or OFF script will be run with each message reception even if the value or state has not changed. **NOTE** the [[xtension_manual:editunitadvancedtab|Advanced tab of the Edit Unit dialog]] now has a setting to log errors if no update for a unit has been received for some length of time. This is useful for things like temp sensors or other battery operated devices that might stop transmitting. If you wish to support this you should send every update to XTension with this flag set even if the value hasn’t changed. This will update the last message received date internal to the units database entry and be used to allow someone to know when that device stops transmitting. If you do not send every update this way then only on actual value or state changes is any date updated and XTension will not be able to properly manage that date checking.
* **xtKeyBatteryLevel** (integer 0-100) If the device type supports reporting a battery level you can include a percentage in this value. (remember to include it as a string, all command values must be strings, but do not include the % character, just an integer value from 0-100) If you include a battery level key then the battery can display in the unit flags column of the unit list will enable and give a graphical display of the remaining battery level. Battery levels below 10 will display as red and include the unit in any reports of low battery devices. If you wish to update a battery level for a unit without sending a state change or new value command you can use the xtCommandNoOp command and include this key.
* **xtKeyRate** (integer) if the script or user has specified a ramp rate in the on/off or set value command that value will be passed through the command with this key.
* **xtKeyPowerLevel** (integer) If your device has the ability to report signal strength or quality you can include this key with the value. The value will be available to the unit in it’s ON and OFF scripts via the “signal strength” verb if the user wishes to use it for reporting or graphing.
* **xtKeyNoScript** (boolean) If included and true then the unit will update it’s database values to the passed state or value, but will not run the unit on or off script.
* **xtKeyOnLabel** and **xtKeyOffLabel** (string) if it makes sense to display a text description of a value rather than a numerical one you can include one or both of these label strings in the command. The text you include will be displayed instead of the numerical value in all displays.
* **xtKeyColor** (string, html color string, 6 characters) if the unit receives a change in color or is controlled to a new color from XTension this value will be included containing the hex string value in standard html color notation. (RRGGBB)
* **xtKeyColorTemperature** (integer) if the device supports color temperature this value will be sent to you with commands to change it and you can include it in commands to change the displays in XTension to reflect a local change of value.
* **xtKeyTimestamp** (date) if not included in the command then XTension will set the last activity date of the unit to the current date at the moment it processes the command packet. This is normally close enough to not matter, but if you are receiving data from a source that might be significantly delayed you may wish to include this date in the command packet. This will override the current date and set the last activity date of the unit to the passed date. **NOTE** If you send dates in order, even if they are in the past, [[:xtdb|XTdb]] will store the new value at the passed date. XTdb will not add values that are before the most recent value it has logged so far though. So if you are loading historical data you should do it in date order or the values will not store in the XTdb database or show up in graphs or gauges. The XTension database will reflect the passed value and set the last activity date as available in displays or in scripts however.
* **xtKeyUnitPropertyName** and **xtKeyUnitPropertyValue** it is also possible to set as many as 10 [[dictionary:unitinformation:setunitproperty|Unit Property]] values inside a command. If there are other values or info that would be useful to have available in XTension you can add them here. For example I use this to set values for the Vera device category and subcategory which can be useful to know and be able to see in XTension for debugging purposes. Using these keys is more complicated than any others as you must append an index number to them. They can be xtKeyUnitPropertyName + “0” through “9” added to the end of them. You must include the same number of Names as Values and they must be in order. The parsing routine will stop reading them out if it encounters a gap in the numbering.
workCommand[ xtKeyUnitPropertyName + ‘0'] = ‘category'
workCommand[ xtKeyUnitPropertyValue + ‘0’] = ‘door sensor’
===Sending Errors===
If the unit is no longer responding or there has been some other error that should be reported at the unit you can include that via the error keys. If you wish to send an error to a unit without sending a change or update to it’s state or value you can use the xtCommandNoOp key for the command value, but a command must always be present in a command.
* **xtKeyCommError** (integer) include this in any command to an XTension unit and that unit will then display the Alert icon next to it’s name in all XTension displays. Set the value to a non-zero number to set an error or to 0 to clear an error. If setting to a non-zero value the Interface Error Script will be run with thisInterface and thisUnit set to this interface and unit for logging or dealing with it in a scriptable way. This value is also available from the unit via it’s properties in the scripting dictionary class xUnit. Additionally this also sets the last error date in the units class properties.
* **xtKeyErrorMessage** (string) text describing what the error actually was. This will be displayed in the help string that pops up when you hover over the alert icon and also be available via the xUnit’s applescript class properties. The text of the last error will be available via scripting even after the value has been set to 0.
===Supported Commands===
Here is a list of the currently supported command key values and the required keys associated with them. Any of the above keys can be included in any of these commands. These are the values for the required xtkeyCommand key into the command dictionary. Some are included only for commands received from XTension and have no meaning when sent to XTension. See the next section for more info on events you will receive from XTension. All commands that can be sent to or are received from a unit in XTension will include the xtKeyAddress and xtKeyTag keys.
==xtCommandNoOp==
When no changes to the unit value or state are desired but you wish to include one of the other optional keys.
==xtCommandBlink==
Received FROM XTension when a unit is issued the [[dictionary:unitcontrol:blink|blink command]]. Sending this command TO XTension will not do anything. When received the command dictionary will contain the xtKeyValue field which will be whatever string or numerical value was passed to the Blink verb.
==xtCommandGetUnitProperty==
Sent to XTension. requires xtKeyAddress and xtKeyTag. Include the name of the unit property you wish to retrieve with the xtKeyName key. XTension will respond asynchronously with an xtSetUnitProperty command, see below.
==xtCommandMessage==
Received from XTension. Will contain xtKeyData. This comes from the Send Message verb and will not contain a unit address or tag as it’s an interface level verb. This is a way to send string data to an interface. I use this to set the message fields in thermostats that can display some textual information on their screen.
==xtCommandOff==
Tells XTension that a unit is now off, or received from XTension to tell you that you should send whatever command is necessary to turn off the addressed unit. Will include xtKeyAddress and xtKeyTag.
==xtCommandOn==
Tells XTension that a unit is now on, or received from XTension to tell you that you should send whatever command is necessary to turn on the addressed unit. Will include xtKeyAddress and xtKeyTag.
==xtCommandPing==
You can send this command to get a response from XTension or if XTension hasn’t heard from you in a while it may send you this command to make sure you’re still connected. You can send an xtCommandPingResponse command back to update the last message date for your interface. You can generate xtCommandPingResponses regularly if you wish which XTension will use to keep the last message date for the interface updated and not have to ping you at all. If you fail to respond to a ping request in a reasonable amount of time XTension may restart your interface. **NOTE** not implemented in API version 1.
==xtCommandPingResponse==
Sent to XTension in response to the xtCommandPing command. After you’ve verified that you can still communicate with your device you can reply with this command or XTension will attempt to restart your connection.
==xtCommandQuery==
Received from XTension in response to the [[dictionary:unitinformation:queryof|Query]] verb. A script or a user is asking you to go out and get the current value of the unit. When you receive the new unit value changed or not you should respond with a normal update command sending either on/off or a value command for that unit. This will include xtKeyAddress and xtKeyTag
==xtCommandReboot==
Received from XTension in response to the “reset controller verb” if there is a way for you to restart your physical device or reset some default parameters you can do so in response to this command. This command will not contain xtKeyAddress or xtKeyTag as it’s an interface level command.
==xtCommandRemoveXMLData==
Sent to XTension. Requires xtKeyAddress, xtKeyTag and xtKeyName. This command will remove the xtKeyName value from the root dictionary of the unit. Please delete only root XML values that you added or that are part of your dynamic interface settings for the unit in question. Use the naming convention to make sure that you do not overwrite or remove any keys that belong to XTension.
==xtCommandSetDescription==
Sent to XTension. Requires xtKeyAddress, xtKeyTag and xtKeyData. The description of the unit is set to the string passed as xtKeyData and all displays are updated to reflect the new display. A good way to send some textual data beyond the on and off labels for a unit. Additionally a description can be displayed in interfaces or even parsed as HTML in interfaces and web interfaces. A good way to do a very customized display of the state or info from a device.
==xtCommandSetUnitOfMeasure==
Sent to XTension. Requires xtKeyAddress, xtKeyTag and xtKeyData. Will set the unit of measure, or value suffix, to the string in xtKeyData. Useful if the type of data being displayed can change at the device and you wish to automatically change it at the unit. You might wish to send °F or °C if the temperature format has been changed at the device for instance. This will overwrite any used entered value however and you should normally respect what they wish to display.
==xtCommandSetUnitProperty==
Similar to the xtKeyUnitPropertyName and Value keys that can be included in a separate command, this command will set a single unit property in a single command. It is sent to XTension and requires xtKeyAddress, xtKeyTag, xtKeyName and xtKeyValue. A unit property named from the xtKeyName value will be set to the string passed in the xtKeyValue value. It may also be received from XTension in response to an xtCommandGetunitProperty command.
==xtCommandSetValue==
Sent to and received from XTension. The command must include xtKeyAddress, xtKeyTag and xtKeyValue. Send to XTension to set the value of the unit to the passed xtKeyValue, if received from XTension then a user or a script has requested that you control your corresponding unit to the passed value.
==xtCommandSetXMLData==
Sent to XTension. requires xtKeyAddress, xtKeyTag, xtKeyName and xtKeyValue. A value with the passed name and the value of the passed value will be set in the root level of the addressed units dictionary. Please use the naming convention to make sure that you do not over write any XTension values for the unit.
==xtCommandSimmPacket==
received from XTension in response to the simulate packet verb. This is a debugging aid and can be used for testing any data or values that you would like to simulate as being received. This is not used normally by users. It will include the xtKeyData key with the data passed to the verb in XTension.
==xtCommandStop==
received from XTension, will include xtKeyAddress and xtKeyTag. Generated by the Stop verb. Currently only used for window shade controls who need a command other than up (on) and down (off) but you can use it for anything that makes sense.
==xtCommandUnitDeleted==
Received from XTension in response to a unit that is assigned to your interface being deleted by the user. Will include xtKeyAddress and xtKeyTag. There is no support for you to send a command to XTension to delete a unit.
PREVIOUS [[:plugins:04_interfaces|]] NEXT [[:plugins:06_events|]]