Caller ID Display
Display details about incoming phone calls on your Squeezeboxes!
I've used my Squeezebox, a modem connected to my server and a bit of Perl/Linux hackery to display details about incoming phone calls on my Squeezebox's display. If the phone number is in my address book, the caller's name is displayed alongside the number. In addition, if a track is currently playing and the volume is above a certain level, the volume gets turned down to make sure I can hear the phone ringing! This is still a work in progress, but if you're interested or fancy using this yourself, please read on. You'll need at least the following:
- A machine running Linux or something similar (not Windows!)
- Squeezebox Server
- One or more Squeezeboxes or SoftSqueeze
- A modem capable of receieving and interpreting your country's Caller ID standard
- Caller ID services on your phone line. This may require a subscription fee with your phone provider. In the UK, BT now offer Caller ID for free as part of the BT Privacy at Home package.
Caller ID Compatible Modems
Apparently it is quite hard to get a modem that is capable of interpreting Caller ID information in the UK. Standards being what they are, almost every country has its own ideas about how to send Caller ID information down the phone line, and most modems don't understand the way it's done in the UK. Two companies that have produced modems that support the UK Caller ID standard are U.S.Robotics and apparently Hayes (Europe) (see http://www.ainslie.org.uk/callerid/cli_faq.htm). I am lucky enough to own a U.S.Robotics 56k Faxmodem, which works just fine.
Setting Your Modem Up in Linux
Provided you have a proper modem, i.e. not one of the horrible modems that do most of the work in the driver and so tend to only work in Windows, this should be as simple as connecting your modem to your server and turning it on. For an in-depth guide, see The Linux Modem HOWTO. For a really quick guide, see the Quick Install section. One thing that caught me out here was the uppercase S in Linux serial devices. I wasted a lot of time trying to use /dev/ttys0 instead of /dev/ttyS0!
You may need to send an AT command to your modem to tell it to pass the Caller ID information on. With my modem, the necessary command is AT#CID=1. I haven't tried this on any other modem, but it does look as if this is a fairly standard command to enable Caller ID. Nevertheless, it's probably worth checking your modem's manual. I give information on how and when to send this command later in this document.
To test whether things are working as expected, you can use minicom. See man minicom for instructions on using this program. Once you've started it up and configured it to talk to your modem, you should be able to send an AT command and get the response, OK. Whilst minicom is running, if you use a phone to ring the phone number for the line to which you've connected the modem, you should see a RING response. At this stage, you probably haven't configured your modem to send Caller ID information, so you should just see a line saying RING. However, if you now send the Caller ID initialisation command, which in my case is AT#CID=1, you should hopefully get something like the following next time the phone rings:
RING DATE = 1030 TIME = 1152 NMBR = 01234567890
Unless you can get your modem to send something like the above information when the phone rings, you will not unfortunately not be able to display Caller ID information on your Squeezebox! :-(
Getting Your Server To Respond to Incoming Calls
Warning: Getting the following bits wrong could leave your server in a state where it will answer the phone and allow callers to get a command-line session on your server. I recommend that you keep the modem disconnected from the phone line whilst following the steps in this section and that you check everything carefully afterwards! I take no responsiblity for any security breaches that occur due to changes that you make to your server whilst following this guide.
For now, I am using mgetty to monitor the modem and decode the incoming data. mgetty is the program that traditionally allows people to dial into a computer and get a console session. One of its features is allowing the server administrator to specify a list of phone numbers that are allowed to dial in to the server. mgetty allows you to specify a program that it should run in order to determine if the current incoming call should be answered. This program is given details about the current call in its command line arguments and should return either 1 i.e. ignore the call or 0 i.e. accept the call. I've abused this feature of mgetty by writing a Perl script that receives the incoming call details from mgetty and always returns 1. In the future, I plan to talk directly to the modem.
mgetty needs to be started by init, so requires an entry in /etc/inittab. On my Debian system, there was already a line there, but commented out. The following needs to be present at the bottom of your inittab file (comment lines are optional!):
# Example how to put a getty on a modem line. # T3:2345:respawn:/sbin/mgetty -x0 -n 2 -s 57600 ttyS0
The highlighted bits are crucial. The first, "-n 2", tells the modem to answer after 2 rings. The Caller ID information is generally sent after the first ring, so if the modem answers before that, the information will never be receieved. The second, "ttys0", must be changed to reflect the serial port to which your modem is attached. You should also make sure that your system's default run level is included in the string that follows T3:. The entry above,
2345, means that mgetty will be run at levels 2, 3, 4 & 5. This should cover most cases!
Once you've made these changes, you need to tell init to reexamine the inittab file. You can do this by running telinit q as the superuser. At this stage, your modem will answer all incoming calls, so make sure you've disconnected the phone line from the modem, as recommended previously. For more information on init and innittab, see man init and man inittab.
The next stage is to configure mgetty to call a program when the phone rings. This is done by editing the mgetty configuration file, which is /etc/mgetty/mgetty.config on my system. Within the global section of this file you need to add the following two lines. If in doubt, you can probably put them at the very top of the file.
cnd-program /usr/local/sbin/cid.pl init-chat "" AT#CID=1
The first line tells mgetty to call /usr/local/sbin/cid.pl whenever the phone rings (you'll put this script in place later!). The second line tells mgetty to send the Caller ID initialisation command. You should change this line as appropriate for your modem. For more information, see info mgetty.
Installing the Perl Script
This is where the magic happens! Download cid.pl using the link above and put it on your system somewhere. I keep mine in /usr/local/sbin—if you choose a different location, make sure you change the path to this script in your mgetty configuration file. Make sure that the script has the execute bit set for at least the user (chmod u+x cid.pl). This script will be run as root so make sure that you're comfortable with what it does!
You will also need to have the Text::CSV_XS module installed. To find out if you already have this, type perl -e 'use Text::CSV_XS' on the command line. If this prints anything, you need to install the module. You can do this using cpan by typing perl -MCPAN -e "install Text::CSV_XS". Alternatively, on a Debian system you can run apt-get install libtext-csv-perl.
There are several bits of cid.pl that can be configured to match your needs. These are below the "#### User-configurable bits below here ####" in the script. In particular, make sure that $numberFile points to the csv file containing your contacts list (if you don't have one, set it to '') and that the $serverAddress and $serverPort lines match your SlimServer details.
Try It Out!
With a bit of luck, your Squeezeboxes should now display details of incoming phone calls! In reality however, something's probably gone a bit awry. The first thing you should do is edit cid.pl and change the $debug line to 1. Now run cid.pl manually by typining cid.pl a 01234567890 (the first option can be anything you like, but it must be there!). Have a look at what gets output and see if you can work out what the problem is. For assistance, try asking in the SlimDevices Forums.
Using A Contacts List
cid.pl will read a csv file containing names and numbers. If an incoming call's number is found in this list, the contact's name will be displayed. If no contacts list is supplied, only the number will be displayed. The first field in this csv file must contain the contact's name, the other fields on the same line should contain the numbers belonging to that contact. The first line of the csv file must contain the field names. The name of the first field is ignored. The names of the other fields will be appended to the contacts name. A field's name can be blank. This is far easier seen as an example:
Name,,Mobile,Work Max Spicer,01234 849284,07123 234853, Sean,01332 494920,,019432845028 Dean,01943 481945,,
The above file defines three types of number for each contact. The first type doesn't have a name, the second is Mobile, the third is Work. With this contacts file, an incoming call from 07123234853 would be displayed as "Max Spicer - Mobile". An incoming call from 01332494920 would be displayed as "Sean" (the name of the field containing this number was blank so nothing is appended). The script preserves spaces in phone numbers for display purposes, but strips them when matching against the incoming call. All of the above numbers are made up!
Generating this file can be tricky. I got mine by exporting my Outlook contacs as csv, opening the csv file in Excel and cutting out the columns I didn't want, then using a text editor to merge the first name and surname columns. If someone has a better way of doing this, I'd be very pleased to hear from them! Once you have a valid file, save it somewhere and change the $numberFile variable in cid.pl to point to it.