The content of this blog is archived. No comments may be made, and no further content will be published. Thank you for your ongoing readership! -Ryan
The best of a bad lot

« RIT's 19th Undergraduate Research and Innovation SymposiumRunning PHP 5.2 on Ubuntu 10.04 LTS »

Voicemail notifications with Asterisk and Google Voice

Permalink 07/29/10 23:12, by Ryan, Categories: Geekery, Howto , Tags: , , , , , , , , , ,

We use Asterisk 1.4 for our home telephone system, with FreePBX 2.7 as the front end.  This allows great flexibility to do strange things, although a home PBX is certainly a little overkill for a two-person, three-bedroom urban house.

Recently, I decided to give Google Voice a spin for voicemail processing.  I’m using a single Google Voice account for my cellphone and home phone extension.  I’m not going to elaborate on how the actual call forwarding to Google Voice is accomplished, but the key parts of the FreePBX and Google Voice configuration are:

FreePBX
  • Misc Destination: Google Voice
  • Ring Group: Destination if No Answer set to Misc Destination
Google Voice
  • All forwarding disabled – prevents loop
  • Home phone number set as “mobile” ("other” carrier, of course)

To make the voicemail integration more seamless from my end, I decided that I needed to have two features:

  1. Voicemail notifications on SIP phones
  2. Normal feature code to retrieve voicemail

I couldn’t completely gut the existing voicemail system, as my wife still uses it.  So, I had to improvise.  First, the “easier” of the two features:

Per-extension feature code handling

FreePBX’s structure is such that an administrator can override parts of the dialplan if required.  This is one of those situations.  Into extensions_override_freepbx.conf, I copied the existing context from extensions_additional.conf and made a few modifications:

[gist:github:499571]

On line 6, I added GotoIf($["${AMPUSER}” = “103″]?googryan), which goes to the googryan label if the caller is user 103 (me).  Then, I added lines 18 through 20 to the end, as the destination for googryan.  The first plays a nice little message telling me to wait.  The second line is a little bit of Asterisk magic.

I didn’t want to have to hit * to get to Google Voice’s PIN prompt, so I wanted Asterisk to hit * for me.  Dial(Local/15855550000@from-internal,15,D(w*)) does this by opening a channel to 15855550000@from-internal (thereby using the normal call routing rules), then it waits for a couple moments and hits * (that’s the D(w*) part).

This works out really well.  Allison Smith politely introduces me to Kiki Baessell, who asks me for my PIN, and I’m there.  Bam.

Voicemail notifications on SIP phones

This is the more interesting of the two features.

I’m using pygooglevoice, a library of Python bindings for the Google Voice API.  Installing pygooglevoice was pretty easy: sudo easy_install pygooglevoice

Once installed, check out the documentation for some example code.  I take that back, actually.  Check out the command line script first.  By typing gvoice and entering your e-mail address and password, you get a delicious command line interface to Google Voice.  Try “help” if you’re stumped.

It turns out that getting the voicemail status from Google Voice was the easy part.  Telling Asterisk about it, however, was more difficult.  I could not find a mechanism where Asterisk could ask my program directly, so I decided to create fake msg0000.txt, msg0001.txt, etc files in the actual voicemail folders to match the current number of voicemails.

Being fancy, I also tried to make sure it would work “seamlessly” with Asterisk’s own voicemail, just in case I need to use that for whatever reason.  I do this by considering any other files on that msg#### (such as a msg####.wav) an indicator that it is an Asterisk-based voicemail and not one of our doppelgangers.  I hope Asterisk has the same courtesy.

So, here’s the code.  It sucks, of course, but it was an afternoon project.  So far, it’s working good.  I’m firing it from cron every three minutes, which seems wasteful: I might change it to only check during times I’m awake, since I won’t hear the voicemail indicator when I’m asleep.  But that’s another project…

[gist:github:499562]

2 comments

Comment from: LT [Visitor]
****-
LTI just have a suggestion for you: Why not download the voicemails to your site and move them to Asterisk's voicemail directory? I don't know Python or I might attempt this, but I do note that if you use the gvoice command from the command prompt, and then give it the voicemail command, it shows you envelope information for each message. Also, the page at http://sphinxdoc.github.com/pygooglevoice/examples.html indicates that it is possible to download the voicemail files in MP3 format. So, what I think you'd have to do would be as follows:

- Get envelope information for the first message
- Download the first message to a temporary directory
- Delete the first message on Google's server
- Convert the downloaded .mp3 file to a 8000 Hz, 16 bit, mono WAV file (you could use lame and sox, see last message at http://forums.whirlpool.net.au/archive/916683) and move the result to msg####.wav in the the /var/spool/asterisk/voicemail/default/***/INBOX/ directory (replace *** with extension number, and #### with the first unused number in the msg####.wav sequence)
- Delete the original MP3 file and any intermediate WAV file
- Create a flie called msg####.txt in the same directory, and to it copy certain envelope information (modified to fit Asterisk's format) as follows:

;
; Message Information file
;
[message]
origmailbox=(((extension number of mailbox)))
context=macro-vm
macrocontext=ext-local
exten=s-NOANSWER
priority=2
callerchan=SIP/(((displayNumber)))-00000001
callerid="Unknown" <(((displaynumber)))>
origdate=(((converted startTime)))
origtime=(((startTime truncated)))
category=(((leave blank)))
duration=(((leave blank)))


Some of the above is obvious (anything in (((...))) must be replaced) but here are a few notes:

(((displayNumber))) must be modified to remove all non-digit characters

(((converted startTime))) - probably easier to convert startTime than deal with displayStartDateTime, but you might need to truncate it to the first ten digits (not sure). The format you need is: Sat Sep 4 09:03:59 AM EDT 2010. Don't know if Python has a function to convert UNIX timestamps to human-readable dates but there has to be a way to do this, though it might work fine if you leave this value blank.

(((startTime truncated))) - only the first ten digits of startTime

There's no way I know of to get the duration from the Google Voice envelope information (that I can see) so unless there is a way to calculate duration of a WAV file in Python, this would have to be left blank, or a dummy value inserted. I don't think the duration is actually used when playing voicemail, is it?

- After doing the above you just keep looping through the messages until all are downloaded and converted. I'm not saying it would be a no-brainer but it doesn't seem like an insurmountable challenge either, particularly for someone who knows Python.

Of course you'd need to run the finished routine as a cron job every so often, just as you are doing now.
09/11/10 @ 22:23
Comment from: Ryan [Member] Email
RyanI thought about that, and it's a decent plan. However, I chose not to do so because I prefer Google Voice's web interface, and I have my cellphone forwarding to GV as well. It made more sense to move the "Voicemail" button to GV than to move the GV to the "Voicemail" button.

However, this would be awesome for retention/backup of voicemails from Google Voice... hmmm. Might be a project. :-)
09/12/10 @ 00:59

Comments are closed for this post.

Blog posts come from a can. They were put there by a man in a factory downtown.

Recent Twitterings

    Stalk me with RSS

    Search the Blog

     

    Support the Beer Fund

    Powered by Linode: Life's too short for crappy hosting

    [Powered by Linode]

    b2

    © 1962-2015 by Ryan Tucker (Public Key)

    Contact | Help | Blog skins by Asevo | blog software | web hosting | monetize