who’s calling? 27 February, 2010
Caller ID is a wonderful feature. Don’t we love getting a call from someone we like, and perhaps more importantly, ignore those annoying callers who we really don’t want to talk to.
But this is yesterday’s news. We all have caller IDs. It just works. Well, yes. It does. But what if we get a call on our landline? We get the caller ID there too, but do we know who it is?? All our contacts are on our mobile phones. Standard phones don’t usually have the capacity to hold more than 10 names on average. And even if they did. Who’s got the energy to key in those numbers?
Enters Asterisk. Asterisk supports name as well as numbers for caller ID. But how do you get your asterisk to know the name of the caller? How can we inject the caller’s name into the caller ID string sent to our voip phones?
I’ve seen some online posts (like this one) about setting up look-up through online phone directories. I wanted something simpler. Why can’t I have my asterisk know who’s calling, based on my contacts on my iphone address book??
So here’s what I did. It can work on any address book format, as long as you can get it out as a csv (examples for iphone here and here). I created a simple CSV file, with two columns: Name and Number, which looks like this:
“Gordon Brown”,07893420393
“Kate Moss”,07393837732
…
I then created a little python script to run on my asterisk box, and pull the name based on the number. It’s an AGI script, but it’s so basic it doesn’t actually need any AGI libraries:
import sys
import csv
if len(sys.argv) <= 1:
exit()
cid = sys.argv[1].replace("-","").replace(" ","").strip()
# accepting AGI input (but there’s nothing to do with it)
while 1:
line = sys.stdin.readline()
if not line:
break
if line=="\n":
break
fd = file("/usr/share/asterisk/agi-bin/my_iphone_address_book.csv")
print ‘VERBOSE "STATUS: Looking up %s" 2′ % cid
for line in csv.reader(fd):
# note: comparing the number back-to-front, and only comparing 8 rightmost digits.
# This helps dealing with different prefix, e.g. +44, 00, 001 etc. and still getting
# an accurate match.
if line[1].replace("-","").replace(" ","").strip()[::-1][:8] == cid[::-1][:8]:
print ‘VERBOSE "STATUS: Found %s : %s" 2′ % (cid, line[0].strip())
print ‘SET VARIABLE CALLERID(name) "%s"’ % line[0].strip()
exit()
print ‘VERBOSE "STATUS: %s Not Found" 2′ % cid
It can be invoked in the same way as described here, i.e.:
exten => s,n,dial(${PHONE},30,t)
…
[cidname-lookup]
exten => s,1,NoOp(looking up callerid name)
exten => s,n,GotoIf($["foo${CALLERID(NAME)}" = "foo" ]?getname)
exten => s,n,GotoIf($["${CALLERID(NAME)}" = "${CALLERID(NUM)}" ]?getname)
exten => s,n,NoOp(caller id name exists as ${CALLERID(NAME)})
exten => s,n,Return
exten => s,n(getname),AGI(calleridname.py,${CALLERID(NUM)})
exten => s,n,NoOp(Caller ID Name is now ${CALLERID(NAME)})
exten => s,n,Return
Note that it’s currently only working with full matches. The caller ID number must match the record on the address book precisely. Let me know if you have any simple ideas for partial matches (e.g. to avoid non matches of numbers, e.g. +447771110006 != 07771110006). I’ll do some more research when I get a chance.
Update: code now deals with partial matches rather effectively.
Another benefit is with voicemails. I started forwarding my voicemail straight to my asterisk box. My mobile provider doesn’t support visual voicemail yet, and I find it frustrating to use the old fashioned voicemail system. Now when I get an email with the voicemail message, I not only see the number of the caller, and can call them back with a click. I also see their name.