Indigo Server Plugin Tutorial

Note most of the code examples below are calling methods on the object self. In this context, self is meant to be the Plugin instance as defined inside the plugin.py file. To execute the sample code outside of Plugin instance methods use the indigo.activePlugin object instead.

Important: For simplicity some of the samples below specify objects based on name (“office desk lamp”). However, the preferred lookup mechanism is to use the object's ID which can be retrieved by control-clicking on the object name in Indigo's Main Window. By using the ID you ensure the object will be found even if its name is changed.

Indigo Plugin SDK Source Code Examples

The Indigo Plugin SDK (available here) includes example plugins with full XML and python source. They are a great place to start when developing new plugins.

Included in the SDK are examples that create plugin based relay, dimmer, thermostat, and custom devices. Also included is an example showing basic Indigo database traversal, how to catch low-level X10/INSTEON messages, and how to create an Indigo telnet server using the python twisted framework.

We'll be adding additional example plugins in the future.

Other Useful Plugin Source Code Examples

Additionally, below is a table of common plugin tasks and built-in plugins that implement those tasks in some form or another (from simplest to most complex):

Plugin task Plugin that illustrates an approach
Parsing XML from an IP source NOAA Weather, WeatherSnoop
Integrating with native Mac Apps Airfoil
Sending RS232 (serial port & network serial port) Commands EasyDAQ
Reading RS232 (serial & network serial port) Input EasyDAQ
Interacting with an IMAP mail server iCal Alarm Processor
Creating custom devices with states Simple: NOAA Weather, WeatherSnoop - Complex: EasyDAQ, iTunes
Creating custom actions Growl, Action Collection
Creating custom events Airfoil

Each of these plugins is installed by default with Indigo 5 - in the /Library/Application Support/Perceptive Automation/Indigo 5/Plugins (Disabled)/ folder. To see the various XML and python source files, just right-click on it in the Finder and select Show Package Contents.

Both the SDK example plugins and the plugins included with Indigo above are great places to see working examples of plugins and their source code.

How to Read and Write Plugin Preferences

FIXME (useful, but very rough notes below)

  • Per plugin prefs file is automatically managed (created, loaded, updated).
  • Pref values can be numbers, boolean, strings, indigo.Dict() or indigo.List().
  • Key values defined in PluginConfig.xml are automatically mapped into the plugin's prefs space which is available via:
    self.pluginPrefs["somePrefKey"]

    or, if you're not sure the key exists:

    self.pluginPrefs.get("somePrefKey", "default value if key doesn't exist")

    The latter will return the second parameter if they key doesn't exist in the dictionary - it's your responsibility to add it to the prefs dict if you want it to be stored permanently.

  • Plugin can also insert other values into its pluginPrefs space (not just values shown in the plugin's config UI).
  • To read a preference value access its key:
    someVal = self.pluginPrefs["somePrefKey"]
    indigo.server.log("value is " + str(someVal))
  • To update a preference value assign it a new value:
    self.pluginPrefs["somePrefKey"] = 1234

How to Add Plugin Metadata to Devices, Trigger & Scheduled Events, Variables, etc.

FIXME (useful, but very rough notes below)

  • Most Indigo database objects support the addition of plugin specific metadata.
  • Every plugin has its own name space accessed via the object instance .pluginProps.
  • The pluginProps dictionary supports numbers, boolean, strings, indigo.Dict() or indigo.List().
  • Example adding new plugin metadata to the Device “den fixture”:
    dev = indigo.devices["den fixture"]
    newProps = dev.pluginProps
    newProps["onCycles"] = 5
    newProps["moreData1"] = "abc"
    newProps["moreData2"] = True
    newProps["moreData3"] = 123.45
    dev.replacePluginPropsOnServer(newProps)
  • Example reading the plugin specific property onCycles from the Device “den fixture”:
    dev = indigo.devices["den fixture"]
    onCycles = dev.pluginProps["onCycles"]
    indigo.server.log("onCycles is " + str(onCycles))
  • Example incrementing by 1 the plugin specific property onCycles for the Device “den fixture”:
    dev = indigo.devices["den fixture"]
    newProps = dev.pluginProps
    newProps["onCycles"] += 1
    dev.replacePluginPropsOnServer(newProps)
    
    dev = indigo.devices["den fixture"]
    onCycles = dev.pluginProps["onCycles"]
    indigo.server.log("onCycles is now " + str(onCycles))
  • Plugins have read-only access to other plugin metadata via .globalProps.
  • Plugins have read/write access to their own metadata space.

Creating a Custom Plugin Device

FIXME (useful, but very rough notes below)

  • Plugin Device state and properties are defined in Devices.xml.
  • Properties define the user configurable options for a device instance, and are specified in the <ConfigUI> XML node. Every field id is automatically mapped into the device instance .pluginProps metadata dictionary (described above) as a unique key.
  • States are specified in the Devices.xml <States> XML node, and are used to define the transient state information for a device (ex: on/off setting, brightness, temperature, etc.).
  • States defined in Devices.xml are automatically shows in the Trigger Event Device State Changed options when that plugin device type is selected, and are automatically shown in the Control Page editor when a control is created inspecting that plugin device.
  • States are read-only for everyone except the plugin that defines the device's states.
  • Plugins should update a device state after it has sent commands to hardware, or somehow received new state information from hardware. Example that increments the plugin defined state heatSetPoint by 1:
    dev = indigo.devices["Custom Plugin Thermostat"]
    dev.updateStateOnServer("heatSetPoint", dev.states["heatSetPoint"] + 1)
  • Plugins should subclass deviceStartComm and deviceEndComm to start/stop any hardware communication (normally via a new per-device thread):
    def deviceStartComm(self, dev):
    	self.easydaq.startCommThread(dev)
    
    def deviceStopComm(self, dev):
    	self.easydaq.stopCommThread(dev)
  • Calls to deviceStartComm and deviceEndComm are automatically managed by the Indigo Server and Indigo Plugin Host. When a plugin first connects all enabled device instances owned by the plugin will receive deviceStartComm calls. Likewise, deviceStartComm is called when a new plugin device is created or duplicated. deviceEndComm is called whenever a plugin is disabled, deleted, or when the plugin is shutting down. Therefore, these two functions should be the primary bottlenecks for starting/stopping device hardware or network connections.

Creating a Custom Plugin Trigger Event

FIXME Explain Events.xml. Show example plugin subclasses of functions: triggerStartProcessing, triggerStopProcessing, didTriggerProcessingPropertyChange. Note it works very similarly to devices.

Monitoring Device State Changes from a Plugin

FIXME (useful, but very rough notes below)

FIXME Give examples of using indigo.devices.subscribeToChanges() and plugin subclasses of functions: deviceCreated, deviceDeleted, deviceUpdated.

Monitoring Changes to Variables, Triggered & Scheduled Events, Action Groups, and Control Pages

FIXME (useful, but very rough notes below)

FIXME Give examples of using indigo.*.subscribeToChanges() and plugin subclasses of functions: variableCreated, variableDeleted, variableUpdated, triggerCreated, triggerDeleted, triggerUpdated, scheduleCreated, scheduleDeleted, scheduleUpdated, actionGroupCreated, actionGroupDeleted, actionGroupUpdated, controlPageCreated, controlPageDeleted, controlPageUpdated.

indigo_5_documentation/plugin_extending_tutorial.txt · Last modified: 2019/01/26 00:10 (external edit)
 

© Perceptive Automation, LLC. · Privacy