The MQTT letterbox Part 2: Sending alerts from MQTT // Tutorial

This is part 2 of my Uber letterbox where I show you how to send notifications to your phone when someone delivers a letter.
If you haven’t seen Part 1 yet, then check that out first.


Software

So, I have my letter box sending MQTT messages to my MQTT Broker when someone delivers a letter or when someone checks the mail, but that’s only the first part. Now to have notifications sent to my phone.

For this I’ll be using MQTTwarn with IFTTTT.

MQTTwarn is a great bit of Python code created by Jan-Piet Mens. He has created a framework that supports a bucket load of Internet services and it’s fairly easy to add your own.

So, first we need to install the required Python PIP package.

apt-get install python-pip

Then install the PAHO MQTT package via Python PIP.

pip install paho-mqtt

Next install GIT as we’ll be using it to pull the source code from GitHub.

apt-get install git

Then we can pull the source, which will place it in the /opt directory.

cd /opt
git clone https://github.com/jpmens/mqttwarn.git

Then change to that directory.

cd /opt/mqttwarn

Add the mqttwarn user.

useradd --shell /bin/bash --home-dir /opt/mqttwarn mqttwarn

Copy the startup defaults file,

cp -i etc/mqttwarn.default /etc/default/mqttwarn

the systemd service file so it’ll start as a service.

cp -i etc/mqttwarn.service /lib/systemd/system/

the logrotate file so we don’t fill up the filesystem with logs,

cp -i etc/mqttwarn.logrotate /etc/logrotate.d/mqttwarn

create the mqttwarn log file directory and change the owner to the mqttwarn user.

mkdir /var/log/mqttwarn
chown mqttwarn:mqttwarn /var/log/mqttwarn

Before you start the service you’ll need to make a change to the service file, which is to remove the virtual Python environment. If you use it, then of course leave it in.

Then enable the mqttwarn service.

systemctl enable mqttwarn

Moving to your phone install the IFTTT app from the App Store. There’s also an Android app for this. It’s all the same process really.
Once installed you’ll need to create an account, or if you have one already, just login.

Then fire up a browser. You can actually do these next steps from your phone as well, but the website looked a bit clearer for this video. Sign in with your account, I always use two-factor authentication for everything and would suggest enabling it for added security.

Next we need to connect an IFTTT service to your account, so click on the search link and search for webhooks. Click on that and then you can connect this to your IFTTT account.

Click on Settings as you will need to record for later, the Webhooks key that has been created.

Now you’ll need to create an applet for MQTTwarn to reference, click on “New Applet”,

then click on the ‘this’ link and search for webhooks.

Click on the webhooks link and then “Receive a web request”.

Now, type in the event name. I used LetterBox. Remember this name as you’ll need this later as well.

Then click on the ‘that’ link so you can tie the event to a service action.

Search for notification. You could really use anything else for this.

If you haven’t yet connected this service to your account it’ll prompt you to connect.

Then click on the “Send a notification” link.

This is where you can customize the notification message that gets sent to you. Since I want to see how many deliveries have be made, I set it to this. The number of deliveries will be contained in Value1.

Then click on “Create Action” and then “Finish”.

And that’s it for IFTTT, now back to your MQTT Broker. First make the /etc/mqttwarn directory, and create a file called mqttwarn.ini with your favourite editor.

mkdir -p /etc/mqttwarn
vi /etc/mqttwarn/mqttwarn.ini

There are several key elements to the ini file.

[defaults]
hostname     = 'mqtt.homenet'
port         = 1883
username     = mqttwarn
password     = mqttwarn
clientid     = 'mqttwarn'
lwt          = 'Home/MQTTwarn/State'
skipretained = False
cleansession = False

; MQTTv31 = 3 | MQTTv311 = 4
protocol     = 4

; logging
logformat = '%(asctime)-15s %(levelname)-5s [%(module)s] %(message)s'
logfile   = '/var/log/mqttwarn/mqttwarn.log'

; one of: CRITICAL, DEBUG, ERROR, INFO, WARN
loglevel  = DEBUG

; name the service providers you will be using.
launch    = file, log, ifttt

[config:file]
append_newline = True
targets = {
    'mylog'     : ['/tmp/mqtt.log']
    }

[config:log]
targets = {
    'info'   : [ 'info' ]
  }

[config:ifttt]
targets = {
    'notify'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBox' ]
  }

[Home/#]
targets = file:mylog, log:info

[Home/LetterBox/Delivery]
targets = ifttt:notify

The hostname of your MQTT server and the port number that the MQTT service is listening on.

hostname     = 'mqtt.homenet'
port         = 1883

The username and password of the MQTT user. Check out my MQTT installation video on how to do this.

username     = mqttwarn
password     = mqttwarn

Or if you’re in a hurry you can type this at the shell prompt.

mosquitto_passwd /etc/mosquitto/passwd mqttwarn

The clientid is used by the MQTT Broker to name clients.

clientid     = 'mqttwarn'

The ‘lwt’ option will Publish a Topic message to the MQTT Broker when mqttwarn stops and starts.

lwt          = 'Home/MQTTwarn/State'

We don’t need to worry about skipretained and cleansession for the moment.

skipretained = False
cleansession = False

Make sure you set your protocol to version 4 for new installs otherwise you’ll see authorized errors in the log file

protocol     = 4

Where the location and message format can be configured here.

logformat = '%(asctime)-15s %(levelname)-5s [%(module)s] %(message)s'
logfile   = '/var/log/mqttwarn/mqttwarn.log'

loglevel  = DEBUG

You can also create functions that will translate MQTT data formats to service formats, but I’m not using this, so it’s commented out.

#functions = 'samplefuncs'

Next I load up three service providers: file, log and IFTTT.

launch    = file, log, ifttt

These are referenced by these three sections. The file service will simply log data to a file.

[config:file]
append_newline = True
targets = {
    'mylog'     : ['/tmp/mqtt.log']
    }

The log service will send messages to syslog,

[config:log]
targets = {
    'info'   : [ 'info' ]
  }

and the IFTTT service is the one we’re interested in. Remember the key that I said to record? You’ll need to enter it here, and also the Event name from the WebHooks service from IFTTT.

[config:ifttt]
targets = {
    'notify'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBox' ]
  }

Next you’ll need to tell mqttwarn what services are subscribed to what topics. You can see that all Topics starting from Home will be sent to syslog and a local file,

[Home/#]
targets = file:mylog, log:info

and only Topics from Home/LetterBox/Delivery will be sent to IFTTT.

[Home/LetterBox/Delivery]
targets = ifttt:notify

Now, just restart the mqttwarn service and you’re done. That’s it! Pretty easy.

systemctl restart mqttwarn

So, does it work? Using a fake publish message from the MQTT server.
Yup. Works OK.

It would also be nice to send a notification when some checks the mail. Add in another target in the IFTTT section. Remember the event name for the IFTTT applet. Then create a new subscription on the Check Topic.

[config:ifttt]
targets = {
    'notify'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBox' ],
    'check'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBoxCheck' ]
  }

[Home/#]
targets = file:mylog, log:info

[Home/LetterBox/Delivery]
targets = ifttt:notify

[Home/LetterBox/Check]
targets = ifttt:check

Then moving back to the IFTTT website we need to create a new applet based on the WebHook service, this time use the event name you used in the mqttwarn file, and set the notification message to something appropriate and click Finish.

Testing it out with some dummy messages. Yup, works OK.

The MQTT Broker will automatically publish a message to the Home/LetterBox/State topic when the letterbox dies because the letterbox has declared a last will.

Also, when the ESP8266 boots up another message will be published.

So, it’d be nice to have alerts sent for the current state of the letterbox. Adding this in is fairly trivial as well. Add the subscribe section and target in to the mqttwarn ini file and go through a similar process on the IFTTT website.

[config:ifttt]
targets = {
    'notify'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBox' ],
    'check'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBoxCheck' ],
    'state'   : [ 'dT2dZsuX_QeBZL-FSO040L', 'LetterBoxState' ]
  }

[Home/#]
targets = file:mylog, log:info

[Home/LetterBox/Delivery]
targets = ifttt:notify

[Home/LetterBox/Check]
targets = ifttt:check

[Home/LetterBox/State]
targets = ifttt:state

Yup, works well.