The plugin system on the OpenMotics Gateway allows users to run python code on the gateway. This code can interact with the OpenMotics Master through the webservice, expose new methods on the webservice, receive events for input and output changes and run background tasks.
- 1 Writing a plugin
- 2 Interfaces
- 3 Plugin configuration
- 4 Packaging a plugin
- 5 Installing a plugin
Writing a plugin
The plugins are written in Python 2.7 and creating a new one is as easy as extending the OMPluginBase. Three class variables should be defined: name (String), version (String with format x.y.z with x,y,z are integers) and interfaces (a list of tuples (interface name, version)). You will find more information about the interface system below.
class MyPlugin(OMPluginBase): name = 'MyPlugin' version = '0.0.1' interfaces = [ ('webui', '1.0') ]
The @om_expose decorator
Decorator to expose a method of the plugin class through the webinterface. The url will be /plugins/<plugin-name>/<method>.
Normally an authentication token is required to access the method. The token will be checked and removed automatically when using the following construction:
@om_expose def method_to_expose(self, ...): ...
It is possible to expose a method without authentication: no token will be required to access the method, this is done as follows:
@om_expose(auth=False) def method_to_expose(self, ...): ...
The @input_status decorator
Decorator to indicate that the method should receive input status messages. The receiving method should accept one parameter, a tuple of (input, output). Each time an input is pressed, the method will be called.
Important ! This method should not block, as this will result in an unresponsive system. Please use a separate thread to perform complex actions on input status messages.
@input_status def recv_input_status(self, status): (input, output) = status ....
The @output_status decorator
Decorator to indicate that the method should receive output status messages. The receiving method should accept one parameter, a list of tuples (output, dimmer value). Each time an output status is changed, the method will be called.
Important ! This method should not block, as this will result in an unresponsive system. Please use a separate thread to perform complex actions on output status messages.
@output_status def recv_output_status(self, status): for s in status: (output, dimmer_level) = s ....
The @background_task decorator
Decorator to indicate that the method is a background task. A thread running this background task will be started on startup.
@output_status def run(self): ....
The @on_remove decorator
Decorator to indicate that the method should be called just before removing the plugin. This can be used to cleanup files written by the plugin. Note: the plugin package and plugin configuration data will be removed automatically and should not be touched by this method.
@on_remove def uninstall(self): ....
The purpose of the interface system is that generic interface can be defined, those interfaces can be implemented by the plugins. For example an audio interface could define methods for setting the channel, the volume and so on. An concrete implementation of the audio interface can then be created for each type of audio device. This allows for a generic web page for controlling audio devices with different backends for different audio devices.
An interface defines a set of methods on the plugin that are exposed on the webinterface. At the moment only two interfaces are defined:
The webui interface
the webui interface allows the user to expose a html page on the gateway web interface.
The config interface
Packaging a plugin
A plugin is packaged as a tgz file containing the content of the plugin package. The plugin class should be defined in main.py and an __init__.py file should be provided. Extra python files can be included in the package. The following commands can be used to create a package and to calculate the md5 sum (required for the plugin installation):
tar czf plugin.tgz main.py __init__.py md5sum plugin.tgz