Forward OwnTracks low-battery warnings to ntfy#

About#

By subscribing to your OwnTracks MQTT topic, and adding a user-defined filter function, you can make mqttwarn send notifications, for example when your phone battery level decreases below a certain threshold.

Details#

As an example, this tutorial will submit notifications to a public topic on ntfy.sh. However, you can always choose a different notification service provided by mqttwarn, or run your own instance of ntfy. A list of all options is presented on the Notifier catalog page.

The tutorial will expect that you installed the mqttwarn command-line program on your machine, so that you can run it within your terminal. There are different options to install mqttwarn.

Configuration#

Within the mqttwarn configuration file, the launch setting within the The [defaults] section, and the [config:ntfy] service section will define ntfy as a notification target.

The topic section [owntracks/#] will define the MQTT topic mqttwarn will subscribe to, here owntracks/#. Its configuration settings filter, format, and targets, will instruct mqttwarn to format the outbound message like defined by a template string, and dispatch it to the corresponding target address descriptor slot ntfy:testdrive.

# Forward OwnTracks low-battery warnings to ntfy.
# https://mqttwarn.readthedocs.io/en/latest/examples/owntracks-ntfy/readme.html

[defaults]
functions = mqttwarn-owntracks.py
launch    = ntfy

[config:ntfy]
targets   = {'testdrive': 'https://ntfy.sh/testdrive'}

[owntracks/#]
filter    = owntracks_batteryfilter()
format    = My phone battery is getting low ({batt}%)!
targets   = ntfy:testdrive

The user-defined filter function owntracks_batteryfilter() will inspect OwnTracks’ JSON event payload for the value of your phone’s battery level.

"""
Forward OwnTracks low-battery warnings to ntfy.
https://mqttwarn.readthedocs.io/en/latest/examples/owntracks-ntfy/readme.html
"""
import json


def owntracks_batteryfilter(topic: str, message: str):
    ignore = True
    try:
        data = dict(json.loads(message).items())
    except:
        data = None

    if data and "batt" in data and data["batt"] is not None:
        ignore = int(data["batt"]) > 20

    return ignore

Usage#

Using three terminal sessions, and one browser session, you can exercise the tutorial interactively.

Setup#

First, let’s start the Mosquitto MQTT broker.

docker run --name=mosquitto -it --rm --publish=1883:1883 eclipse-mosquitto:2.0 mosquitto -c /mosquitto-no-auth.conf

Let’s acquire the configuration file mqttwarn-owntracks.ini, and the user-defined functions file mqttwarn-owntracks.py, and start mqttwarn.

wget https://github.com/mqtt-tools/mqttwarn/raw/main/examples/owntracks-ntfy/mqttwarn-owntracks.ini
wget https://github.com/mqtt-tools/mqttwarn/raw/main/examples/owntracks-ntfy/mqttwarn-owntracks.py
mqttwarn --config-file=mqttwarn-owntracks.ini

Before dry-run publishing a JSON message, in order to validate your setup, subscribe to the ntfy topic testdrive, either using your browser of choice,

open https://ntfy.sh/testdrive

or a commandline-based HTTP client like curl.

curl -s https://ntfy.sh/testdrive/json

Self-test#

Now, when publishing a minimal example JSON event payload, mqttwarn will run a notification to ntfy when the battery level threshold is reached, as instructed.

echo '{"batt": 19}' | mosquitto_pub -t 'owntracks/testdrive' -l

A JSON event with a battery level above the minimum threshold will not trigger a notification.

echo '{"batt": 42.42}' | mosquitto_pub -t 'owntracks/testdrive' -l

An invalid message, which can’t be decoded, will also not trigger a notification.

echo 'foobar' | mosquitto_pub -t 'owntracks/testdrive' -l

Appendix#

This section demonstrates a few alternative methods for solving different aspects of this recipe, and also includes administrative information.

Running mqttwarn as container#

This command will run mqttwarn in a container, using the docker command to launch it. Alternatively, podman can be used. It expects an MQTT broker to be running on localhost, so it uses the --network=host option. The command will mount the configuration file and the user-defined functions file correctly, and will invoke mqttwarn with the corresponding --config-file option.

docker run --rm -it --network=host --volume=$PWD:/etc/mqttwarn \
  ghcr.io/jpmens/mqttwarn-standard \
  mqttwarn --config-file=mqttwarn-owntracks.ini

Running ntfy as container#

While this tutorial uses the ntfy service at ntfy.sh, it is possible to run your own instance. For example, use Docker or Podman.

docker run --name=ntfy --rm -it --publish=5555:80 \
  binwiederhier/ntfy serve --base-url="http://localhost:5555"

In this case, please adjust the ntfy configuration section [config:ntfy] to use a different URL, and make sure to restart mqttwarn afterwards.

[config:ntfy]
targets   = {'testdrive': 'http://localhost:5555/testdrive'}

Backlog#

Todo

  • [o] Define battery threshold level within the configuration file.