AstriCon 2009, Building a Distributed Call Center

Every year that AstriCon has existed, I have presented or at least helped organize, and this year is no exception. I will be presenting on Wednesday, October 14, 2009 from 10:00am to 10:35am in the Carrier/Call Center track. I will be the first presenter of the day hoping to give you lots of information about using Asterisk as a call center platform.

More information about my talk is here: http://www.astricon.net/confDescriptions.aspx?t=CC#CC-01

Over the last year or so I’ve been building a distributed call center based on Asterisk 1.4. However, there are some additional tools and features that make the task easier in the new 1.6.x builds of Asterisk, and I’ll be discussing them and showing some of the configuration options to get you going. Because I only have 35 mins of total talk time, I’ll be discussing a lot of technical and logical topics quickly, so the presentation most likely won’t be for the faint of heart.

Since I’m the first one in the track, I will try to give a brief, low-level overview of call centers in general, along with the traditional method of running a call center, versus the freedom a distributed call center gives you, and some of the technical challenges involved in that, and how to overcome them.

Hopefully you can make it to AstriCon. I’ve been to a number of conferences, and as someone who is technical who doesn’t enjoy the pitches of sales engineers as talks because I rarely get anything out of it (since I’m not there to purchase thousands of dollars of equipment), I absolutely love what AstriCon provides. From higher level talks for business associates to down-and-dirty talks on how to implement and design complex solutions with Asterisk, the conference has it all. It’s a truly unique conference where the business manager, the sales associate, and the network engineer can all come together and leave with increased knowledge about a powerful phone system that could potentially save their company thousands of dollars a year (or day!).

Hope to see you there!

Ask the Expert!

UPDATE (October 7, 2009):

This post didn’t quite generate the type of questions I was hoping for, and because of that I’m not able to generate a knowledgeable and informed response that would be overtly useful. However, I will leave this topic open for the next little while in the hopes some more questions can be generated. It is entirely possible I haven’t been specific enough in my request for the type of questions I’d like to answer, so here goes.

I’m looking for questions related to Asterisk implementation issues, specifically related to problems in the dialplan or /etc/asterisk configuration. For example, a good question might be proposed as;

“I have a call center solution I’m building, and I’ve been unable to get the member status to be consistently accurate. Here are the relevant parts of my configuration currently, and the console output of my mostly correct but inaccurate status. Thanks!”

Hopefully this helps to clear up any confusion I may have generated by the generally asked topic of Ask the Expert, and will lead to better questions and a fruitful article in the future. Thanks!

I figured that due to my limited time to write blog posts, and my intent to try and write at least one blog post a week, I’d do a simple “Ask the Expert” type of article. I’ll take 5 of your questions and answer them in a blog post later this week (hopefully on Thursday). So if you have some particular problem you’re trying to get solved, or have a question about implementation, now would be a a great time to get the answer you’re looking for.

Ideally you’ll ask questions related to Asterisk :) I tend to specialize in queues and database integration, so those are the realms you’ll probably get the most indepth answer. Or if you just have a problem you’re trying to solve in dialplan that you can’t quite get to work, let me know, as I love creating clever dialplans.

Creating vCards with QR Codes

Recently I’ve been noticing a lot more use of QR codes around the internet. A QR code is those 2D matrices that look like a bar code, but aren’t just the ordinary vertical lines that you would see on your box of cereal. These are a box that contain pixels that have been coded to contain information about pretty much anything. I’ve been seeing some people using them for contact information, web links, and pretty much anything you can think of to distribute information.

I also recently saw a show on Discovery where in Japan people will post these large images on a wall somewhere hoping people will scan them with their cell phones, thereby visiting a site of a product, or perhaps giving information about an upcoming show.

These codes can then be scanned by an application on your cell phone which then displays the data for you. On my Nokia E71, if I scan in a QR code which is in the format of a vCard, then my phone will recognize that, and let me save the contact information to my phone book. How cool is that!

I figured it’d be neat to build a vCard (which is a standard format that can be used by cell phones to distribute contact information so you can easily add it to your phone book), so I went looking on the internet for some free QR code generators, specifically for vCards. I was somewhat disappointed because all the vCard generators seemed to be missing a field for a SIP URI, which I wanted to add. So I ended up using Wikipedia to find the standard vCard format, and then noticed I just needed to add the X-SIP field to my vCard information, and voila, I had the field I wanted!

If you want to generate a vCard as well, you can use the http://www.invx.com website. I found it the most forgiving, and generated the best QR codes. Additionally, it generates a semacode at the same time if you’re looking for that kind of thing :)

Here is the result of my internet scouring for QR code data generators. If you wanna try it out, feel free to scan with your cell phone and add my contact details to your cell phone! If you don’t have a bar code scanner for your cell phone, then there are several that you can find on the Internet. I tried one from http://www.i-nigma.com which seemed to work pretty well. I have one that comes with my cell phone anyways, which I actually liked quite a bit, so I’m just using that, but thought I’d try something else just for fun. You can also install it from you cell phone by visiting http://www.i-nigma.mobi.

NOTE: At some point you can only encode so much information into the graphic because the cell phone seems to get confused. For example, the image I’m generating below seems to be pretty much at the limit that my cell phone will easily pick up. It seems to be the more data you encode, the less likely your cell is to pick it up on the first try.

Consuming SOAP complexType webservice with PHP

I recently had a client request that I communicate with a webservice via SOAP in order to do some credit card authorization for an Asterisk project they were implementing. After a couple of days of reading several posts I found via Google (which funny enough weren’t exactly what I was looking for, but gave me JUST enough information to finally start putting it all together), I had something that worked.

In order to potentially save someone the hassle of having to figure out how to consume a complexType in SOAP via PHP (and not using NuSoap as many of the posts pointed out), I’m writing this down. As with many of my posts, there is probably just enough information here that will be useful for me in the future should I need to do this again. If this helps someone else out, then great!

Note: I am not a programmer. What I’m showing may be entirely the WRONG approach to solving this issue, but it solves it for me. Feel free to provide better examples by commenting on this article. In addition, there is the potential I may be using the wrong terminology. Please feel free to correct me, and I will then update the article to reflect anything deemed to be incorrect.

First, you need to install the php-soap module for your PHP installation. This could require you to recompile PHP with SOAP support, or if you’re using a package based distro (like me), you may just need to do something like:

# yum install php-soap

In order to give you just enough of a reference point to figure out what I’m trying to do here, the following snippet of XML code is from the webservice I’m trying to consume. It is the complextype which I need to perform request against, and defines how the object should be passed. I’ll then show the result. This is *not* the entire WSDL.

First we’re looking at the element named ‘Purchase’. This element contains a complexType object named oPurchaseRequest and receives a request of the type PurchaseRequestType.

<s:element name="Purchase">
 <s:complexType>
   <s:sequence>
     <s:element minOccurs="0" maxOccurs="1" name="oPurchaseRequest" type="tns:PurchaseRequestType"/>
   </s:sequence>
 </s:complexType>
</s:element>

The structure of the PurchaseRequestType is as follows. This is how we need to structure our complexType.

<s:complexType name="PurchaseRequestType">
 <s:sequence>
   <s:element minOccurs="0" maxOccurs="1" name="MembershipNumber" type="s:string"/>
   <s:element minOccurs="0" maxOccurs="1" name="SessionID" type="s:string"/>
   <s:element minOccurs="0" maxOccurs="1" name="Password" type="s:string"/>
   <s:element minOccurs="0" maxOccurs="1" name="Gender" type="s:string"/>
   <s:element minOccurs="1" maxOccurs="1" name="RatePlanID" type="s:int"/>
   <s:element minOccurs="0" maxOccurs="1" name="CCNumber" type="s:string"/>
   <s:element minOccurs="1" maxOccurs="1" name="CCExpireMonth" type="s:int"/>
   <s:element minOccurs="1" maxOccurs="1" name="CCExpireYear" type="s:int"/>
   <s:element minOccurs="1" maxOccurs="1" name="CCCode" type="s:int"/>
   <s:element minOccurs="1" maxOccurs="1" name="Zip" type="s:int"/>
  </s:sequence>
 </s:complexType>

The magic really happens in the following code. It is how I built the object in order to be consumed by the webservice. It works by first creating a new standard class, and then creating another standard class inside the oPurchaseRequest object (which is the name of the complexType that the Purchase element is expecting). Then you build the oPurchaseRequest by adding the elements outlined by the PurchaseRequestType complexType, and assigning values to them.

$search_query = new StdClass();
$search_query->oPurchaseRequest = new StdClass();
$search_query->oPurchaseRequest->MembershipNumber = $MembershipNumber;
$search_query->oPurchaseRequest->SessionID = $SessionID;
$search_query->oPurchaseRequest->Password = $Password;
$search_query->oPurchaseRequest->Gender = $Gender;
$search_query->oPurchaseRequest->RatePlanID = $RatePlanID;
$search_query->oPurchaseRequest->CCNumber = $CCNumber;
$search_query->oPurchaseRequest->CCExpireMonth = $CCExpireMonth;
$search_query->oPurchaseRequest->CCExpireYear = $CCExpireYear;
$search_query->oPurchaseRequest->CCCode = $CCCode;
$search_query->oPurchaseRequest->Zip = $Zip;

The entire snippet of code is available below.

// We can take in our arguments from the console if we're using PHP CLI
$MembershipNumber = $argv[1];
$SessionID = $argv[2];
$Password = $argv[3];
$Gender = $argv[4];
$RatePlanID = $argv[5];
$CCNumber = $argv[6];
$CCExpireMonth = $argv[7];
$CCExpireYear = $argv[8];
$CCCode = $argv[9];
$Zip = $argv[10];

// Create the object we'll pass back over the SOAP interface. This is the MAGIC!
$search_query = new StdClass();
$search_query->oPurchaseRequest = new StdClass();
$search_query->oPurchaseRequest->MembershipNumber = $MembershipNumber;
$search_query->oPurchaseRequest->SessionID = $SessionID;
$search_query->oPurchaseRequest->Password = $Password;
$search_query->oPurchaseRequest->Gender = $Gender;
$search_query->oPurchaseRequest->RatePlanID = $RatePlanID;
$search_query->oPurchaseRequest->CCNumber = $CCNumber;
$search_query->oPurchaseRequest->CCExpireMonth = $CCExpireMonth;
$search_query->oPurchaseRequest->CCExpireYear = $CCExpireYear;
$search_query->oPurchaseRequest->CCCode = $CCCode;
$search_query->oPurchaseRequest->Zip = $Zip;

// setup some SOAP options
echo "Setting up SOAP options\n";
$soap_options = array(
        'trace'       =&gt; 1,     // traces let us look at the actual SOAP messages later
        'exceptions'  =&gt; 1 );

// configure our WSDL location
echo "Configuring WSDL\n";
$wsdl = "https://locationofservices.tld/asterisk.asmx?WSDL";

// Make sure the PHP-Soap module is installed
echo "Checking SoapClient exists\n";
if (!class_exists('SoapClient'))
{
        die ("You haven't installed the PHP-Soap module.");
}

// we use the WSDL file to create a connection to the web service
echo "Creating webservice connection to $wsdl\n";
$webservice = new SoapClient($wsdl,$soap_options);

echo "Attempting Purchase\n";
try {
        $result = $webservice-&gt;Purchase($search_query);

        // save our results to some variables
        $TransactionID = $result-&gt;PurchaseResult-&gt;TransactionID;
        $ResponseCode = $result-&gt;PurchaseResult-&gt;ResponseCode;
        $ResponseDetail = $result-&gt;PurchaseResult-&gt;ResponseDetail;
        $AddMinutes = $result-&gt;PurchaseResult-&gt;AddMinutes;

        // perform some logic, output the data to Asterisk, or whatever you want to do with it.

} catch (SOAPFault $f) {
        // handle the fault here
}

echo "Script complete\n\n";

You’ll notice that our results are passed back in the ‘try’ statement. We assign the values passed back to some variables we could use. The layout of the result is similar to the request. It is laid out as follows in the WSDL.

<s:element name="PurchaseResponse">
 <s:complexType>
  <s:sequence>
   <s:element minOccurs="0" maxOccurs="1" name="PurchaseResult" type="tns:PurchaseResponseType"/>
  </s:sequence>
 </s:complexType>
</s:element>

<s:complexType name="PurchaseResponseType">
 <s:sequence>
  <s:element minOccurs="0" maxOccurs="1" name="TransactionID" type="s:string"/>
  <s:element minOccurs="1" maxOccurs="1" name="ResponseCode" type="tns:ResponseCodes"/>
  <s:element minOccurs="0" maxOccurs="1" name="ResponseDetail" type="s:string"/>
  <s:element minOccurs="1" maxOccurs="1" name="AddMinutes" type="s:int"/>
 </s:sequence>
</s:complexType>

Hope that helps!

Suzanne Bowen Interviews Leif Madsen, Asterisk Rockstar

Today I had the privilege to be interviewed by Suzanne Bowen of DIDX.

You can find the interview at http://www.didx.net/podcast/?p=episode&name=2009-07-30_leifmadsenjul312009.mp3

Hope you enjoy!

Here is a description of the interview:

“Truth is that I “met” the authors of the book “Asterisk, the Future of Telephony” when I was an English teacher and had volunteered over email to help edit the documentation. It was a joy to interview Leif Madsen. The Asterisk rockstar* shares with us the history of how he became interested in voice, telephony, Asterisk and open source.

We discussed the “cliques or special interest groups” in telecommunications, in fact three.
1. Old style, keep it closed, don’t share, beat the competition, sell it at an inflated price, and it’s all about the money.
2. It should all be free and if you are not offering it free, you’re not one of us.
3. With a happy medium area of those who realize that people do need a paycheck to take care of their lives. At the same time, be willing to give back in an open source manner. Like a compromise!

Advice for entrepreneurs… Leif says he’s more a technical guy but he definitely did not want to work for someone else and being in your own business assures that. You must create content that is of value to other people. For him, it worked with his documentation projects such as the O’Reilly book and he’s now a successful Asterisk consultant and author.

Websites he uses most? news.google.com and Twitter! Also Asterisk IRC channel.

Who inspires Leif Madsen? James Shaw, his friend since age 17 when Leif took Jim’s place working on at a computer store. Second one is Jim Van Meggelen. Leif describes him as a guy who can make you laugh and enjoy life, not a workoholic, and a good example for public speaking.

What do people ask him most often about the O’Reilly book? When are you going to write a new version? And that’s tough because Asterisk is progressing fast with changes by the second.

Leif will be at Astricon Oct 13-15, 2009 in Glendale. He will be speaking 10 AM on Oct. 14, 2009. He usually attends IT360 in Toronto every year. You can learn from him, contact him, do business with him at http://www.leifmadsen.com.

You can listen to other podcast interviews on DIDX podcasts at http://www.didx.net/podcast.

* After polling 11 people how I should define Leif, 10 said, they voted rockstar.”

Next Page »