SMS Alerts

How to set up SMS alerts using Webhooks

The Airthings API can be combined with other APIs to allow for the creation of a powerful automatic SMS messaging service that can alert you when any of the sensors on your Wave devices reach dangerous levels. Your radon levels in particular are one of the most important attributes measured by your Wave Plus devices, and dangerous levels of radon are absolutely something you should be alerted about as soon as possible. By utilising Twilio, a cloud communications platform, and an Airthings webhook we can do exactly that!

Throughout this tutorial, you will:

  1. Set up a Twilio trial account.
  2. Create an Airthings webhook.
  3. Host your own (temporary) example application that will be periodically listen to webhook requests.

For those who want to get right into the code, the example can be found one of our Github repositories. We have both a Python and Node example.

Creating your Twilio Account

Before getting started set up a Twilio trial account using a valid mobile phone number. When creating the account select Get a Trial Number once you reach the dashboard. With Twilio you will need this number so you can send SMS messages.

Before choosing ensure that the number is capable of sending SMS messages to and from mobile numbers, you will be made aware of this when Twilio presents the number to you. Try Twilio's trial account guide for more details on setting up mobile numbers.

From Twilio you will need your:

  • Trial phone number
  • Account SID
  • Auth Token

All of these can be found on the Twilio dashboard.

Building the initial code

In one of the programming languages detailed below we can create a method to use our Twilio trial number to send messages to our own mobile number. The code below can be used with any Twilio account as long as the correct Twilio credentials and phone number are provided.

const client = require('twilio')(accountSid, authToken);

module.exports = {
	twilioAccount: (message, number_from, number_to) => {
	client.messages
  .create({
     body: message,
     from: number_from,
     to: number_to
   })
  .then(message => console.log(message.sid));
}
};
from twilio.rest import Client

class TwilioSMSAccount:
    def __init__(self, account_sid, auth_token):
        self.client = Client(account_sid, auth_token)

    def send_sms(self, message, number_to, number_from):
        self.client.messages.create(
            to=number_to,
            from_=number_from,
            body=message)

The simple web application code can be found below. We listen on the /airthings-webhook endpoint for POST requests that allows us to parse data sent from a webhook. If the Radon levels in our device are 50 becquerels or higher we use Twilio to alert us of the devices that meet this requirement and we send an SMS message.

'use strict';
const http = require('http');
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const twilio = require('./twilioNode');

app.set('view engine', 'ejs');
app.use(
	bodyParser.urlencoded({
		extended: true
	})
);
app.use(express.static('public'));
app.use(bodyParser.json());

app.post('/airthings-webhook', (req, res) => {
	let devices = [];
	for (let deviceinfo in req.body.data) {
		if (req.body.data[deviceinfo].radonShortTermAvg >= 50) {
			devices.push(req.body.data[deviceinfo].serialNumber);
		}
	}
	if (devices.length > 0) {
		twilio.twilioAccount(
			'ALERT: Radon levels are above 50 becquerels in the following devices:\n'
			+ devices.reduce((allDevices, device) => allDevices + device + '\n'),
			'<number_from>',
			'<number_to>',
		);
	}
	res.sendStatus(200);
});

http.createServer(app).listen(3000, () => {
	console.log('Express server listening on port 3000');
});
# /usr/bin/env python
from flask import Flask, request, abort
from twilioPython import TwilioSMSAccount

app = Flask(__name__)

# Setup Twilio account
twilioAccount = TwilioSMSAccount("<account_sid>", "<auth_token>")

@app.route("/airthings-webhook", methods=['POST'])
def airthings_reply():
    """Respond to incoming Airthings measurements"""
    if request.method == 'POST':
        devices = []
        for device in request.json['data']:
            if device['radonShortTermAvg'] >= 50.0:
                devices.append(device['serialNumber'])
        if devices:
            twilioAccount.send_sms('ALERT: High levels of Radon measured in the following devices with serial number: \n' + device['serialNumber'])
        return '', 200
    else:
        abort(400)

if __name__ == "__main__":
    app.run(debug=True)

Creating an Airthings Webhook and Running the example

Before we can create our webhook I recommend installing and using ngrok. It creates safe and secure temporary tunnels to web applications running on localhost.
Once installed follow the steps below:

node basic-node.js
python basic-flask.py
ngrok http 3000

Note the https link provided by ngrok.


Session Status                online
Account                       Tyler
Version                       2.3.35
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://c6fb79ca.ngrok.io -> http://localhost:3000
Forwarding                    https://c6fb79ca.ngrok.io -> http://localhost:3000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00

Now that ngrok is set up you can create a webhook by following the following flow:

An example webhook will look something like the image below. Remember to add the https link provided by ngrok and your desired endpoint.

Our example will only send a text if we receive radon levels above 50. You can change this value to 0, restart your code, then click the Test Webhook button just so we can make sure everything is set up correctly.

Upon testing the webhook you should receive a text like the following:

Hopefully you won't get into a situation where you actually need to receive this kind of text, but it's much more reassuring to be alerted as soon as possible for something as important as radon. And of course this code can be extended to look at any of the other parameters on our devices.