Note: For information on Ann Arbor DDA blocking this application, click here.
VoIP is Fun
Patrick and Fred eat, breathe, and live telecommunication. So, when the chance to make fun little phone applications come around, we like to jump on it. Recently, while discussing parking issues with Ann Arbor’s Edward Vielmetti, and idea came to mind. Mr. Vielmetti is active within the Ann Arbor community and among the many hats he wears, one seeks to provide access to accurate information concerning downtown transportation and parking (wow that was a mouthful). While discussing the lack of accurate bus information in Ann Arbor, the conversation took a tangent (yes, how odd that conversations with Fred or Patrick take tangents) on the area of parking.
The parking garages in Ann Arbor provide nice signs in front displaying in brightly lit numbers, the amount of available spaces remaining. Ann Arbor also posts this information on the web at the A2DDA website. An idea came to mind that basically, you can tell the available spots either from the website or right when you reach the garage — but what if you wanted to know while driving to the garage?
So, with that long introduction, we present “using asterisk, cepstral, and perl to get parking and weather updates.” Ok, for the non-techs, don’t panic! We’ll talk about the techie stuff in a little bit. The bottom line is using Asterisk, Cepstral, and Perl, you can check the internet for the spaces available and let the caller know — all in real time. For a working example, call +1 (212) 937-7844 and press 6 +1 (734) 272-0909 (this is not a toll-free number).
First, let’s talk about the three major components here: Asterisk, Cepstral, and Perl.
Asterisk
Asterisk (by Digium) is the world’s leading open source telephony engine and tool kit. Asterisk empowers communication with it’s flexibility. Whether working as a simple office telephone system, a robust Call Center platform, or anything in-between, Asterisk provides advanced features at a very low deployment cost.
Asterisk is free, open source software provided under the GNU General Public License (GPL). Asterisk is the most popular open source software available, with the Asterisk Community being the top influencer in VoIP.
Why free? “It’s just how Digium rolls.” They really take that GPL open source to heart.
Cepstral
Cepstral provides speech technologies and services for the spoken delivery of information. They build high quality, natural sounding voices for hand-held, desktop, and server applications. Their technology is easy to incorporate and operates in a small memory footprint with low computing resources. Cepstral is not free, however a full user’s license can cost under $30.00 (as of January 2009 at least).
If you are looking for a free alternative to Cepstral, try Festival. Festival is free, but sounds very “machine” like. Cepstral is a little more human.
Perl
Perl is a stable, cross platform programming language. Perl is open-source and is sometimes called the “duct tape of the internet.” If MacGyver programmed, he would have used Perl.
Ok, with our introductions in hand, let’s get on with the show. First step was to get the information from the A2DDA website using a perl script. the perl code for that was:
my $ua = LWP::UserAgent->new( timeout => 45);
my $URL = 'http://www.a2dda.org/parking.php';
$ua->agent('AsteriskAGIQuery/1');
my $req = new HTTP::Request GET => $URL;
my $res = $ua->request($req);
if ($res->is_success()) {
if ($res->content =~ /4th and Washington</td><td>(.*)</td></tr>/) {
my $spaces = $1;
if($spaces =~ m/(d+)/) {
$spaces = $1;
return $spaces;
}
}
}
Sure, it could be nicer, but it works.
Ok, next was to resign the script so that it would work with the Asterisk AGI (the gateway interface of Asterisk). We modified the script slightly to read the amount of parking spaces at 4th and Washington and if we’re unable to get a number, report an ERROR.
#!/usr/bin/perl -w
use strict;
use LWP::UserAgent;
$|=1;
sub trim($);
my %AGI;
while(<STDIN>) {
chomp;
last unless length($_);
if (/^agi_(w+):s+(.*)$/) {
$AGI{$1} = $2;
}
}
print qq(VERBOSE "STATUS: checking a2dda.org for spaces available" 2n);
my $spacesavail = "";
if ($spacesavail = &parking_lookup) {
print qq(VERBOSE "There are $spacesavail spaces at 4th and Washington" 2n);
print qq(SET VARIABLE SPACESAVAIL "$spacesavail"n);
exit(0);
}
else {
print qq(VERBOSE "STATUS: unable to determine spaces" 2n);
}
print qq(SET VARIABLE SPACESAVAIL "ERROR"n);
exit(0);
sub parking_lookup {
my $ua = LWP::UserAgent->new( timeout => 45);
my $URL = 'http://www.a2dda.org/parking.php';
$ua->agent('AsteriskAGIQuery/1');
my $req = new HTTP::Request GET => $URL;
my $res = $ua->request($req);
if ($res->is_success()) {
if ($res->content =~ /4th and Washington</td><td>(.*)</td></tr>/) {
my $spaces = $1;
if($spaces =~ m/(d+)/) {
$spaces = $1;
return $spaces;
}
}
}
return "";
}
Now, we have a number of available spaces, and integrating it was as easy as:
exten => s,1,NoOp(checking parking)
exten => s,n,playback(/tmp/spaces-greet)
exten => s,n,AGI(getspaces.pl)
exten => s,n,GotoIf($["${SPACESAVAIL}" = "ERROR" ]?error)
exten => s,n,SayNumber(${SPACESAVAIL})
exten => s,n,playback(/tmp/spaces-avail)
So why do we need Cepstral?
Good question! During testing of the script, we noticed that the number of spaces was always 130. No matter what we did, we kept getting back 130. Fred was pulling out what little hair he has… checking the asterisk… checking the code… couldn’t figure it out. Then, after checking the website, realized that Ann Arbor’s garages weren’t updating the spaces available. Perhaps a glitch, perhaps they don’t care, perhaps the information is being held hostage. No one knows for sure, but as of this moment, it’s pinned at 130.
Anyway, so enter Cepstral. Since the parking spots wouldn’t change, maybe the weather would. So, using another script to check the weather, you can modify the results and create a sound file using Cepstral (and swift), such as:
my $hash = "";
$hash .= ('0'..'9', "a".."f")[int(rand(16))] for 1 .. 8;
my $text = qq(Currently <break strength="weak" /> it is $currtempf degrees <break strength="weak" /> in $city <break strength="medium" /> Current conditions <break strength="weak" /> $currcondition <break strength="medium" /> Rest of day predicts <break strength="weak" /> $todaycond <break strength="medium" />);
my $sounddir = "/tmp";
my $wavefile = "$sounddir/"."tts-$hash.wav";
my $wavefileAst = "$sounddir/"."tts-$hash";
my $t2wp= "/opt/swift/bin/";
unless (-f $wavefile) {
open(fileOUT, ">$sounddir"."/say-text-$hash.txt");
print fileOUT "$text";
close(fileOUT);
my $execf=$t2wp."swift -f $sounddir/say-text-$hash.txt -p audio/channels=1,audio/volume=70,audio/sampling-rate=8000,audio/deadair=2 -o $wavefile";
system($execf);
unlink($sounddir."/say-text-$hash.txt");
}
print qq(SET VARIABLE SWIFTFILE "$wavefileAst"n);
Yes, again the code could be nicer.. but in this case we create a sound file for the weather conditions and then make a sound file variable. Yes, AGI supports streaming the audio and even playing it back directly from the script… so why did we chose to exit the script and return to the dialplan? Asterisk is very versatile. We like returning to the dialplan, and that’s how we code. Life is that simple. What works for you best, can sometimes be the best solution.
Ok, bringing that into the asterisk dial plan, you have:
exten => s,1,NoOp(checking parking)
exten => s,n,playback(/tmp/spaces-greet)
exten => s,n,AGI(testspaces.pl)
exten => s,n,GotoIf($["${SPACESAVAIL}" = "ERROR" ]?error)
exten => s,n,SayNumber(${SPACESAVAIL})
exten => s,n,playback(/tmp/spaces-avail)
exten => s,n,goto(weather)
exten => s,n(error),playback(/tmp/spaces-error)
exten => s,n(weather),AGI(current-weather.pl)
exten => s,n,GotoIf($["${CITY}" = "ERROR" ]?end)
exten => s,n,playback(${SWIFTFILE})
exten => s,n(end),goto(main,s,1)
Your comments are always welcome!
UPDATE — 01/10/2009
Well, the system has been upgraded a little bit… if you call +1 (212) 937-7844 and press option 6 +1 (734) 272-0909 you can choose your garage, and then be automatically called back (on the number you called from) when there are fewer than 10 spaces available.
Comments… we love to hear them.
This is awesome, Fred. Let’s see if we can actually get live data out of this as well.
Great effort — awesome — I diled te numbner and if I wanted to drive to Ann Arbor right now from manchester, I would have enough spaces to choose at 4th & Wash!! Say, perhaps we can use this for library patrons who want to know when their book is ready for pickup — or something similar. Like – is this available type of messages? Who knows where it can go.
Thnaks for the explanation!
Randal Baier
That is really cool. But when I dialed in, the system also offered a wake up call! That is the feature I really want on my home Switchvox? How do I get that?
Update Looks like Parking is in real time again… so maybe it’s time to take it to the next step.
Pingback: The week that was 1/9/2009 | Fred Posner dot com
Check out Twilio (http://twilio.com), a startup with Ann Arbor (UM, monkey.org) roots now based in SF and Seattle, for doing these kinds of voice applications really, really easily:
http://www.techcrunch.com/2008/11/20/twilio-powerful-api-for-phone-services-that-can-recreate-grandcentral-in-15-lines-of-code/
Twilio is nice, but personally, I like the flexibility of Asterisk, ie not needing the Internet, ability to keep things very local, SIP, IAX, POTS, PSTN, etc. There are many good products out there like freeswitch, switchvox, trixbox, twilio,… and 4000 others. I actually think the weather example we use here is easier than the weather example they post… but to paraphrase Lord Dennis Miller, That’s just my opinion…
For a slightly more advanced way to do the weather using Cepstral, look at:
http://www.voip-info.org/wiki/view/Modified+Weather.agi+to+Work+with+Cepstral
And be sure to scroll down the page to the section labeled “Alternative change.” Once caveat, the page was written for use with Asterisk 1.2 – it may require minor tweaking with Asterisk 1.4 or above, although I’d be a bit surprised if that is the case.
Dave Michels – I think that was an old add-on feature from the Nerd Vittles site, which has more than likely been replaced by this:
http://bestof.nerdvittles.com/applications/reminders4/
Pingback: Dave Askins
Good stuff, guys. I came here from the Ann Arbor Chronicle site. Not so much for your benefit, but for others that follow from there, I’ll say that this is an excellent example of the technology that the parking system can now take advantage of to manage peak demand periods, for example. Rather than building a new, expensive, underground parking structure to provide additional capacity to meet the higher demand of relatively few days per year, we could use technology and ingenuity to connect downtown employees and visitors with the service they’re looking for.
Hey Patrick and Fred that’s pretty neat!
Asterisk + Cepstral + AGI Foo is actually how we started Twilio! It’s killer for doing simple and advanced stuff telephony stuff. We founded Twilio (as Dug mentioned, we all went to UM-Ann Arbor) for those that don’t know SIP, IAX, POTS, PSTN but do know PHP/Python/C#/Java/etc.
If fact we know people that use both Twilio + Asterisk together. They make excellent companions.
I whipped up a Twilio + Google App Engine version of your demo with one enhancement that lets you select which parking location you want. You can try it by calling 734-399-4328.
The source code is posted here if others want to play around:
http://monkey.org/~phy/a2parking/a2parking.py
http://monkey.org/~phy/a2parking/locations.xml
http://monkey.org/~phy/a2parking/spots.xml
http://monkey.org/~phy/a2parking/error.xml
Love the idea!
-Evan
If someone is up to the challenge -
The city of Ann Arbor (or at least the DDA’s parking consulting firm) considers a structure “full” if it’s at 85% capacity or more. For instance, Fourth and Washington has 282 spaces, so when there are less than about 42 spaces left whatever info system you have should also suggest a nearby alternative that’s less full. (Adjust the numbers to match whatever threshold matches human intuition).
The good guide might say “8 spaces free at Fourth and Washington; the nearest open structure is 254 spaces free at Fourth and William, two blocks south”. & thus the person driving in who dialed that information would know just a little more about what their options were that would have them avoid driving around town looking for a space.
Sounds good, I’m hoping to have the next enhancement built over the weekend… which will automatically notify you of fewer than 10 spots remaining in the lot of your choice.
It’s LIVE… Automated call back when there’s fewer than 10 spots available.
Pingback: Parking Availability, Team Forrest, and Asterisk - Team Forrest
Good stuff and well explained. For the best of both worlds, an open source framework that abstracts Asterisk/Telephony while leaving the entire stack in the hands of the developer if desired, check out Adhearsion (http://www.adhearsion.com). Great to see all of the various approaches to bringing telephony into modern web development.
Thanks for stopping by Jason. We were impressed with Adhearsion (and Jay Phillips) during Astricon… Jay’s got a great blog at http://jicksta.com/…
How do you guys connect your instance of Astrisk up to the phone network? What do your costs look like there?
In the spirit of comparing and contrasting the various approaches and adding another language to the mix, I have created an Adhearsion component. The component re-creates the core capability of the example, you may find it here:
http://jsgoecke.github.com/annarbor_parking/
One point to note, is that I believe the optimal Asterisk context looks like this:
[my_context]
exten => my_extension,1,AGI(agi://uri_to_agi_server)
Therefore, all of the call logic happens in Adhearsion and therefore Ruby.
Kyle, there are many carriers out there. This system is using termination and origination services from Flowroute. Jason, thanks for the feedback… and you’ve given us a new idea for an article. We’ll explain in just a little bit.
Hi. I’m the Chair of the Downtown Development Authority (DDA), that manages the parking system in Ann Arbor (as well as does many other things: http://www.a2dda.org). This is very cool stuff you are working on here. I’d love to get this up and going officially. We have the topic on our Operations Committee agenda for Wednesday Jan 28th (11am). I think this kind of data availability will be a great customer service to downtown patrons.
Just as a further comparison, I implemented the first version of this on our SoftIVR system, which is another hosted IVR platform, which uses Javascript as its scripting language. The script’s here (all half-a-dozen lines of it): parking example, and you can test it by calling 1-253-243-1137.
Pingback: Ann Arbor Parking Information by Phone - an Adhearsion Example « Warheads Stacked in the Kitchen
Pingback: A2DDA Blocks Asterisk Parking Data | VoIP Tech Chat
Pingback: Notional Slurry » Hey, I checked our records. You didn’t say you wanted a revolution after all. Sorry!
Pingback: FOIA Friday Fun | VoIP Tech Chat
Pingback: Real-time Ann Arbor Parking Availability By Phone | Twilio Cloud Communications Blog