Services#

Introduction#

This section of the documentation will outline how to configure mqttwarn services. Services are instances of service plugins, using Python modules to implement notifier components.

Later, you will learn how to subscribe to MQTT topics, and map them to the services you have defined here.

You can choose from a variety of Notifier catalog, or you can write your own notification plugin easily, see Creating custom notification plugins.

Configuration#

Configuration sections called [config:xxx] configure settings for a service, where xxx is the name of the service. When a service is launched, a corresponding section is mandatory to be present in the mqttwarn configuration file.

A service configuration section has a mandatory option called targets, which is used to define groups of multiple recipients or targets. It is expected to be a dictionary, where each item defines an individual service point for a particular service.

The keys are target names, and the structure and value depends on what the particular service plugin implementation expects.

The original configuration variant, still used by many service plugins, looks like this.

[config:xxx]
targets = {
    'targetname1': [ 'address1', 'address2' ],
    'targetname2': [ 'address3', 'address4' ],
  }

Note

Historically, as outlined in the example above, the value / right-hand side of the recipient/target group map, was exclusively defined as a list, and as such, the term address list was used.

Nowadays, after a few evolution cycles of mqttwarn, the value can have a different data type and structure, depending on the particular service plugin. As such, the term target address descriptor is used now.

For example, after implementing named target address descriptor options, the configuration of the Pushsafer service plugin is much more capable now.

[config:pushsafer]
targets = {
    'basic': { 'private_key': '3SAz1a2iTYsh19eXIMiO' },
    'extraphone': { 'private_key': '3SAz1a2iTYsh19eXIMiO', 'time_to_live': 60, 'priority': 2, 'retry': 60, 'expire': 600, 'answer': 0 }
    }

Other than the mandatory targets option, and an optional module option, these sections may have more options. Some of them may even be required for a particular service.

Effectively, this configuration snippet defines individual groups of “target addresses” for a particular service, and assigns them “target names”. Using those groups, it is, for example, possible to define different…

  • target paths for the file service.

  • database tables for the mysql service.

  • topic names for outgoing mqtt publishers.

  • hostname/port number combinations for xbmc, etc.

General options#

Individual services offer different configuration options, however there are a few settings optionally available to all services.

For example, the decode_utf8 option, which is True by default, can be turned off for a whole service definition. This makes it suitable to receive and process binary or other non-UTF8 data.

# Don't assume incoming MQTT message to be encoded in UTF-8.
# This is applicable for receiving and processing binary data.
decode_utf8 = False

Launching services#

In order to launch configured services, you will have to add them to the global defaults section of the mqttwarn.ini configuration file. For launching multiple services, please use a comma-separated list.

[defaults]
launch = xxx, foo

Module resolvement#

Resolving the name#

The Python module name for the service will be determined…

  1. from the name of the definition itself. For [config:xxx], it would be xxx.

    [config:xxx]
    
  2. from the value of the optional module option within that configuration section, when given.

    [config:custom-service]
    module = xxx
    

Resolving the module#

There are three options how the module name will be resolved to a Python module.

  1. When the module name is a plain string without a dot, and does not end with .py, it will be resolved to a module filename inside the built-in mqttwarn/services directory.

  2. When the module name contains a dot, and does not end with .py, it will be resolved as an absolute dotted reference to a Python module, see From package.

  3. When the module name ends with a .py suffix, it will be treated as a reference to a Python file, see From file.

Loading external services#

In order to bring in custom sink components to mqttwarn in form of service notification plugins, there are two options. We will explore them on behalf of corresponding example configuration snippets.

From package#

When the module name contains a dot, and does not end with .py, it will be resolved as an absolute dotted reference using Python’s importlib. In this way, it is easy to load modules from other packages than mqttwarn.

This configuration snippet outlines how to load a custom plugin from a Python module referenced in “dotted” notation. Modules will be searched for in all directories listed in sys.path, so any installed Python package will be available. Additional directories can be added by using the PYTHONPATH environment variable.

From file#

When the module name ends with a .py suffix, it will be treated as a reference to a Python file. It can be either absolute, or relative to the current working directory, or relative to the directory of the configuration file.

This configuration snippet outlines how to load a custom plugin from a Python file referenced by file name. When relative file names are given, they will be resolved from the directory of the mqttwarn.ini file, which is, by default, the /etc/mqttwarn folder.

Creating custom notification plugins#

Creating new service plugins is easy, and we recommend you use the file plugin as a blueprint and start from there.

Plugins are invoked with two arguments, srv and item. srv is an object with some helper functions, and item a dictionary which contains information on the message which is to be handled by the plugin. item has the following top-level keys:

item = {
    'service'       : 'string',       # Name of handling service (`twitter`, `file`, ...)
    'target'        : 'string',       # Name of target (`o1`, `janejol`) in service
    'addrs'         : list,           # List of addresses from SERVICE_targets
    'config'        : dict,           # None or dict from SERVICE_config {}
    'topic'         : 'string',       # MQTT topic the message was received on
    'payload'       : 'string',       # Raw message payload
    'message'       : 'string',       # Formatted message (if no format string, then equals payload)
    'data'          : None,           # Dictionary with transformation data
    'title'         : 'mqttwarn',     # Optional title from title{}
    'priority'      : 0,              # Optional priority from priority{}
}