Categories
Asterisk python Technology voip

who’s calling?

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:

"Tony Blair",07392838482
"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:

#!/usr/bin/env python

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,Gosub(cidname-lookup,s,1)
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.

7 replies on “who’s calling?”

Hi Yoav,

I have just tried your Script who’s calling. Indeed it is wokring fine. If I do asterisk -r in CLI it shows me the following Errormessage:
utils.c:1168 ast_carefulwrite: write() returned error: Broken pipe
[Mar 14 07:45:51] ERROR[7848]: utils.c:1168 ast_carefulwrite: write() returned error: Broken pipe

How Im going to resolve the issue, or at least ignore the Message. I’m not sure if it is critical as all is working fine so far.
Thanks a lot for your Help.

Best Regards

Andy.

Hi Yoav,
yes as already mentioned, for me it is working totally fine, except those two three pipe Errors I’m receiving all the Time. But my Question, do you have a newer Script based on Python that I could try.
None of the Perl Scirpts are working with me. Maybe Im doing something wrong. I just installed the Perl Script for AGI as described and Perl is installed anyway on my Machine. Do you have an accurate HOWTO for agi isntall or another Python Script? Maybe that assist to analise the Errors.
Best Regards

Andy

Maybe the Fault is related to my way of usage. You mentioned it in your Script below, but is used my internal phonenumber for dialing:

my way
exten => s,n,Gosub(cidname-lookup,s,1)
exten => s,n,dial(SIP/201,30,t)

according to you
exten => s,n,Gosub(cidname-lookup,s,1)
exten => s,n,dial(${PHONE},30,t)

Sorry Andy, but it’s working for me for a couple of years now without a hitch. From what I read it’s working for you too. I don’t see much point worrying too much about an error message that seems to do no harm…

Really nice guide. I do need to create something in reverse of yours and I would appreciate some help if possible. I do need to send the incoming caller’s I’d to a php form.

Leave a Reply

Your email address will not be published. Required fields are marked *