Writing a Plugin

This page contains some notes and tips on how to build a Plugin for DomotiGa; on how to work with Gambas, see Gambas.
Please add/edit this page if you have any additions.

How can I write my own plugin?

If you want DomotiGa to support your own hardware, or connect to a internet service it doesn't support yet, you can create your own plugin.
Most of the times it can be easy to copy an existing plugin which does more or less the same.
But even then you need to create/adapt settings, database entries etc.
We walk through a few steps now.

Decide on which name you want to use.

Choose one not too long or too short, because you need to use this for settings table, settings form and plugin class file name.
For this how-to we choose 'PluginFoo'

Settings database table

Every plugin needs settings, settings for all plugins are stored in the MySQL database, in a table called 'settings_<pluginname>'
So 'settings_pluginfoo' is the one we need to create.

Mandatory fields are:

+----------+--------------+------+-----+---------+-------+
| Field    | Type         | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| id       | int(11)      | NO   | PRI | NULL    |       |
| enabled  | tinyint(1)   | NO   |     | 0       |       |
| debug    | tinyint(1)   | NO   |     | 0       |       |
+----------+--------------+------+-----+---------+-------+

You have to determine which extra settings you need, and what type they are.
If you plugin connects only via a serialport you can have:

+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| serialport   | varchar(128) | YES  |     | NULL    |       |
| baudrate     | varchar(32)  | YES  |     | NULL    |       |
| debug        | tinyint(1)   | NO   |     | 0       |       |
+--------------+--------------+------+-----+---------+-------+

If your plugin only connects to a tcp address and port you may need:

+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| tcphost      | varchar(32)  | YES  |     | NULL    |       |
| tcpport      | int(11)      | YES  |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

If your plugin can connect to both (user select-able) for example a serialport connected via an netwerk device, implement them both:

+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| tcphost      | varchar(32)  | YES  |     | NULL    |       |
| tcpport      | int(11)      | YES  |     | NULL    |       |
| type         | varchar(32)  | YES  |     | NULL    |       |
| serialport   | varchar(128) | YES  |     | NULL    |       |
| baudrate     | varchar(32)  | YES  |     | NULL    |       |
| debug        | tinyint(1)   | NO   |     | 0       |       |
| relayenabled | tinyint(1)   | YES  |     | NULL    |       |
| relayport    | int(11)      | YES  |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+

The field 'type' contains serial and tcp as options, and is use to select interfacetype.
The fields 'relayenabled' and 'relayport' can be use to relay the data received on the serial or tcp port to another device or software for analyse of the data (debugging)
If the protocol is very simple you can leave them out.

PluginFoo implement both interfaces, so this will be our settings table:

mysql> describe settings_pluginfoo;
+--------------+--------------+------+-----+---------+-------+
| Field        | Type         | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+-------+
| id           | int(11)      | NO   | PRI | NULL    |       |
| enabled      | tinyint(1)   | NO   |     | 0       |       |
| tcphost      | varchar(32)  | YES  |     | NULL    |       |
| tcpport      | int(11)      | YES  |     | NULL    |       |
| type         | varchar(32)  | YES  |     | NULL    |       |
| serialport   | varchar(128) | YES  |     | NULL    |       |
| baudrate     | varchar(32)  | YES  |     | NULL    |       |
| debug        | tinyint(1)   | NO   |     | 0       |       |
| relayenabled | tinyint(1)   | YES  |     | NULL    |       |
| relayport    | int(11)      | YES  |     | NULL    |       |
+--------------+--------------+------+-----+---------+-------+
10 rows in set (0.00 sec)

We need to create the sql command to create them.

Every new version of DomotiGa has an upgrade file in the upgrade directory, needed for database upgrade between versions.

So we add the following to file 'upgrade/10017to10018.sql' (example file/versions)
and also to the install sql files, 'install/domotiga.sql' and 'install/domotiga-empty.sql'

--
-- Table structure for table `settings_pluginfoo`
--

DROP TABLE IF EXISTS `settings_pluginfoo`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `settings_pluginfoo` (
  `id` int(11) NOT NULL,
  `enabled` tinyint(1) NOT NULL DEFAULT '0',
  `tcphost` varchar(32) DEFAULT NULL,
  `tcpport` int(11) DEFAULT NULL,
  `type` varchar(32) DEFAULT NULL,
  `serialport` varchar(128) DEFAULT NULL,
  `baudrate` varchar(32) DEFAULT NULL,
  `debug` tinyint(1) NOT NULL DEFAULT '0',
  `relayenabled` tinyint(1) DEFAULT NULL,
  `relayport` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `settings_pluginfoo`
--

LOCK TABLES `settings_pluginfoo` WRITE;
/*!40000 ALTER TABLE `settings_pluginfoo` DISABLE KEYS */;
INSERT INTO `settings_pluginfoo` VALUES (0,0,'192.168.100.7',10001,'serial','/dev/ttyACM1','38400',0,-1,10020),(1,0,'192.168.100.7',10001,'serial','/dev/ttyACM1','38400',0,-1,10020);
/*!40000 ALTER TABLE `settings_pluginfoo` ENABLE KEYS */;
UNLOCK TABLES;

You see that some default values are provided, you have to do this also.

This table must contain two rows/records
Values in row with 'id' 0 are default values, when users click on the 'defaults' button on the settings form, these values are loaded/shown.
The values under id 1 are the active settings for instance #1, currently DomotiGa supports only one instance per plugin, but we are almost ready to implement mulitple instances, their settings will be under id 2, 3 etc.
So id 1 is instance 1.
The 'enabled' field of this record should be false by default.
The 'debug' field boolean determines if the plugin should output debug information to the log and log window.

Plugin Code

You can find two example templates under the development/plugin diretory of your domotiga installation the CPluginFoo.class file supports both serial and TCP interface code, and the CPluginTCPonly.class only TCP sockets.
Keep in mind that although an interface for a certain product can be an USB or serial dongle, it's often handy to also code support for connection to it over an TCP socket, when the USB device is connected to an network server, or you want to test/connect with a device in another location.

They receive data (lets say sensor data), and they can control devices via the SendCommand() routine.
Not all plugin types need devices linked to them, but most of them do, we need to define entries for them in the 'devicetypes' database table, more on that later...

They are too big to go through all the routines and code, but look at other plugins to see what they do in those routines.

StartPlugin() is called when DomotiGa starts and find it's entry in the plugins table, and sees an 'enabled' is true field in the settings table.
StopPlugin() and thus Disconnect() is called when DomotiGa is closing, or the plugin gets disabled/restarted.
DomotiGa calls the routine SendCommand() in each plugin if it has received a control command (On/Off/Dim etc) for a device linked to the interface/plugin and instance.

Regarding naming of variables, please add a letter to the name determining the type, for example s for string, b for boolean, i for integer etc, then followed by a Capital letter.

Plugins database table

Every Plugin needs an entry in the 'plugins' table, this so DomotiGa knows, what kind of plugin it is, which protocols it's supports, and to see if it needs to be started when domotiGa start (if field enabled is activated)
It displays only device types with the same protocol in the device editor for example.

+----+---------------------+-----------+-----------+-------+
| id | interface           | protocols | name      | type  |
+----+---------------------+-----------+-----------+-------+
| xx | PluginFoo Interface | FooProt   | PluginFoo | class |
+----+---------------------+-----------+-----------+-------+

For 'id' you need to pick the first unused one from the Plugins table.
'interface' is the name used to identify the name for the user, but also for the code when it needs to look up an device id.
'protocols' if your plugin and devices talk via a protocol enter the name here, this links the interface/plugin to the device types with the same protocol.
A plugin can have more than one protocol, for example to keep apart different sensor types. They are defined with a space between them, so a protocol can't have a space in it's name.
Type 'class' means we can instantiate it more than ones, used later.

Devicetypes database table

When you need to store values for a device (sensors for example) or need to control a physical device though the plugin you need to define one or more device types.

It looks like this:

+----+------------------+-------------+----------+----------------+
| id | name             | description | protocol | addressformat  |
+----+------------------+-------------+----------+----------------+
| xx | PluginFoo Device | Temp Sensor | FooProt  | temp 0x701     |
+----+------------------+-------------+----------+----------------+

Devicetypes must have an unqiue id, so find an empty one in the devicetypes table and claim it.
Don't use one above 2500, they are reserved for private types. (users can create them via the devicetype editor)

Settings form

Lastly you need to create a settings form for the GUI, and a Yii form for DomotiYii.

Optional steps

  • The device editor need to be made aware of protocol and address/identification field name.
  • If your module uses a serialport (like in this example) add it's name to this array in FToolsSerialPorts.class
    So it can display the plugin name next to the selected port.
Dim sInterfaces AS String[] = ["ctx35" "irman" "sms" "gps" "onewire" "visca" "rfxcom" "weeder"...]
  • Add a Wiki Page

Template

Have a look at development/plugin/ and you will find:
  • CPluginFoo.class - Template containing code to connect to a TCP host or a serial port
  • CPluginFooTCPonly.class - Template containing code to connect to a TCP host (only)
  • CPluginFoo.sql - A file giving a sample for the SQL updates
  • README - A file pointing to this Wiki

How can I share the code?

When you have something working please consider to share your code so others can use it and the code can be further extended by others.

On how to share code, see Beta_Branch.
Basically, you can fork the repo and initiate a pull request.

When you think this is too much overhead, contact support for alternatives.

Related Resources

    Updated by: wwolkers, Updated almost 3 years ago
    Access count: 67077 since 2011-08-25

    Attached Files

    Also available in: PDF HTML TXT