Finally I got a second Raspberry for tinkering as the old one is now operating as my own calendar and address server (which is pretty useless if the “agencies” really can monitor and decrypt HTTPS, SSL, VPN and every other means of communication). And I have been to my “evidence vault” and found an old UMTS-modem, a Huawei E220. So the most obvious thing to do was to send and receive short message texts (SMS) via my Raspberry Pi. There are some frameworks out there that do this from scratch, but I wanted to dig a little deeper and do it by myself. So read on and I will reference some of the available tools and show you my proof of concept.
There are numerous USB-modems out there. I first tried to use an Huawei E167 with my Pi but that didn’t work out. The modem, connected via USB, got disconnected from the Pi every 5 minutes or so, leaving it unusable. With the Huawei E220 (which despite its higher number I bought one year earlier than the E167) I didn’t have that problem. And, surprisingly, because the older modem is much bigger it has a bigger antenna, thus having better reception even when hidden behind some furniture!
So the first thing was to check if the modem gets recognized. UMTS-modems do consume a lot of power, so I used a Y-cable that uses two USB ports, one for power and signals, the second plug for additional power. I recommend using a powered USB-hub. When I connected the cable directly to the Pi, it stopped working. Now here is a picture of the modem I am using:
Of course you will need a SIM-card to use the modem. I bought a very cheap one from (Germans only here) “Tchibo” as a pre-paid card that is valid for one year. It came with 5 Euros credit to spend so I was able to start right away.
Huawei modems do have a special partition in their firmware that announces a CD-ROM drive to the operating system when connected. In this partition the drivers and a software for operating the modem are located. As this is generally a good idea as you have everything you need to operate the modem within the modem, this is exactly what we do not need with the Pi. So the first step would be to check if the modem gets recognized and then get rid of the CD partition.
Connecting the modem
The following steps can be done without any SIM card in the modem. I prefer this method as it prevents me from doing something stupid that may cause horrendous costs or render the SIM card unusable…
With the Pi running just plug in the modem. Wait a few seconds, then run the command
to check if the modem gets recognized at all. You should get something like this:
Clearly, the Huawei modem is recognized by the system. Excellent. Although I have no idea why my E220 modem gets recognized as an E169/E620/E800 type. If you happen to see an additional CD-drive, this is OK, I will cover that in a second.
Now it is time to check if the Pi created any devices for the modem (which it should do automatically). Type
sudo dmesg | grep usb
This should display all connected USB devices, including the modem. The modem entries look like this:
Don’t worry about the three entries for the GSM modem, the first one is the one we are going to use. In human understandable terms the first “GSM modem” line reads: A GSM modem was detected, the hardware is numbered as “1-220.127.116.11” and a device “ttyUSB0” has been created. You can check this with “ls -al /dev/ttyUSB0”, which should give an output like this:
crw-rw---T 1 root dialout 188, 0 Sep 12 16:57 /dev/ttyUSB0
Getting rid of the CD drive and other useful configurations
If you happen to see an additional CD drive, the following steps will disable that feature on the modem. Why is there a CD partition, anyway? Simple answer: in this partition the Huawei people did save driver and software for the modem so that it can be used without downloading anything. Pretty clever. Plug the modem in, install the needed bits from its internal CD partition and you are ready to go.
Using it with the Pi means problems. At least I made the experience that with the CD partition enabled, things didn’t work out.
The Huawei modems recognize a number of system commands that we can use to configure the internals of the modem. To do this we need access to the modem via its serial interface. So we need a terminal program. I chose “picocom” which can be downloaded using the apt package manager:
sudo apt-get install picocom
A short manual is included as a manpage (type “man picocom” in the shell, or look here).
So what do we need to configure next? During my tinkering I discovered a set of obstacles that I needed to get rid of:
- The modem announcing a CD partition to the operating system
- The need to manually input the SIM’s PIN number at every start
- Frequent disconnects when changing from GSM to UMTS networks
So we are using the AT-system commands to remove all these things once and for all… To connect to the modem using picocom type (the last letter is a small “L” (not a “one”:
picocom /dev/ttyUSB0 -b 115200 -l
You should get a screen like this:
Now, if you type “AT”, followed by “Enter” (the key) it should display “OK”. If all goes as expected, you are now connected to the modem.
To remove the CD partition we use the “AT^U2DIAG” command. The “^” needs to be displayed on screen, on my Mac I need to type “^” followed by the space-key. Type:
The U2DIAG-command is very versatile. It can be used to activate different operating modes of the modem:
- AT^U2DIAG=0 – the device is only modem
- AT^U2DIAG=1 – device is in modem mode + CD ROM
- AT^U2DIAG=255 – the device in modem mode + CD ROM + card reader
- AT^U2DIAG=256 – the device in modem mode + card reader
To check if everything worked well, exit picocom by typing
that is: press the CTRL-key (and hold it pressed), then type “a” and then (CTRL still pressed) “x”.
Next, we configure the modem to NOT ask for the SIM PIN any more. Replace xxxx with your PIN! Of course this step needs a SIM card inserted in the modem.
You can re-enable the PIN constraint with “AT+CLCK=”SC”,1,”xxxx”.
Now exit picocom, unplug the modem and replug it to let the changes take effect. If you do a “dmesg | grep usb” now, it should not display an additional CD-rom drive.
I encountered frequent disconnects/connects with my modem at first. A little bit of poking around and (luckily) looking at the modem at the exact moment it got disconnected brought the solution: whenever the modem changes the network type, that is going from GPRS to UMTS (3G) and vice versa, it did disconnect (and that was visible by the LED changing its color). As I only wanted to send and receive text messages I decided to configure the modem to use GPRS only. I do not need UMTS (3G) functionality with that modem ever. So lets get this done.
Connect to the modem with picocom (as above) and type:
You should get something like
There are 4 modes that can be selected for operation:
- Only GPRS/EDGE: 13,1,3FFFFFFF,2,4
- Only 3G: 14,2,3FFFFFFF,2,4
- Preferred GPRS/EDGE: 2,1,3FFFFFFF,2,4
- Preferred 3G: 2,2,3FFFFFFF,2,4
All we need to do is activate the mode we need: “Only GPRS/EGDE” in this case. In picocom type:
Pay attention that there are no spaces after the commas and type in the correct number of “F”s.
Sending and receiving SMS
I did quite a lot of research on this and found numerous valuable resources online. One of the most complete frameworks for controlling a phone/modem from Unix/Linux is Gammu. It seems a little complicated at first, but once one has read most of the excellent documentation things get clear. Again, I wanted to do things by myself to get e deeper understanding of things, so I did not use Gammu. Another great source of information is the SMS Tutorial at developershome.com.
Let’s have a look at the basics by interfacing with the modem directly with picocom. Modems support two types of SMS handling: text mode and PDU mode. Text mode is easier and I will use it throughout this post. In PDU-mode the SMS is binary encoded which adds some complexity. Again, I wanted a “proof of concept” and decided to go with textmode.
One word about AT-commands before we begin:
- AT+CMD? outputs the current configuration for CMD in the form “+CMD=xxx”
- AT+CMD=xxx sets the parameters for CMD
The command for SMS mode is “CMGF”:
AT+CMGF? displays current mode AT+CMGF=1 sets text mode AT+CMGF=0 sets PDU mode
So set the modem to text mode first. It should respond with “OK”. Next we use the command “CMGL” to read all messages. This command takes one parameter that is used to configure if we want to get all messages, only new messages etc. Here is a list:
- ALL. List all messages
- REC UNREAD. List “received unread” messages
- REC READ. List “received and already read” messages
- STO UNSENT. The messages that are stored but not sent
- STO SENT. Messages stored and sent
So to read all messages from the card you would type
and get an output like this:
+CMGL: 0,"REC READ","+4911234567890",,"13/07/11,19:03:45+08" this is message number one +CMGL: 1,"REC READ","+4911234567890",,"13/07/11,19:48:31+08" Second message, 45 minutes later OK
The format of this output is straightforward. The command (CMGL) is repeated, followed by the index of the SMS. Then follows the status and the phone number from the sender and a timestamp. The following lines (until the next line starts with “+CMGL”) are the message.
Messages can be deleted using the “CMGD” command. It takes the index and an (optional) flag as parameters:
The flag value can be one of the following:
- 0 – Only delete SMS at index given
- 1 – Ignore index and delete all “received read” SMS
- 2 – Ignore index and delete all “received read” or “stored sent” SMS
- 3 – Ignore index and delete all “received read” or “stored sent” or “stored unsent” SMS
- 4 – Ignore index and delete all SMS
Lastly, we are going to send an SMS. This is done with the command “CMGS”. The syntax is:
AT+CMGS="phonenumber"<CR>the message to send<Ctrl+z>
If you are doing this in picocom you need to press the return-key after the number, type the message and finalize it by pressing CTRL+z. If you encounter the message “+CMS ERROR: 330” the message center service number is not set. You can check the configured service center number with the command “AT+CSCA?”. It should return something like “+CSCA: “xxxxxxxxxxxx”,145.
Beware: I just spent one hour debugging, because I did get the “ERROR: 330” message despite the fact that “CSCA” did return the correct number. In the end I decided to just write the number again to the modem and give it a try. And it worked. I just have no idea why… Here’s a screenshot:
So that’s pretty much it. The Raspberry Pi can receive and send SMS texts. This gives us a lot of new tinkering possibilities. Send the Pi a SMS, get it parsed and let it send you an SMS back or do something with the home automation system. Wonderful 🙂
And just in the process of writing this, trying to remember all the websites I visited and testing the whole stuff again, I found a webpage with a python library for encoding/decoding SMS messages. With python’s serial library this makes things really easy. Connect to the device, send AT commands and do whatever you want to do with it.