NotiPi

   

Notifications via SMS Text or Twitter from the Pi

Fred Sonnenwald and Hamish Cunningham, June 2013

1. Introduction

The general idea of NotiPi, or notifications, is to let the Raspberry Pi interact with you in ways not tied to sitting in front of the monitor. That is to say, to let you know what's going on at a distance. There are different ways to go about this, but they all boil down to sending a bit of text to you in some fashion so that you are aware you've received it. The Raspberry Pi is a general purpose machine, so it is easy to take advantage of existing services like texting phones, or Tweets.

Here we'll look at two options for texting (using the net or using a mobile phone handset) and finish up with the Twitter option.

2. Pi Texting (SMS) via a Web Service

The general idea here is that there are loads of companies out there that offer what is called SMS gateway service. You usually see them in the form of a webpage where you type in some text and a phone number and off it goes — you get a message on your phone. This is the same principle as what we'll have the Pi do, except the Pi will be using something a bit more industrial strength.

The webpage method is a sort of end-user thing that's friendly to you and I, but is a bit more complex to get the Pi talking to. What we want really is a company that specializes in providing the service that those webpages use. If you've ever received an advert on your phone via text, it's what those guys use. (I keep getting messages about debt consolidation, annoyingly!)

BulkSMS

Unfortunately we can't just use any company that provides this service. The Raspberry Pi is running Linux and isn't on an Intel so we need a service that's platform and architecture independent. Browsing and googling around led us to BulkSMS. Sending a text with them costs about 5 pence (you have to buy at least 200 texts to send). Even better though, they quite nicely have published documentation for their HTTP API. This is the written explanation of how programs can talk to their service, which in this case is done in a way similar accessing a web-page, only using a program. Happily there are lots of ways to do this on Linux.

To understand the API (or really any programming concept or protocol) I find that you can approach it in two ways. You can read the documentation and piece together what needs to be done, or you can look at some code that's already been written and work out how that needs to be changed to do what you want it to instead. I prefer the latter, learning from example. BulkSMS has quite a few code samples available. My strongest language of the ones they have available there is PHP and so I dissected that one. The example is comprehensive and quite complete.

To save you the tedium of working through either the API or the example code and here we'll provide you with a rough outline of how it works. Communication with BulkSMS is done over an HTTP POST request. This is the sort of thing that your browser does when you hit the "login" button on a website — your username and password are encoded together in a key-pair format and sent off down the tubes. The technical details are of less interest to us than the key-pair bit. We need to craft together the correct key-pairs (e.g. username=fred&password=imnottelling) so that BulkSMS on the other side knows what we want to do.

The key-pairs

There are 5 bits of information that BulkSMS absolutely needs to get things done. These are as follows:

  • A unique message ID (stop_dup_id). This is an integer (whole number) value between 1 and 2147483647.
  • Your BulkSMS username (username).
  • Your BulkSMS password (password).
  • The message text you're sending (message).
  • The phone number (msisdn). This is including the country code, but without the leading '+'.

All of this information is pretty easy to get a hold of. The next half of the battle is actually sending the message.

Curl

The absolute easiest way to send a message is to use a bit of software that's already been written. We don't need to deal with the tedious creation of HTTP packets, we can let someone else do that bit. Again, we just need to deal with those key-pairs. So we turn to a program called curl which is a command line utility for HTTP and other useful things. What is of particular interest to us is that it can do HTTP POST communications quite easily via the —data-urlencode argument which takes the key=data pair as its parameter. Add one of these to the command for each key-pair and tell curl to go after the service url, http://www.bulksms.co.uk/eapi/submission/send_sms/2/2.0, and that's it. Simple!

curl http://www.bulksms.co.uk/eapi/submission/send_sms/2/2.0 \ 
  --data-urlencode stop_dup_id="some random number" \ 
  --data-urlencode username="your username" \ 
  --data-urlencode password="your password" \ 
  --data-urlencode message="golly wow it works!" \ 
  --data-urlencode msisdn="441632960123"
It can be taken a step further and the whole thing can be wrapped around with a shell script that stores your username and password and can be manipulated from the command line a bit easier. I've written a script which does this, available here. More information of shell programing with bash is available from The Linux Documentation Project (TLDP). It's a bit heavy reading but it's very comprehensive.

(Note: you may get a warning when running the script under Raspbian, it's not necessary, but you can make it go away by editing /etc/locale.gen and uncommenting (delete the #) with the line which has en_GB.iso8859-1 in it. Then running sudo locale-gen. This has to do with the script changing character encoding to the older latin1, which BulkSMS recommends to be used. Character encoding has to do with the way letters are stored digitally. There's no real practical difference here, but there's more info on Wikipedia!)

3. Pi Texting (SMS) via a Phone Handset

In the last section, we looked at sending a text over the internet. What if isn't available? You may find yourself in situations where the ethernet cable or the wifi doesn't reach. Well don't panic, because Linux has you covered. A real, physical cell connection can provide a second mechanism for sending notifications — actually sending SMS messages on a cell phone proper.

There's a handy bit of software called gnokii which lets Linux, or in our case Raspbian, talk with older mobile phones. This is not Android or Windows smartphone territory, but rather that of everyone’s favorite candy-bar bricks of the 90s and early 00s. It's the perfect use for that old phone you've had lying around for years, and let's face it, Nokias are indestructible. If you don't have one they're pretty cheap these days too. Just the sort of bit of kit you want for a fun project.

Equipment

We had an old Nokia 6230i lying around, so our directions are relevant to that. It uses the DKU-2 USB cable to connect to the Pi. Check the list of phones to see if what you already have will work. The USB based setups are ideal, but there are other phones with only serial cables. To use those you'll need a USB to RS-232 (serial) adapter. If all you have is the phone, you can usually find the cables and adapters you need pretty cheaply on Amazon.

You'll also need mobile service to get this to work. A pre-paid SIM chip is ideal as it's cheap. We've got a giffgaff chip as they offer the cheapest SMS rates here in England — a mere 6p a text. Make sure you're phone's unlocked before you get a chip that doesn't work with it! See the Wikipedia page on SIM lock for more info there to work out what you've got.

Setup

We'll have a few things to do before we can get going...

Installing gnokii

First, install gnokii by running sudo apt-get install gnokii in a terminal and hitting Y when prompted to conform the installation. If you're in the default Rasbian GUI, double clicking the LXTerminal icon on the desktop starts a terminal.

Kernel module blacklisting

A kernel module need to be blacklisted to allow gnokii to work. Edit /etc/modprobe.d/raspi-blacklist.conf and add a line which reads:

blacklist cdc_acm 
See how our raspi-blacklist.conf file looks here.

The /etc/gnokiirc configuration file

Rasbian does not install a default configuration file for gnokii so it will have to be copied out of the documentation files. This results in a nice global configuration file, /etc/gnokiirc, being in place. These command should be run as root, so sudo bash must be executed first.

sudo bash
cp /usr/share/doc/gnokii-common/sample/gnokiirc.gz /etc/
cd /etc/
gunzip gnokiirc.gz 
The /etc/gnokiirc needs to be edited next. There is a lot of stuff in here, and most of it isn't relevant, so the bits to be edited will need to be picked out. I use vim as my editor, which can happily show line numbers and make this easier. :set number to get them turned on. Note that the file will need to be edited as root, so the command for me is sudo vim /etc/gnokiirc.

  • Line 13: port = none should be commented (add # in front of the line).
  • Line 47: # port = 1 should be uncommented (remove # from the the front of the line).
  • Line 54: model = fake should be changed to model = series40.
  • Line 94: # connection = dku2libusb should be uncommented.
  • Line 104: connection = serial should be commented.

Make these changes and save. Alternatively you can download our already modified configuration file.

cd /etc
sudo wget https://raw.github.com/hamishcunningham/pi-tronics/master/notipi/conf/gnokii/rasbian/gnokiirc 
For some reason, Rasbian's compilation of gnokii is not set to recognize the /etc/gnokiirc file as a global configuration file. To work around this —config /etc/gnokiirc will have to be added to every gnokii command run later on. Alternatively a softlink can be setup between where Raspbian expects the config file and where we've placed it.

mkdir ~/.config/
mkdir ~/.config/gnokii/
ln -s /etc/gnokiirc ~/.config/gnokii/config 

udev rules

By default when the phone is plugged in, only root will be allowed to access it. This is somewhat less than useful in many cases. Fortunately we can get around this by adding what are called udev rules. This is a special configuration file which lets the system know to do something special in terms of permissions when the phone is plugged in. A file for this is already included in Rasbian, and just needs to be installed.

sudo cp /usr/share/doc/gnokii-common/sample/45-nokiadku2.rules /etc/udev/rules.d/ 

Using gnokii

Now that it's all setup, we should be able to get going with gnokii and start sending messages. Connect the DKU-2 data cable to the Raspberry Pi and the phone. When the Nokia 6230i is connected, it asks about being a data storage device hit no to that. According to lsusb (usbutils package) it shows up like the following to the system:

Bus 001 Device 010: ID 0421:0428 Nokia Mobile Phones 6230i Modem 

To get rid of the data storage device query, simply remove the memory card from the phone. You'll need to do this if you're planning to use the phone with the Pi in an automated environment.

Test the phone's connection by running gnokii —identify. Output should be something like this:

GNOKII Version 0.6.30
LOG: debug mask is 0x1
Config read from file /etc/gnokiirc.
Cannot open logfile /root/.cache/gnokii/gnokii-errors
WARNING: cannot open logfile, logs will be directed to stderr
phone instance config:
model = series40
port = 1
connection = dku2libusb
initlength = default
serial_baudrate = 19200
serial_write_usleep = -1
handshake = software
require_dcd = 0
smsc_timeout = 10
rfcomm_channel = 0
sm_retry = 0
Connecting
Serial device: opening device USB
Ignoring extra header, type 171, length 5
Found FBUS interface
Getting model...
Message sent: 0x1b / 0x0006
00 01 00 07 01 00                               |                 
Message received: 0x1b / 0x0032
01 44 00 08 00 01 58 2c 00 26 56 20 30 33 2e 36 |  D    X, &V 03.6
32 0a 30 34 2d 4e 6f 76 2d 30 35 0a 52 4d 37 32 | 2 04-Nov-05 RM72
5f 37 33 5f 2d 0a 47 53 4d 20 50 31 2e 0a 43 00 | _73_- GSM P1. C 
00 00                                           |                 
Received message type 1b
model length: 9
Received model RM72_73_-
Found model "RM72_73_-"
Identifying...
Message sent: 0x1b / 0x0005
00 01 00 00 41                                  |     A           
Message sent: 0x1b / 0x0006
00 01 00 07 01 00                               |                 
Message received: 0x1b / 0x001a
01 44 00 01 00 01 41 14 00 10 XX XX XX XX XX XX |  D    A   XXXXXX
XX XX XX XX XX XX XX XX XX 00                   | XXXXXXXXX       
Received message type 1b
Received imei [REDACTED]
Message received: 0x1b / 0x0032
01 44 00 08 00 01 58 2c 00 26 56 20 30 33 2e 36 |  D    X, &V 03.6
32 0a 30 34 2d 4e 6f 76 2d 30 35 0a 52 4d 37 32 | 2 04-Nov-05 RM72
5f 37 33 5f 2d 0a 47 53 4d 20 50 31 2e 0a 43 00 | _73_- GSM P1. C 
00 00                                           |                 
Received message type 1b
Received revision V 03.62
model length: 9
Received model RM72_73_-
IMEI         : [REDACTED]
Manufacturer : Nokia
No flags section in the config file.
Model        : RM72_73_-
Product name : RM72_73_-
Revision     : V 03.62
Serial device: closing device 

To send a text message is now simple:

echo “Message.” | gnokii --sendsms <phone number> 
Let a text be sent!

Errors!

You may have some problems running gnokii. If you get a PHONET error, the kernel module hasn't black listed properly. Re-check that. If it's a complaint about permissions try running as root and with the —config option set as mentioned above. There may be a problem with udev not having taken up the rules correctly.

I'm using Fedora!

It's OK! Lots of stuff is the same or similar. The blacklist file is instead /etc/modprobe.d/blacklist.conf and requires three modules to be added:

blacklist cdc_acm
blacklist cdc_phonet
blacklist phonet
We have one already done.

/etc/gnokiirc is already in place and the lines to be edited are the same. There's just one more to be done:

  • Line 127: use_locking = yes should be changed to no.

We also have one done too.

Fedora however doesn't include an set of udev rules. We've made our own.

cd /etc/udev/rules.d/
sudo wget https://raw.github.com/hamishcunningham/pi-tronics/master/notipi/conf/gnokii/fedora/40-basic-permissions.rules 

Other resources

Hopefully we've covered everything you need to get started. If you need more help we're not the first ones to look into this. We're not even the first ones to do it with a Raspberry Pi. Some other guides:

Guides with just a regular setup:

There are also some more generic pages which might be of use if you're having trouble:

A bit of googling should turn up more stuff too!

4. Pi Messaging via Twitter

Did you bump into a lamp-post last time you walked down the street? Are you developing hunched shoulders and a cricked neck? Do your thumbs have more muscle on them than your arms? These are all classic signs of becoming a twitter-head... those conversations are just so important and fast-moving that you've got to keep track at all times.

Don't worry — we're here for you. Your trusty Pi can tweet at you, so now you can programme a cron script to pull data out of Google Calendar and remind you about your Granny's birthday or your dentist appointment or whatever.

The main hoop we have to jump through to do this is authentication. Dom Rout has written a Python library to make this easier, which lives on GitHub at https://github.com/domrout/python-twitter-wrapper

To install it, use PIP (sudo apt-get install python-pip to get hold of it) like this:

pip install -e git+https://github.com/domrout/python-twitter-wrapper.git#egg=TwitterWrapper
Once installed, you need a Twitter API consumer key and secret. You can get these by logging into https://dev.twitter.com/ and setting up an application.

Once you've done that, there's a script at https://github.com/domrout/python-twitter-wrapper/blob/master/scripts/authenticate_twitter that requests a proper OAuth token for your application and user. It sends you to the Twitter site wherein you can enter your username and password.

Once all of that has been done, the snippet goes like:

import twitterwrapper

api = twitterwrapper.Api()

# Post an update
new_status = api.statuses.update("I'm tweeting programmatically!")

# Delete that update.
new_status.destroy()
Happy tweeting — but do try to straighten up now and then, just to keep the blood flowing!