Developing a Python plugin

From Domoticz
Jump to: navigation, search

Overview

Page (still) under construction.

The Domoticz Python Framework is not a general purpose Domoticz extension. It is designed to allow developers to easily create an interface between a piece of Hardware (or Virtual Hardware) and Domoticz. To that end it provides capabilities that seek to do the hard work for the developer leaving them to manage the messages that move backwards and forwards between the two.

The Framework provides the plugin with a full Python 3 instance that exists for as long as Domoticz is running. The plugin is called by Domoticz when relevant events occur so that it can manage connectivity to the hardware and state synchronisation.

Multiple copies of the same plugin can run for users that have more than one instance of a particular hardware type.

The following things should not be attempted using the Python Framework:

  • Use of asynchronous code or libraries. This will not work the way you expect.
  • Use of call back functions. This will not work the way you expect.
  • Waiting or sleeping. Plugins are single threaded so the whole plugin system will wait.

Overall Structure

The plugin documentation is split into two distinct parts:

  • Plugin Definition - Telling Domoticz about the plugin
  • Runtime Structure - Interfaces and APIs to manage message flows between Domoticz and the hardware

Plugin Definition

To allow plugins to be added without the need for code changes to Domoticz itself requires that the plugins be exposed to Domoticz in a generic fashion. This is done by having the plugins live in a set location so they can be found and via an XML definition embedded in the Python script itself that describes the parameters that the plugin requires.

During Domoticz startup all directories directly under the 'plugins' directory are scanned for python files named plugin.py and those that contain definitions are indexed by Domoticz. When the Hardware page is loaded the plugins defined in the index are merged into the list of available hardware and are indistinguishable from natively supported hardware. For the example below the Kodi plugin would be in a file domoticz/plugins/Kodi/plugin.py. Some example Python scripts can be found in the domoticz/plugins/examples directory.

Plugin definitions expose some basic details to Domoticz and a list of the parameters that users can configure. Each defined parameters will appear as an input on the Hardware page when the plugin is selected in the dropdown.

Definitions look like this:

"""
<plugin key="Kodi" name="Kodi Players" author="dnpwwo" version="1.0.0" wikilink="http://www.domoticz.com/wiki/plugins/Kodi.html" externallink="https://kodi.tv/">
    <params>
        <param field="Address" label="IP Address" width="200px" required="true" default="127.0.0.1"/>
        <param field="Port" label="Port" width="30px" required="true" default="9090"/>
        <param field="Mode1" label="MAC Address" width="150px" required="false"/>
        <param field="Mode2" label="Shutdown Command" width="100px">
            <options>
                <option label="Hibernate" value="Hibernate"/>
                <option label="Suspend" value="Suspend"/>
                <option label="Shutdown" value="Shutdown"/>
                <option label="Ignore" value="Ignore" default="true" />
            </options>
        </param>
        <param field="Mode3" label="Notifications" width="75px">
            <options>
                <option label="True" value="True"/>
                <option label="False" value="False"  default="true" />
            </options>
        </param>
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>
"""

Definition format details:

Tag Description/Attributes
<plugin> Required.
Attribute Purpose
key Required.

Unique identifier for the plugin. Never visible to users this should be short, meaningful and made up of characters A-Z, a-z, 0-9 and -_ only. Stored in the ‘Extra’ field in the Hardware. Used as the base name for the plugin Python file, e.g. ‘DenonAVR’ maps to /plugins/DenonAVR/plugin.py

name Required.

Meaningful description for plugin. Shown in the ‘Type’ drop down on the Hardware page.

version Required.

Plugin version. Used to compare plugin version against repository version to determine if updates are available.

author Optional.

Plugin author. Supplied to Hardware page but not currently shown.

wikilink Optional.

Link to the plugin usage documentation on the Domoticz wiki. Shown on the Hardware page.

externallink Optional.

Link to an external URL that contains additional information about the device. Shown on the Hardware page.

<params> Simple wrapper for param tags. Contained within <plugin>.
<param> Parameter definitions, Contained within <params>.

Parameters are used by the Hardware page during plugin addition and update operations. These are stored in the Hardware table in the database and are made available to the plugin at runtime.

Attribute Purpose
field Required.

Column in the hardware table to store the parameter.
Valid values:

  • SerialPort - used by ‘serial’ transports
  • Address - used by non-serial transports
  • Port - used by non-serial transports
  • Mode1 - General purpose
  • Mode2 - General purpose
  • Mode3 - General purpose
  • Mode4 - General purpose
  • Mode5 - General purpose
  • Mode6 - General purpose
  • Username - Username for authentication
  • Password - Password for authentication
label Required.

Field label. Where possible standard labels should be used so that Domoticz can translate them when languages other than English are enabled.

width Optional.

Width of the field

required Optional.

Marks the field as mandatory and the device will not be added unless a value is provided

default Optional.

Default value for the field. Ignored when <options> are specified.

<options> Simple wrapper for option tags. Contained within <param>.

Parameter definitions that contain this tag will be shown as drop down menus in the Hardware page. Available values are defined by the <option> tag.

<option> Instance of a drop down option. Contained within <options>.
Attribute Purpose
label Required.

Text to show in dropdown menu. Will be translated if a translation exists.

value Required.

Associated value to store in database

default Optional. Valid value:

true

Runtime Structure

Domoticz exposes settings and device details through two Python dictionaries.

Parameters

These are always available and remain static for the lifetime of the plugin. They can be accessed by name for example: Parameters["SerialPort"]

Description
Key Unique short name for the plugin, matches python filename.
Address IP Address, used during connection.
Port IP Port, used during connection.
Username Username.
Password Password.
Mode1 General Parameter 1
...
Mode6 General Parameter 6
SerialPort SerialPort, used when connecting to Serial Ports.

Devices

Description
Key Unit.

Unit number for the device as specified in the Manifest. Note: Devices can be deleted in Domoticz so not all Units specified will necessarily still be present. E.g: Domoticz.Log(Device[2].Name)

Function Description
ID The Domoticz Device ID
Name Current Name in Domoticz
nValue Current numeric value
sValue Current string value
LastLevel Last level as reported by Domoticz
LastUpdate Timestamp of the last update, e.g: 2017-01-22 01:21:11
Methods Per device calls into Domoticz to manipulate specific devices
Function Description
__init__
Parameter Description
Name Mandatory.
Is appended to the Hardware name to set the initial Domoticz Device name.
This should not be used in Python because it can be changed in the Web UI.
Unit Mandatory.
Plugin index for the Device. This can not change and should be used reference Domoticz devices associated with the plugin. This is also the key for the Devices Dictionary that Domoticz prepopulates for the plugin.
TypeName Optional.
Common device types, this will set the values for Type and Subtype.

"Air Quality"
"Alert"
"Barometer"
"Counter Incremental"
"Current/Ampere"
"Current (Single)"
"Custom"
"Distance"
"Gas"
"Humidity"
"Illumination"
"kWh"
"Leaf Wetness"
"Percentage"
"Pressure"
"Rain"
"Selector Switch"
"Soil Moisture"
"Solar Radiation"
"Sound Level"
"Switch"
"Temperature"
"Temp+Hum"
"Temp+Hum+Baro"
"Text"
"Usage"
"UV"
"Visibility"
"Voltage"
"Waterflow"
"Wind"
"Wind+Temp+Chill"

Type Optional.
Directly set the numeric Type value. Should only be used if the Device to be created is not supported by TypeName.
Subtype Optional.
Directly set the numeric Subtype value. Should only be used if the Device to be created is not supported by TypeName.
Switchtype Optional.
Image Optional.
Set the image number to be used with the device. Only required to override the default.
Options Optional.
Set the Device Options field. A few devices, like Selector Switches, require additional details to be set in this field.
Both positional and named parameters are supported.
Creates a new device object in Python. E.g:
 myDev1 = Domoticz.Device("Total", 1, 113)
 myDev2 = Domoticz.Device(Name="My Counter", Unit=2, TypeName="Counter Incremental")

or

 import Domoticz
 import base64
 #
 def stringToBase64(s):
   return base64.b64encode(s.encode('utf-8')).decode("utf-8")
 #
 def onStart():
   if (len(Devices) == 0):
       Domoticz.Device(Name="Status",  Unit=1, Type=17,  Switchtype=17).Create()
       LevelActions= "LevelActions:"+stringToBase64("||||")+";"
       LevelNames= "LevelNames:"+stringToBase64("Off|Video|Music|TV Shows|Live TV")+";"
       Other= "LevelOffHidden:ZmFsc2U=;SelectorStyle:MA=="
       Options=LevelActions+LevelNames+Other
       Domoticz.Device(Name="Source", Unit=2, \
                       TypeName="Selector Switch", Options=Options).Create()
       Domoticz.Device(Name="Volume", Unit=3, \
                       Type=244, Subtype=73, Switchtype=7, Image=8).Create()
       Domoticz.Device(Name="Playing", Unit=4, \
                       Type=244, Subtype=73, Switchtype=7, Image=12).Create()
       Domoticz.Log("Devices created.")

Device objects in Python are in memory only until they are added to the Domoticz database using the Create function documented below.

Create Parameters: None, acts on current object. Creates the device in Domoticz from the object. E.g:
 myDev = Domoticz.Device(Name="Kilo Watts", Unit=16, TypeName="kWh")
 myDev.Create()
 Domoticz.Log("Created device: "+Devices[16].Name+ \
              ", myDev also points to the Device: "+myDev.Name)

or

 Domoticz.Device(Name="Kilo Watts", Unit=16, TypeName="kWh").Create()
 Domoticz.Log("Created device: "+Devices[16].Name)

Successfully created devices are immediately added to the Devices dictionary.

Update Parameters: nValue, sValue. Updates the current values in Domoticz.

E.g Devices[1].Update(1,”10”)

Delete Parameters: None, acts on current object. Deletes the device in Domoticz.E.g:
 Devices[1].Delete()

or

 myDev = Devices[2]
 myDev.Delete()

Deleted devices are immediately removed from the Devices dictionary but local instances of the object are unchanged.

Refresh Parameters: None. Refreshes the values for the device from the Domoticz database.

Not normally required because device values are updated when callbacks are invoked.

Image Parameters: Image number. Updates the image associated with the device.

Used to change the image in Domoticz for example: wind direction, day/night or temperature.

Callbacks

Plugins are event driven. Domoticz will notify the plugin when certain events occur through a number of callbacks, these are:

Callback Description
onStart Parameters: None.

Called when the hardware is started, either after Domoticz start, hardware creation or update.

onConnect Parameters: Status, Description

Called when connection to remote device either succeeds or fails. Zero Status indicates success. If Status is not zero then the Description will describe the failure.

onMessage Parameters: Data, Status, Extras.

Called when a single,complete message is received from the remote device (as defined by the Protocol setting). This callback should be used to interpret messages from the device and set the related Domoticz devices as required. Status and Extras are protocol specific. For HTTP Status is the Response Status (200, 302, 404 etc) and Extras is a dictionary containing the Response Headers

onNotification Parameters: Data.

Called when any Domoticz device generates a notification. The Data param contains the notification details. Hardware that can handle notifications should be notified as required.

onCommand Parameters: Unit, Command, Level, Hue.

Called when a command is received from Domoticz. The Unit parameters matches the Unit specified in the device definition and should be used to map commands to Domoticz devices. This callback should be used to send Domoticz commands to the remote device.

onHeartbeat Called every 'heartbeat' seconds (default 10) regardless of connection status.

Heartbeat interval can be modified by the Heartbeat command. Allows the Plugin to do periodic tasks including request reconnection if the connection has failed.

onDisconnect Called after the remote device is disconnected.
onStop Called when the hardware is stopped or deleted from Domoticz.

C++ Callable API

Importing the ‘Domoticz’ module in the Python code exposes functions that plugins can call to perform specific functions. All functions are non-blocking and return immediately.

Function Description/Attributes
Debug Parameters: String

Write message to Domoticz log only if verbose logging is turned on.

Log Parameters: String.

Write message to Domoticz log

Error Parameters: String

Write error message to Domoticz log

Debugging Parameters: Integer, 0 or 1.

Set logging level. 1 set verbose logging, all other values use default level

Transport Defines the connection type that will be used by the plugin.
Parameter Description
Transport Mandatory.
Values can be TCP/IP or Serial.
Address Mandatory.
IP Address or SerialPort to connect to.
Port Optional.
TCP/IP connections only, string containing the port number.
Baud Optional.
Serial connections only, the required baud rate.

Default: 115200

This allows Domoticz to make connections on behalf of the plugin. E.g:

 Domoticz.Transport("TCP/IP", Parameters["Address"], Parameters["Port"])
 Domoticz.Transport(Transport="Serial", Address=Parameters["SerialPort"], Baud=115200)

Both positional and named parameters are supported.

Protocol Parameters: String.

Defines the protocol details that will be used by the plugin. This allows Domoticz to know how to handle incoming messages properly.

Attribute Purpose
protocol Required.

The protocol that will be used to talk to the device. This is used to allow Domoticz to break incoming data into single messages to pass to the plugin. Valid values:

  • None (default)
  • line
  • JSON
  • XML
  • HTTP
Heartbeat Parameters: Integer.

Set the heartbeat interval in seconds, default 10 seconds. Values greater than 30 seconds will cause a message to be regularly logged about the plugin not responding. The plugin will actually function correctly with values greater than 30 though.

Connect Parameters: None.

Connect to remote device using transport details. Connect returns immediately and the results will be returned via the onConnect callback. If the address set via the Transport function translates to multiple endpoint they will all be tried in order until the connection succeeds or the list of endpoints is exhausted.

Send Send the specified message to the remote device.
Parameter Description
Message Mandatory.
Message text to send.
Verb Optional.
Protocol specific meaning. For HTTP should be GET or POST.
URL Optional.
Protocol specific meaning. For HTTP should be the target URL.
Headers Optional.
A dictionary with Protocol specific meaning. For HTTP should be a dictionary of HTTP headers.
Delay Optional.
Number of seconds to delay message send.
Note that Domoticz will send the message sometime after this period. Other events will be processed in the intervening period so delayed sends will be processed out of order. This feature may be useful during delays when physical devices turn on.

Both positional and named parameters are supported.
E.g:

 Domoticz.Send(Message=myMessage, Delay=4)
 
 Headers = {"Connection": "keep-alive", "Accept": "Content-Type: text/html; charset=UTF-8"}
 Domoticz.Send("", "GET", "/page.html", Headers)
 
 postData = "param1=value&param2=other+value"
 Domoticz.Send(postData, "POST", "/MediaRenderer/AVTransport/Control", {'Content-Length':str(len(postData))})
Disconnect Parameters: None.

Disconnect from remote device