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…
from the name of the definition itself. For
[config:xxx]
, it would bexxx
.[config:xxx]
from the value of the optional
module
option within that configuration section, when given.[config:custom-service] module = xxx
Note
A service definition using the
module = xxx
variant will use the Python modulexxx
, however it has its own distinct set of service options. It is thus possible to have several service configurations for the same underlying service, with different configurations, e.g. one for files that should have notifications appended, and one for files that should get truncated before writes.Example
Consider this configuration file in which we want two services of type log. We launch an additional
xxxlog
service here, also based on thelog
module.# Note how both services must be launched. [defaults] launch = log, xxxlog # Configure two individual services, both using the `log` module. [config:log] targets = { 'debug' : [ 'debug' ], } # Note how the xxxlog is instantiated from log. [config:xxxlog] module = log targets = { 'debug' : [ 'debug' ], } # The topic subscription rule using both services. [topic/1] targets = log:debug, xxxlog:debug
Resolving the module#
There are three options how the module name will be resolved to a Python module.
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.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.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.
Example
[defaults]
; name the service providers you will be using.
launch = log, file, acme.foobar
[config:acme.foobar]
targets = {
'default' : [ 'default' ],
}
[test/plugin-module]
; echo '{"name": "temperature", "value": 42.42}' | mosquitto_pub -h localhost -t test/plugin-module -l
targets = acme.foobar:default
format = {name}: {value}
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.
Example
[defaults]
; name the service providers you will be using.
launch = log, file, acme/foobar.py
[config:acme/foobar.py]
targets = {
'default' : [ 'default' ],
}
[test/plugin-file]
; echo '{"name": "temperature", "value": 42.42}' | mosquitto_pub -h localhost -t test/plugin-file -l
targets = acme/foobar.py:default
format = {name}: {value}
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{}
}