ESP Easy: how to develop your own plugins

In the previous tutorial we saw how to customize the ESP Easy firmware from Playground plugins, the sandbox that allows any developer to offer add-ons. I am currently preparing a small project to monitor the indoor air quality based on an MQ135 sensor. How there is not yet a module for this sensor, I started in the development of my own module. I take this opportunity to share with you my experience. There is no (yet) official documentation, so much of the information has been obtained by deduction and successive testing.

For this tutorial, we will develop a new plugin for the MQ135. Since no plugin 135 still exists in the playground, I took advantage of it.

ESP Easy plugin header: include and #define

In the plugin header, we can define which libraries to include

#include <SPI.h>

Then, all modules must be identified by a series of keys. It is important to correctly assign the chosen ID to all keys for the plugin to work.

#define PLUGIN_135 Plugin identifier
#define PLUGIN_ID_135 135 Plugin ID
#define PLUGIN_NAME_135 “Indoor Air Quality – MQ135” The label that will be displayed in the selection list
#define PLUGIN_VALUENAME1_135 “CO2” Variable output of the plugin. Label displayed in quotation marks

If the module has more than one output value, simply add a new key by incrementing the counter. For example, PLUGIN_VALUENAME2_135, PLUGIN_VALUENAME3_135

Plugin function

The plugin is encapsulated in a function. This function takes several parameters that you just have to test. The ESP Easy engine launches the plugins associated with the configured Devices at regular intervals.

boolean Plugin_135(byte function, struct EventStruct *event, String& string)

By convention, we name the plugin by Plugin_ID_DU_PLUGIN

Method PLUGIN_DEVICE_ADD

The first method (PLUGIN_DEVICE_ADD) is used to define the parameters that are common to all Devices

case PLUGIN_DEVICE_ADD:
      {
        Device[++deviceCount].Number = PLUGIN_ID_135;
        Device[deviceCount].Type = DEVICE_TYPE_ANALOG;
        Device[deviceCount].VType = SENSOR_TYPE_SINGLE;                           
        Device[deviceCount].Ports = 0;
        Device[deviceCount].PullUpOption = false;
        Device[deviceCount].InverseLogicOption = false;
        Device[deviceCount].FormulaOption = true;
        Device[deviceCount].ValueCount = 1;
        Device[deviceCount].SendDataOption = true;
        Device[deviceCount].TimerOption = true;
        Device[deviceCount].GlobalSyncOption = true;
        break;
      }

The main parameters are:

  • Type: The type of hardware connected. One can choose from
    • DEVICE_TYPE_SINGLE (1): connected to a digital input (datapin)
    • DEVICE_TYPE_I2C (2): the device communicates with the ESP via the I2C bus
    • DEVICE_TYPE_ANALOG 3: the A / D converter of the ESP8266 is used (Pin TOUT, for example A0)
    • DEVICE_TYPE_DUAL (4): Device connected using 2 digital inputs
    • DEVICE_TYPE_DUMMY (99): logical device without a physical connection (Dummy device). Read
    • this article to learn more
  • VType. What type of value will return the plugin. One can choose from
    • SENSOR_TYPE_SINGLE (1): an output
    • SENSOR_TYPE_TEMP_HUM (2): 2 temperature & humidity outputs (DHT11 or DHT22)
    • SENSOR_TYPE_TEMP_BARO (3): 2 temperature and atmospheric pressure outputs (BMP180)
    • SENSOR_TYPE_TEMP_HUM_BARO (4): 3 outputs, temperature, humidity, atmospheric pressure (BME280)
    • SENSOR_TYPE_DUAL (5): generic, 2 outputs
    • SENSOR_TYPE_TRIPLE (6): generic, 3 outputs
    • SENSOR_TYPE_SWITCH (10): 2 states, switch
    • SENSOR_TYPE_DIMMER (11): 1 dimmer output
    • SENSOR_TYPE_LONG (20): 1 output
  • ValueCount: number of output variables. This counter must match the number of keys PLUGIN_VALUENAME1_xxx

Method PLUGIN_GET_DEVICENAME

This method returns the Device name.

Method PLUGIN_GET_DEVICEVALUENAMES

This method is called when you open the module configuration page. It allows to add a new row for each output variable of the plugin (Optional Settings). Here is what we get for example.

espeasy-plugin-optional-settings-mq135

Method PLUGIN_INIT

This method is called to initialize the plugin. It is possible, for example, to reload parameters.

The method must end with success = true;

Method PLUGIN_WEBFORM_LOAD

This method is called to open the module configuration page. It allows to build the configuration options (except the parameters common to all modules) of the module. The method must return a string that contains the HTML of the rows to be added.

It’s a painting. Each row (<TR>) consists of 2 columns (<TD>).

Here is an example to add a line to define the reference CO2 level. Here are some explanations for those who discover HTML:

  • <TR>: add a line to the table.
  • <TD>: a column is added
  • CO2 Level ref. : The text displayed in the first column. The label of the parameter
  • <TD>: a 2nd column is added
  • <Input type = ‘text’ name = ‘plugin_135_ATMOCO2’ value = ‘: The 2nd column consists of a text input field. We can retrieve the contents of the field with its name (name = ‘plugin_135_ATMOCO2’).
  • The default value is constructed by going to read it in the module settings: Settings.TaskDevicePluginConfigFloat [event-> TaskIndex] [4]. It is located at index 4. We will see below how we store the parameters of the plugin.
  • Finally, we close the column F(“‘>”)
string += F("<TR><TD>CO2 Level ref.:<TD><input type='text' name='plugin_135_ATMOCO2' value='");
string += Settings.TaskDevicePluginConfigFloat[event->TaskIndex][4];
string += F("'>");

Finally, you can ask to reload the parameters with the LoadTaskSettings method (event-> TaskIndex).

Here is what we get for example

espeasy plugin playground develop

The method must end with success = true;

Method PLUGIN_WEBFORM_SAVE

This method is called every time you press the submit button on the Device Configuration page. This method will allow us, for example, to save the parameters of the plugin.

To retrieve the value of a field (input, combo, checkbox), the WebServer.arg method is used. Which gives for example to recover the level of reference level. A string is retrieved?

String plugin5= WebServer.arg("plugin_135_ATMOCO2");

It is now necessary to make a small conversion before recording the value of the parameter on the EPROM of the ESP8266.

Settings.TaskDevicePluginConfigFloat[event->TaskIndex][4] = plugin5.toFloat();

There are two methods:

TaskDevicePluginConfigFloat: to store as a float. It will be necessary to do a conversion of the string with the method toFloat ()
TaskDevicePluginConfig: to store an integer value (int). It is also used for the index of a choice in a list of choices. First, make a conversion with toInt ().
The method must end with success = true;

Methods PLUGIN_READ, PLUGIN_ONCE_A_SECOND, PLUGIN_TEN_PER_SECOND:

This method makes it possible to read the value of the sensors, and more generally to perform all the treatments which are usually carried out in the loop () of an Arduino program. Depending on the desired treatment frequency, there are 3 methods:

  • PLUGIN_READ: The plugin is executed according to the delay specified on the Device configuration page only once.
  • PLUGIN_ONCE_A_SECOND: this task will be executed once every second with all the other tasks calling this function.
  • PLUGIN_TEN_PER_SECOND: same but 10 times per second.
    When the ESP starts, tasks are added to lists. It will run at the selected frequency. It is therefore necessary to choose the frequency of execution and not to create a code too heavy for the ESP to have the time to handle all the tasks.

The method must end with success = true;

Personal Methods

If you want to add your own methods, just write them as usual just after the Plugin method.

espeasy plugin playground develop

So, you know the basics to start developing your own plugins. Of complicated appearance, it is actually quite simple. The easiest way is to copy an existing plugin and modify it to retrieve the basic structure and methods. In the next tutorial, we will see a concrete case with the addition of a module to measure air quality using an MQ135 sensor.

Subscribe to the weekly newsletter

No spam and no other use will be made of your email. You can unsubscribe anytime.

5 Comments
  1. Hi Christophe,
    Many thanks for posting this, I’ve found it a good introduction to developing my own first plugin (for an AC current/power sensor). Is the full code of your plugin 135 available anywhere, please? I looked on the plugin playground but didn’t see it there – is it available anywhere else please?
    Regards, Andrew

    • Hello Andrew. Thank you very much. I hesitated to publish the plugin because I was disappointed with the measurements of my MQ135 (very few variations). You’re right, the best thing is that I share my code on Github. You will be able to try and most certainly improve my code. My MQ135 may be defective. I send you a message as soon as the plugin is available on github. See you soon

      • Any chance to share this plugin on Github ?

      • Hello Christophe,
        I’m just giving this a bump. I’d still be interested in your code, please, to help myself to learn about plugins. Did you share it on Github?

      • Hi Christophe, did you have any success with publishing your plugin on github? I am still very interested to learn from it. Don’t worry if it’s not completely finished!
        Best wishes, Andrew

Leave a Reply

DIY Projects
%d bloggers like this: