Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
indigo_5_documentation:plugin_extending_tutorial [2012/02/19 17:16]
mattb
indigo_5_documentation:plugin_extending_tutorial [2019/01/26 00:10] (current)
Line 1: Line 1:
 +====== 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 ([[http://​www.indigodomo.com/​Indigo5SDK|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:<​code>​
 +self.pluginPrefs["​somePrefKey"​]
 +</​code>​ or, if you're not sure the key exists:<​code>​self.pluginPrefs.get("​somePrefKey",​ "​default value if key doesn'​t exist"​)</​code>​ 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:<​code>​
 +someVal = self.pluginPrefs["​somePrefKey"​]
 +indigo.server.log("​value is " + str(someVal))
 +</​code>​
 +  * To update a preference value assign it a new value:<​code>​
 +self.pluginPrefs["​somePrefKey"​] = 1234
 +</​code>​
 +
 +===== 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":<​code>​
 +dev = indigo.devices["​den fixture"​]
 +newProps = dev.pluginProps
 +newProps["​onCycles"​] = 5
 +newProps["​moreData1"​] = "​abc"​
 +newProps["​moreData2"​] = True
 +newProps["​moreData3"​] = 123.45
 +dev.replacePluginPropsOnServer(newProps)
 +</​code>​
 +  * Example reading the plugin specific property onCycles from the Device "den fixture":<​code>​
 +dev = indigo.devices["​den fixture"​]
 +onCycles = dev.pluginProps["​onCycles"​]
 +indigo.server.log("​onCycles is " + str(onCycles))
 +</​code>​
 +  * Example incrementing by 1 the plugin specific property onCycles for the Device "den fixture":<​code>​
 +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))
 +</​code>​
 +  * 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:<​code>​
 +dev = indigo.devices["​Custom Plugin Thermostat"​]
 +dev.updateStateOnServer("​heatSetPoint",​ dev.states["​heatSetPoint"​] + 1)
 +</​code>​
 +  * Plugins should subclass ''//​deviceStartComm//''​ and ''//​deviceEndComm//''​ to start/stop any hardware communication (normally via a new per-device thread):<​code>​
 +def deviceStartComm(self,​ dev):
 + self.easydaq.startCommThread(dev)
 +
 +def deviceStopComm(self,​ dev):
 + self.easydaq.stopCommThread(dev)
 +</​code>​
 +  * 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.
 

© Perceptive Automation, LLC. · Privacy