.. Writing and Using Plugins describes how to implement a plugin for FogLAMP and how to use it
.. https://docs.google.com/document/d/1IKGXLWbyN6a7vx8UO3uDbq5Df0VvE4oCQIULgZVZbjM

.. Images

.. |DHT11 in PI| image:: https://s3.amazonaws.com/foglamp/readthedocs/images/06_dht11_tags_in_PI.jpg
   :target: https://s3.amazonaws.com/foglamp/readthedocs/images/06_dht11_tags_in_PI.jpg

.. Links
.. |these INSTALLATION| raw:: html

   <a href="../building_foglamp/04_installation.html">these</a>

.. |Getting Started| raw:: html

   <a href="../building_foglamp/building_foglamp.html">here</a>

.. Links in new tabs

.. |DHT Repo| raw:: html

   <a href="https://github.com/foglamp/foglamp-south-dht11" target="_blank">FogLAMP DHT11 South Plugin</a>

.. |ADAFruit| raw:: html

   <a href="https://github.com/adafruit/Adafruit_Python_DHT" target="_blank">ADAFruit DHT Library</a>

.. |DHT Description| raw:: html

   <a href="https://www.adafruit.com/product/386" target="_blank">DHT11 Product Description</a>

.. |DHT Manual| raw:: html

   <a href="https://s3.amazonaws.com/foglamp/docs/v1/Common/plugins/South/DHT11/DHT11.pdf" target="_blank">DHT11 Product Manual</a>

.. |DHT Resistor| raw:: html

   <a href="https://s3.amazonaws.com/foglamp/docs/v1/Common/plugins/South/DHT11/DHT11-with-resistor.jpg" target="_blank">This picture</a>

.. |DHT Wired| raw:: html

   <a href="https://s3.amazonaws.com/foglamp/docs/v1/Common/plugins/South/DHT11/DHT11-RaspPI-wired.jpg" target="_blank">This picture</a>

.. |DHT Pins| raw:: html

   <a href="https://s3.amazonaws.com/foglamp/docs/v1/Common/plugins/South/DHT11/DHT11-RaspPI-pins.jpg" target="_blank">this</a>

.. |GPIO| raw:: html

   <a href="https://www.raspberrypi.org/documentation/usage/gpio/README.md" target="_blank">here</a>


.. =============================================


A South Plugin Example In Python: the DHT11 Sensor
--------------------------------------------------

Let's try to put all the information together and write a plugin. We can continue to use the example of an inexpensive sensor, the DHT11, used to measure temperature and humidity, directly wired to a Raspberry PI. This plugin is available on github, |DHT Repo|.

First, here is a set of links where you can find more information regarding this sensor:

- |DHT Description|
- |DHT Manual|
- |ADAFruit|


The Hardware
~~~~~~~~~~~~

The DHT sensor is directly connected to a Raspberry PI 2 or 3. You may decide to buy a sensor and a resistor and solder them yourself, or you can buy a ready-made circuit that provides the correct output to wire to the Raspberry PI. |DHT Resistor| shows a DHT11 with resistor that you can buy online.

The sensor can be directly connected to the Raspberry PI GPIO (General Purpose Input/Output). An introduction to the GPIO and the pinset is available |GPIO|. In our case, you must connect the sensor on these pins:

- **VCC** is connected to PIN #2 (5v Power)
- **GND** is connected to PIN #6 (Ground)
- **DATA** is connected to PIN #7 (BCM 4 - GPCLK0)

|DHT Wired| shows the sensor wired to the Raspberry PI and |DHT Pins| is a zoom into the wires used.


The Software
~~~~~~~~~~~~

For this plugin we use the ADAFruit Python Library (links to the GitHub repository are above). First, you must install the library (in future versions the library will be provided in a ready-made package):

.. code-block:: console
 
  $ git clone https://github.com/adafruit/Adafruit_Python_DHT.git
  Cloning into 'Adafruit_Python_DHT'...
  remote: Counting objects: 249, done.
  remote: Total 249 (delta 0), reused 0 (delta 0), pack-reused 249
  Receiving objects: 100% (249/249), 77.00 KiB | 0 bytes/s, done.
  Resolving deltas: 100% (142/142), done.
  $ cd Adafruit_Python_DHT
  $ sudo apt-get install build-essential python-dev
  Reading package lists... Done
  Building dependency tree
  Reading state information... Done
  The following NEW packages will be installed:
  build-essential python-dev
  ...
  $ sudo python3 setup.py install
  running install
  running bdist_egg
  running egg_info
  creating Adafruit_DHT.egg-info
  ...
  $


The Plugin
~~~~~~~~~~

This is the code for the plugin:

.. code-block:: python

  # -*- coding: utf-8 -*-

  # FOGLAMP_BEGIN
  # See: http://foglamp.readthedocs.io/
  # FOGLAMP_END

  """ Plugin for a DHT11 temperature and humidity sensor attached directly
      to the GPIO pins of a Raspberry Pi

      This plugin uses the Adafruit DHT library, to install this perform
      the following steps:

          git clone https://github.com/adafruit/Adafruit_Python_DHT.git
          cd Adafruit_Python_DHT
          sudo apt-get install build-essential python-dev
          sudo python setup.py install

      To access the GPIO pins foglamp must be able to access /dev/gpiomem,
      the default access for this is owner and group read/write. Either
      FogLAMP must be added to the group or the permissions altered to
      allow FogLAMP access to the device.
      """


  from datetime import datetime, timezone
  import uuid

  from foglamp.common import logger
  from foglamp.services.south import exceptions

  __author__ = "Mark Riddoch"
  __copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
  __license__ = "Apache 2.0"
  __version__ = "${VERSION}"

  _DEFAULT_CONFIG = {
      'plugin': {
           'description': 'Python module name of the plugin to load',
           'type': 'string',
           'default': 'dht11'
      },
      'pollInterval': {
          'description': 'The interval between poll calls to the device poll routine expressed in milliseconds.',
          'type': 'integer',
          'default': '1000'
      },
      'gpiopin': {
          'description': 'The GPIO pin into which the DHT11 data pin is connected', 
          'type': 'integer',
          'default': '4'
      }

  }

  _LOGGER = logger.setup(__name__)
  """ Setup the access to the logging system of FogLAMP """


  def plugin_info():
      """ Returns information about the plugin.

      Args:
      Returns:
          dict: plugin information
      Raises:
      """

      return {
          'name': 'DHT11 GPIO',
          'version': '1.0',
          'mode': 'poll',
          'type': 'south',
          'interface': '1.0',
          'config': _DEFAULT_CONFIG
      }


  def plugin_init(config):
      """ Initialise the plugin.

      Args:
          config: JSON configuration document for the device configuration category
      Returns:
          handle: JSON object to be used in future calls to the plugin
      Raises:
      """

      handle = config['gpiopin']['value']
      return handle


  def plugin_poll(handle):
      """ Extracts data from the sensor and returns it in a JSON document as a Python dict.

      Available for poll mode only.

      Args:
          handle: handle returned by the plugin initialisation call
      Returns:
          returns a sensor reading in a JSON document, as a Python dict, if it is available
          None - If no reading is available
      Raises:
          DataRetrievalError
      """

      try:
          humidity, temperature = Adafruit_DHT.read_retry(Adafruit_DHT.DHT11, handle)
          if humidity is not None and temperature is not None:
              time_stamp = str(datetime.now(tz=timezone.utc))
              readings = {'temperature': temperature, 'humidity': humidity}
              wrapper = {
                      'asset':     'dht11',
                      'timestamp': time_stamp,
                      'key':       str(uuid.uuid4()),
                      'readings':  readings
              }
              return wrapper
          else:
              return None

      except Exception as ex:
          raise exceptions.DataRetrievalError(ex)

      return None


  def plugin_reconfigure(handle, new_config):
      """ Reconfigures the plugin, it should be called when the configuration of the plugin is changed during the
          operation of the device service.
          The new configuration category should be passed.

      Args:
          handle: handle returned by the plugin initialisation call
          new_config: JSON object representing the new configuration category for the category
      Returns:
          new_handle: new handle to be used in the future calls
      Raises:
      """

      new_handle = new_config['gpiopin']['value']
      return new_handle


  def plugin_shutdown(handle):
      """ Shutdowns the plugin doing required cleanup, to be called prior to the device service being shut down.

      Args:
          handle: handle returned by the plugin initialisation call
      Returns:
      Raises:
      """
      pass


Building FogLAMP and Adding the Plugin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you have not built FogLAMP yet, follow the steps described |Getting Started|. After the build, you can optionally install FogLAMP following |these INSTALLATION| steps.


- If you have started FogLAMP from the build directory, copy the structure of the *foglamp-south-dht11/python/* directory into the *python* directory:

.. code-block:: console

  $ cd ~/FogLAMP
  $ cp -R ~/foglamp-south-dht11/python/foglamp/plugins/south/dht11 python/foglamp/plugins/south/
  $

- If you have installed FogLAMP by executing ``sudo make install``, copy the structure of the *foglamp-south-dht11/python/* directory into the installed *python* directory:

.. code-block:: console

  $ sudo cp -R ~/foglamp-south-dht11/python/foglamp/plugins/south/dht11 /usr/local/foglamp/python/foglamp/plugins/south/
  $

.. note:: If you have installed FogLAMP using an alternative *DESTDIR*, remember to add the path to the destination directory to the ``cp`` command.


- Add service

.. code-block:: console

   $ curl -sX POST http://localhost:8081/foglamp/service -d '{"name": "dht11", "type": "south", "plugin": "dht11", "enabled": true}'

.. note:: Each plugin repo has its own debian packaging script and documentation, And that is the recommended way to go! As above method(s) may need explicit action for linux and/or python dependencies installation.

Using the Plugin
~~~~~~~~~~~~~~~~

Once south plugin is added as an enabled service, You are ready to use the DHT11 plugin.

.. code-block:: console

   $ curl -X GET http://localhost:8081/foglamp/service | jq

Let's see what we have collected so far:

.. code-block:: console

  $ curl -s http://localhost:8081/foglamp/asset | jq
  [
    {
      "count": 158,
      "asset_code": "dht11"
    }
  ]
  $

Finally, let's extract some values:

.. code-block:: console

  $ curl -s http://localhost:8081/foglamp/asset/dht11?limit=5 | jq
  [
    {
      "timestamp": "2017-12-30 14:41:39.672",
      "reading": {
        "temperature": 19,
        "humidity": 62
      }
    },
    {
      "timestamp": "2017-12-30 14:41:35.615",
      "reading": {
        "temperature": 19,
        "humidity": 63
      }
    },
    {
      "timestamp": "2017-12-30 14:41:34.087",
      "reading": {
        "temperature": 19,
        "humidity": 62
      }
    },
    {
      "timestamp": "2017-12-30 14:41:32.557",
      "reading": {
        "temperature": 19,
        "humidity": 63
      }
    },
    {
      "timestamp": "2017-12-30 14:41:31.028",
      "reading": {
        "temperature": 19,
        "humidity": 63
      }
    }
  ]
  $


Clearly we will not see many changes in temperature or humidity, unless we place our thumb on the sensor or we blow warm breathe on it :-)

.. code-block:: console

  $ curl -s http://localhost:8081/foglamp/asset/dht11?limit=5 | jq
  [
    {
      "timestamp": "2017-12-30 14:43:16.787",
      "reading": {
        "temperature": 25,
        "humidity": 95
      }
    },
    {
      "timestamp": "2017-12-30 14:43:15.258",
      "reading": {
        "temperature": 25,
        "humidity": 95
      }
    },
    {
      "timestamp": "2017-12-30 14:43:13.729",
      "reading": {
        "temperature": 24,
        "humidity": 95
      }
    },
    {
      "timestamp": "2017-12-30 14:43:12.201",
      "reading": {
        "temperature": 24,
        "humidity": 95
      }
    },
    {
      "timestamp": "2017-12-30 14:43:05.616",
      "reading": {
        "temperature": 22,
        "humidity": 95
      }
    }
  ]
  $

Needless to say, the North plugin will send the buffered data to the PI system using the OMF plugin or any other north system using the appropriate north plugin.

|DHT11 in PI|


