For years, my colo server has had a SMS "modem" attached to it, so that the monitoring system running there can send/receive SMS messages, even if its Internet connection was down.

Originally it was an Ericcson R520m cellphone, which was one of the first "feature phones" to include a serial interface and reasonable "AT modem" features -- over 2G. That worked, controlled by kannel for a very long time, until eventually the last battery for the R520m died from being left "on charge" all time. (The phone survived longer than the company name -- the company changed to Sony Ericsson some years back.)

A couple of years ago, when the R520m battery died, I replaced it with a fairly generic Huwaei-based 3G modem stick from Vodafone -- the Vodafone K3772. After a bit of fiddling to get it into "modem mode" (rather than the USB Storage mode it starts in when first connected), it worked okay with kannel for sending SMS messages.

The Vodafone K3772 on Linux seemed to need something like these magic strings:

usb_modeswitch -WD -v 12d1 -p 1526 -n -M 555342437f0000000002000080000a11062000000000000100000000000000 -I -w 500
modprobe option
echo "12d1 14cf" | tee -a /sys/bus/usb-serial/drivers/option1/new_id

before it became /dev/ttyUSB0 and could be spoken to like a modem. Back a couple of years ago it did not get auto-detected, so that did not happen automatically. I wrote a boot shell script to do that on each boot -- but I think now it is being auto-detected by more modern Ubuntu 14.04 LTS packages and the need for manual setup is redundant. (Sadly I do not know precisely what those commands do, other than the hex ID numbers being USB Bus ids, and the long hex string being a magic USB programming string for the device which I found online.)

The only annoying thing was that SMS reception on the Vodafone K3772 did not work with kannel. And I had been using kannel for years (at least a decade) since it was one of the original tools that worked as a SMS gateway that could be reached from other machines. For a couple of years I ignored it, as I only occassionally wanted it to receive messsages: to ask for the "BAL"ance on the prepay account, and to use the SMS path to ask the colo server to do things (eg, try pinging something, for remote diagnostics).

At the time I put it in, I found out the problem was that the Vodafone K3772 SMS features assumed that the SMS messages received were numbered from 0-19, where as the kannel code assumed that the messages were numbered 1-20. Which meant that kannel was never able to retrieve the first message, or the last message, which caused errors. Since I was not the first to find this issue (some modems numbering messages from 0), I discovered that a "later version" of kannel was going to include a message-start=0 config option to solve this problem. So I had decided to wait until my colo server was upgraded to the current Ubuntu LTS release (14.04), and assumed that would come with a newer version of kannel including the fix.

Unfortunately it turns out that Ubuntu 14.04 LTS came with basically the same kannel release (1.4.3-2fakesync2build1) as Ubuntu 10.04 LTS (1.4.3-0ubuntu2) -- so the new configuration option did not appear. Upon closer inspection, it turns out that kannel has not had any production releases between February 2009 and August 2014 -- and the August 2014 release, of 1.4.4 did not include the patch (it was only in the 1.5.0 development version last updated in October 2010).

After some hunting I managed to track down the patch, from a mailing list post in April 2010, and it seemed quite small. So today, when I had a little bit of spare time, I decided to try to build my own Ubuntu 14.04 LTS package of kannel 1.4.3 including that patch.

Since I already had Docker installed, I used Docker to create a build environment for the Ubuntu 14.04 LTS source of kannel 1.4.3 and then had it integrate the patch before building -- which involved using quilt to add one more patch, and updating the debian/changelog to show a new version.

With the Dockerfile and patch in the same directory, building new kannel packages is:

docker build --rm -t kannel-build .
mkdir packages
docker run --rm -i -t -v $(pwd)/packages:/mnt kannel-build

and the new packages will be copied into the packages directory on the host machine, ready to be installed on the real server (the default CMD is to copy the *.deb files to /mnt).

The Dockerfile was fairly simple to write, other than figuring out how to automatically integrate an existing patch into quilt: the Debian guide to using Quilt provided some useful hints. (dch would make editing the changelog easier, but I did it by hand because the devscripts package had a lot of dependencies I did not want to install into that container.)

Once the new packages are installed on the real server, it is possible to add:

message-start = 0

to the relevant section of the modems group, and it the SMS message reception would look for SMS messages 0 through 19, rather than 1 through 20.

With a bit more experimentation I also found that to use the "ME" (ie modem, rather than SM = SIM) storage for SMS messages, which is faster, I needed to both set:

message-storage = "ME"

and also update the init string to initialise the SMS storage used, with a three argument storage setting:

init-string = "AT+CNMI=2,1,2,2,0;+CPMS=\"ME\",\"ME\",\"ME\""

(Note that the backslashes are needed to escape literal double quotes that have to be passed to the modem -- it is not clear to me who chose that syntax, but it is a bit inconvenient.)

Those three arguments are:

  1. Storage used for reading/deleting SMS messages

  2. Storage used for sending/writing SMS messages

  3. Storage used for receiving SMS messages

By default kannel only sets the storage for reading SMS messages, with a single argument, so you are on your own to set the storage for receiving messages to match where kannel is going to look to read messages.

After doing that, I was able to both send and receive SMS messages, via kannel, with the Vodafone K3772. At last.