Differences
This shows you the differences between two versions of the page.
| indigo_2022.1_documentation:plugin_extending_tutorial [2022/03/23 17:13] – [Monitor Changes to Scheduled Events] davel17 | indigo_2022.1_documentation:plugin_extending_tutorial [2025/02/18 20:36] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Indigo Server Plugin Tutorial ====== | ||
| + | |||
| + | Note most of the code examples below are calling methods on the object //'' | ||
| + | |||
| + | // | ||
| + | |||
| + | ===== Indigo Plugin SDK Source Code Examples ===== | ||
| + | |||
| + | The Indigo Plugin SDK ([[https:// | ||
| + | |||
| + | Included in the SDK are examples that create plugin based relay, dimmer, thermostat, sensor, speed control, sprinkler, energy meter 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. The following table lists the Indigo Plugin SDK examples that were available at the time Indigo 2022.1 shipped. | ||
| + | |||
| + | ^ SDK Plugin task ^ Plugin that illustrates an approach | ||
| + | | Broadcast Plugin Information to Listeners | Example Custom Broadcaster | | ||
| + | | Subscribe to Plugin Information Broadcast | Example Custom Subscriber | | ||
| + | | Walk Through the Indigo Database | Example Database Traverse | | ||
| + | | Non-native Device Type | Example Device - Custom | | ||
| + | | Energy Meter Device Type | Example Device - Energy Meter | | ||
| + | | Device Factory Device Type | Example Device - Factory | | ||
| + | | Switch / Relay / Dimmer Device Type | Example Device - Relay and Dimmer | | ||
| + | | Sensor Device Type (Water, Motion, Light, Humidity) | Example Device - Sensor | | ||
| + | | Speed Control Device Type (Fan) | Example Device - Speed Control | | ||
| + | | Sprinkler Device Type | Example Device - Sprinkler | | ||
| + | | Thermostat Device Type | Example Device - Thermostat | | ||
| + | | Interact with the Indigo Server Using HTTP Client / Server | Example HTTP Responder | | ||
| + | | Listen for Insteon and/or X-10 Traffic | Example INSTEON:X10 Listener | | ||
| + | | Listen for Indigo Variable Change Notifications | Example Variable Change Subscriber | | ||
| + | | Listen for Z-Wave Traffic | Example ZWave Listener | | ||
| + | |||
| + | We'll be adding additional example plugins in the future. | ||
| + | |||
| + | ===== Other Useful Plugin Source Code Examples ===== | ||
| + | |||
| + | Additionally, | ||
| + | |||
| + | ^ Plugin task ^ Plugin that illustrates an approach | ||
| + | | Parsing JSON, XML from an IP source | NOAA Weather, [[https:// | ||
| + | | 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 | Email+ | ||
| + | | Interacting with an HTTP Web server | Example HTTP Responder | ||
| + | | Creating custom devices with states | Simple: NOAA Weather, [[https:// | ||
| + | | Creating custom actions | [[https:// | ||
| + | | Creating custom events | Airfoil | | ||
| + | |||
| + | Each of these plugins is installed by default with Indigo - in the ''/ | ||
| + | |||
| + | The [[https:// | ||
| + | |||
| + | ===== How to Read and Write Plugin Preferences ===== | ||
| + | |||
| + | * The per plugin preferences (pref) file is automatically managed (created, loaded, updated). | ||
| + | * Pref values can be numbers, boolean, strings, indigo.Dict() or indigo.List(). | ||
| + | * Key values defined in '' | ||
| + | |||
| + | < | ||
| + | |||
| + | * Or, if you're not sure the key exists: | ||
| + | |||
| + | < | ||
| + | |||
| + | * The latter will return the second parameter if they key doesn' | ||
| + | * A plugin can also insert other values into its pluginPrefs space (not just values shown in the plugin' | ||
| + | * To read a preference value access its key: | ||
| + | |||
| + | < | ||
| + | someVal = self.pluginPrefs[" | ||
| + | indigo.server.log(" | ||
| + | </ | ||
| + | |||
| + | * To create a new or update an existing preference value assign it a new value: | ||
| + | |||
| + | < | ||
| + | |||
| + | * The Indigo server will save the plugin prefs automatically, | ||
| + | |||
| + | < | ||
| + | indigo.server.savePluginPrefs | ||
| + | </ | ||
| + | |||
| + | ===== 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 //'' | ||
| + | * The pluginProps dictionary supports numbers, boolean, strings, indigo.Dict() or indigo.List(). | ||
| + | |||
| + | === Add new plugin metadata to the Device "den fixture" | ||
| + | < | ||
| + | dev = indigo.devices[" | ||
| + | newProps = dev.pluginProps | ||
| + | newProps[" | ||
| + | newProps[" | ||
| + | newProps[" | ||
| + | newProps[" | ||
| + | dev.replacePluginPropsOnServer(newProps) | ||
| + | </ | ||
| + | |||
| + | === Read plugin specific property '' | ||
| + | < | ||
| + | dev = indigo.devices[" | ||
| + | onCycles = dev.pluginProps[" | ||
| + | indigo.server.log(" | ||
| + | </ | ||
| + | |||
| + | === Increment the plugin specific property onCycles by 1 for the Device "den fixture" | ||
| + | < | ||
| + | dev = indigo.devices[" | ||
| + | newProps = dev.pluginProps | ||
| + | newProps[" | ||
| + | dev.replacePluginPropsOnServer(newProps) | ||
| + | |||
| + | dev = indigo.devices[" | ||
| + | onCycles = dev.pluginProps[" | ||
| + | indigo.server.log(" | ||
| + | </ | ||
| + | |||
| + | * Plugins have read-only access to other plugin metadata via //'' | ||
| + | * Plugins have read/write access to their own metadata space. | ||
| + | |||
| + | ===== How to Create 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 //''< | ||
| + | * States are specified in the Devices.xml //''< | ||
| + | * States defined in Devices.xml are automatically shown in the Trigger Event ''// | ||
| + | * States are read-only for everyone except the plugin that defines the device' | ||
| + | * 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 ''// | ||
| + | |||
| + | < | ||
| + | dev = indigo.devices[" | ||
| + | dev.updateStateOnServer(" | ||
| + | </ | ||
| + | |||
| + | * Plugins should subclass ''// | ||
| + | |||
| + | < | ||
| + | def deviceStartComm(self, | ||
| + | self.easydaq.startCommThread(dev) | ||
| + | |||
| + | def deviceStopComm(self, | ||
| + | self.easydaq.stopCommThread(dev) | ||
| + | </ | ||
| + | |||
| + | * Calls to ''// | ||
| + | |||
| + | ===== How to Create a Custom Plugin Trigger Event ===== | ||
| + | |||
| + | The XML in this file describes all events that your plugin will generate for use in Indigo. Your users will use these in the Trigger Events dialog just like any of the built-in Indigo events (like Power Failure, Email Received, etc). Your plugin can offer other types of events, including update notifications, | ||
| + | |||
| + | Here’s a very small '' | ||
| + | |||
| + | <?xml version=" | ||
| + | < | ||
| + | < | ||
| + | <Event id=" | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | <Field id=" | ||
| + | < | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | </ | ||
| + | |||
| + | As you can see, your ''< | ||
| + | |||
| + | <Event id=" | ||
| + | |||
| + | There are several Event-related and Trigger-related methods that you can add to your '' | ||
| + | |||
| + | ^ Element | ||
| + | | self.closedEventConfigUi(self, | ||
| + | | self.getEventConfigUiValues(self, | ||
| + | | self.getEventConfigUiXml(self, | ||
| + | | validateEventConfigUi(self, | ||
| + | |||
| + | The power of Events | ||
| + | |||
| + | ===== How to Monitor Changes to Various Indigo Objects ===== | ||
| + | |||
| + | In some instances, a plugin may need to know about changes to an Indigo object that it doesn' | ||
| + | |||
| + | Indigo provides a method to do this by allowing the plugin to " | ||
| + | === Subscribe to Indigo Object Changes === | ||
| + | |||
| + | To monitor changes to different classes of Indigo objects, you can include a call to the appropriate '' | ||
| + | |||
| + | ^ Element | ||
| + | | indigo.devices.subscribeToChanges() | | ||
| + | | indigo.variables.subscribeToChanges() | | ||
| + | | indigo.triggers.subscribeToChanges() | | ||
| + | | indigo.schedules.subscribeToChanges() | | ||
| + | | indigo.actionGroups.subscribeToChanges() | | ||
| + | | indigo.controlPages.subscribeToChanges() | | ||
| + | |||
| + | < | ||
| + | def __init__(self, | ||
| + | super().__init__(plugin_id, | ||
| + | |||
| + | indigo.devices.subscribeToChanges() | ||
| + | indigo.variables.subscribeToChanges() | ||
| + | indigo.triggers.subscribeToChanges() | ||
| + | indigo.actionGroups.subscribeToChanges() | ||
| + | </ | ||
| + | |||
| + | These methods only invoke the notification process, they don't do anything with the notifications they subscribe to. In order to react to any notifications, | ||
| + | === Monitor Device State Changes from a Plugin === | ||
| + | |||
| + | ^ Element | ||
| + | | self.deviceCreated(self, | ||
| + | | self.deviceDeleted(self, | ||
| + | | self.deviceUpdated(self, | ||
| + | |||
| + | < | ||
| + | def deviceCreated(self, | ||
| + | # Receives a copy of the device instance | ||
| + | self.logger.debug(f" | ||
| + | </ | ||
| + | < | ||
| + | def deviceDeleted(self, | ||
| + | # Receives a copy of the device instance | ||
| + | self.logger.info(f" | ||
| + | </ | ||
| + | < | ||
| + | def deviceUpdated(self, | ||
| + | self.logger.debug(" | ||
| + | |||
| + | # Call the parent implementation of deviceUpdated() base class | ||
| + | indigo.PluginBase.deviceUpdated(self, | ||
| + | |||
| + | # Convert the payload objects from indigo.Dict() objects to Python dict() objects. | ||
| + | orig_dict = {} | ||
| + | for (k, v) in orig_dev: | ||
| + | orig_dict[k] = v | ||
| + | |||
| + | new_dict = {} | ||
| + | for (k, v) in new_dev: | ||
| + | new_dict[k] = v | ||
| + | |||
| + | # Create a dictionary that contains only those properties and attributes that have changed. | ||
| + | diff = {k: new_dict[k] for k in orig_dict if k in new_dict and orig_dict[k] != new_dict[k]} | ||
| + | |||
| + | self.logger.debug(f" | ||
| + | </ | ||
| + | === Monitor Changes to Variables === | ||
| + | |||
| + | ^ Element | ||
| + | | self.variableCreated(self, | ||
| + | | self.variableDeleted(self, | ||
| + | | self.variableUpdated(self, | ||
| + | |||
| + | The variable change monitoring methods operate like the methods for devices above. Note, unlike Indigo devices, you'll need to monkey patch the '' | ||
| + | |||