Asterisk, the OS X Address Book, and cheap calls without dialing '1'

Posted by Scott Laird Fri, 09 Apr 2004 08:23:06 GMT

I am a happy man. I have, after four years of trying, achieved nerdvana. I am down to one single address book, accessible everywhere. It’s shared between my computer, my cell phone, my palm, my wife’s Mac, her phone, and finally, as of yesterday, our home phone. I can add new contacts anywhere, and they show up everywhere automatically.

It’s actually even more pervasive then that; the same address book entries re-write incoming caller ID and control our home phone’s ringer, so we can tell the difference between friends and telemarketers without even looking at the caller ID display. The best part is that it all just works. Setting it up in the first place took a bit of work, but once it’s running, all I have to do is drag cards around inside of the OS X Address Book, and everything else follows along on its own.

The first part of this whole operation was to get data out of the OS X Address Book and into a form that I could work with on one of my servers at home. Towards that end, I wrote ab2vcard, a simple tool that extracts vCards for every address book entry and stores them in a directory. If you set up Subversion and use the right flags on ab2vcard, then all of your vCards will be checked into Subversion and automatically replicated onto the Subversion server. I run ab2vcard from cron, so every two hours, all of my addresses are automatically sent to my server at home.

Next, I wrote asterisk-vcard-cid so I could use the names in my Address Book for Caller ID instead of the nasty stuff that Verizon sends me. If you copy the ‘vcardcid-cron.sh’ file that comes with it onto your Asterisk server and run it every couple hours, then it’ll do all of the hard work of checking changes out of Subversion and shoving them into Asterisk. The way I have it set up, I have 5 groups in my Address Book:

  • Home CallerID
  • Home Ring 1
  • Home Ring 2
  • Home Ring 3
  • Home Ring 4

Any contacts in the ‘Home CallerID’ group will automatically be added to the caller ID DB in Asterisk. Anyone in one of the ‘Home Ring’ groups will have ‘distinctive ring’ turned on when they call. That was really easy with Asterisk. All I had to do was add a macro like this:

[macro-setalertinfo]
  exten => s,1,DBGet(ALERT_INFO=distinctivering/${CALLERIDNUM})

Then, I make sure that all incoming calls use this macro. Here’s my complete outside line macro:

[macro-outsideline]
  exten => s,1,SetCDRUserField(Outside (${CHANNEL}))
  exten => s,2,LookupCIDName
  exten => s,3,SetMusicOnHold(random)
  exten => s,4,Macro(setalertinfo)
  exten => s,5,LookupBlacklist
  exten => s,6,Dial(${PHONES},13,Ttmr)
  exten => s,7,Answer
  exten => s,8,Goto(outside-ivr,s,1)
  exten => s,106,Wait(3600)
  exten => s,107,Hangup

This handles caller-ID rewriting, blacklisting, distinctive rings, adds extra logging, and sends unanswered calls to voicemail.

One little note on distinctive ring: the way I’m using it, it probably only works right with Cisco SIP phones, although other SIP phones that support distinctive ring will work with a few changes to the vcardcid-cron script.

Finally, I’ve added a mechanism for tying the same set of vCards into the speed dial directory on Cisco SIP phones. I’m using the 7940, but the 7905, 7912, 7920, 7960, and 7970 should all work. Each of these phones has the ability to download XML programming objects over HTTP. There aren’t a lot of great references out there, but this one is fairly complete and seems accurate so far.

The directory tool that I wrote, cisco-phone-directory, runs as a CGI on a web server. If you set up the Cisco phone right, every time you select ‘external directory’ from the directory menu, you’ll be prompted with a search screen. Enter a few letters from the name that you’re looking for, and you should get a nice, short list of names to choose from. At this point, it works with almost no fuss, and almost no user training.

Er, except for one little problem. All of the numbers in my address book look like (206)-555-1212. Once you strip the punctuation, you’re left with 10 digits. The problem is that I need to dial a ‘1’ before I call long distance numbers, and it’s not really obvious which numbers are long distance and which aren’t. I can dial most numbers in the 206 area code for free, and about half of the numbers in 425, but there’s no simple way to tell which numbers are which. Since I’m cheap, I want to send toll-free calls out over a real phone line, because it doesn’t cost me anything, while I send toll calls to NuFone over the Internet, because they cost about half as much per minute.

In order to do that, I need to know which numbers are local, given my phone’s area code and exchange. So, enter yet another tool: asterisk-lca-map. If your home number was (425)-488-1212, then you’d run it from the command line like this:

$ asterisk-lca-map.rb 425 488 1212 'Macro(dialanalog)'

and it’ll produce a dial plan that sends all local calls out ‘Macro(dialanalog)’, like this:

exten => _206200XXXX,1,Macro(dialanalog)
exten => _206202XXXX,1,Macro(dialanalog)
exten => _206203XXXX,1,Macro(dialanalog)
exten => _206204XXXX,1,Macro(dialanalog)
exten => _206205XXXX,1,Macro(dialanalog)
exten => _206208XXXX,1,Macro(dialanalog)
exten => _206210XXXX,1,Macro(dialanalog)
exten => _206213XXXX,1,Macro(dialanalog)
exten => _206214XXXX,1,Macro(dialanalog)
exten => _206215XXXX,1,Macro(dialanalog)

You can then add a couple extra rules at the bottom to handle 800 numbers and toll calls:

exten => _888NXXXXXX,1,Macro(dialanalog1)
exten => _1888NXXXXXX,1,Macro(dialanalog)
; continue on with 877, 866, 855, and 800

exten => _NXXNXXXXXX,1,Macro(dialnufone1)
exten => _1NXXNXXXXXX,1,Macro(dialnufone)

The ‘dialanalog1’ and ‘dialnufone1’ macros prepend a ‘1’ to the number that they’re calling. When all of this is done, dialing ‘2062001111’ goes out the POTS line as-is, while dialing ‘2125551212’ goes out NuFone as ‘12125551212’. Everything Just Works, and users don’t have to know when to dial a 1 and when not to. They never actually need to dial the 1 at all, although if they do, it’ll still work. And that’s what I’m aiming for–the back end is complex, because it has to interact with complex parts of the real world. The front end is dead simple, though, because I can handle all of the hard bits without bothering the user. They can just dial the phone number, and I’ll route it out the cheapest connection automatically.

Posted in , , ,  | Tags , , , , , ,  | 13 comments

Comments

  1. nik said 22 days later:

    You have pushed asterisk and cisco foo over the edge! I’m thinking of setting up a site dedicated to cisco/asterisk services development.

  2. J. S. Townsley said about 1 month later:

    How has maintenance been with this setup?

    I have an applescript that converts OS X’s Address Book into the xml directory scheme that the 7960 needs, but your method is even cooler.

    –JST

  3. Scott Laird said about 1 month later:

    It’s been great so far. I haven’t had to touch it in the slightest, and updates work perfectly. I ran into one little bug a couple weeks ago that I haven’t fixed yet–if your contact’s name is too long, the end of it will be pre-pended onto the phone number. This is so weird that it has to be a Cisco bug–I don’t see how the XML representation could get that wrong. I’ll limit the contact’s name to around 25 letters, and that should fix it.

  4. Paul said 3 months later:

    Scott

    What are the variable values that got into ALERT_INFO? According to the WiKi they are:- Bellcore-Stutter Bellcore-dr1 etc…

    but when I try them Asterisk rejects them as being invalid.

    TIA

    P

  5. Scott Laird said 3 months later:

    Paul, can you show us an example of the config that’s failing for you? It’s always Just Worked for me.

  6. Bryan McGill said 5 months later:

    Wondering if anyone could give me some advice on how to set this up: I have a local voip provider that wants me to use a Cisco 7940/60. They can’t offer me a solution for a softphone because there are no sccp supported softphones available for OS X. It is my understanding that Asterisk supports sccp. However, I’m a bit confused on how to configure Asterisk to communicate with my provider. I’m trying to use Jon’s Phone Tool, which you may know is a softphone that will can use Asterisk with sccp, but don’t understand what I need to set up Asterisk to work like this. Any help would be greatly appreciated.

    peace

  7. Scott Laird said 5 months later:

    First, Asterisk’s SCCP support isn’t all that full-featured. It works well enough when talking to Cisco’s phones, but I doubt it can talk to other SCCP servers. You’d be best off asking the asterisk-users list (see http://lists.digium.com).

  8. steve said 5 months later:

    When I click on asterisk-lca-map above it gives me a black screen where the code should be located. I am interested in using this. Thanks!

  9. Jason Sjobeck said 9 months later:

    You are a nerd after my own heart.

    You have inspired me. I will attempt his at home, but using Outlook/Exchange as a substitue for OS X’s addressbook.

    More power to you, Scott, you party.

    Thanks.

  10. Alex said about 1 year later:

    Thanks - we will try this!!

  11. Robert Shilston said about 1 year later:

    Can you give us some details of the distinctive ringing - specifically, what’s in the database used by macro-setalertinfo?

  12. Jason Hughes said over 2 years later:

    Holy nerdsmack! This is too cool. I’m just setting up Asterisk (Trixbox, specifically) and am in awe of the kinds of things possible. It’s almost daunting, because as a programmer, not an IT guy, if I get into this too much, my job title might change. :-)

    Great page!

  13. ian said over 2 years later:

    now that is brilliant. im still trying to figure out how to get these sodden 7910 phones to work with Asterisk. if you could point me in the right direction? sliders1127@yahoo.com

Comments are disabled