Posts Tagged ‘CCXML’

How to call your VoiceXML, CCXML or CallXML app directly from Skype

Monday, November 23rd, 2009

When I wrote last week about how you could call a Tropo.com app directly from Skype, it naturally begged the question – can you also call a VoiceXML, CCXML, or CallXML app via Skype?

The answer is… of course!

We have had this feature in our platform for years, as I discussed in a post back in March 2008 called “Skype-ifying your voice applications“. Skype numbers (and SIP addresses and iNum numbers) are automagically assigned to your application when your create it. Once you login to our Evolution developer portal, simply click on “Application Manager” and then the name of one of your applications.

You’ll then see the “Applications Settings” information and by simply clicking on the “Contact Methods” tab you will see all the contact numbers available to you:

vxmlwithskype.jpg

You also have the ability to add more numbers if you want additional direct numbers (DIDs) associated with your app.

As I mentioned in the Tropo blog post, you can copy/paste that Skype number into Skype and call away… with or without the space in the number. You can try it out by calling:

+990009369991439407

Now, that is just a “Hello, world” type of app that is not nearly as exciting as the Yahoo!Weather app referenced in the Tropo blog post, but you get the idea.

That’s it! Create an app… call it from Skype. Nice and simple.

If you’d like to try it out, you can just head over to Evolution and sign up for free developer account if you don’t already have one. (And yes, we give you free direct DIDs, free Skype access, free SIP access, etc., etc.)


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


Make your existing VoiceXML (and CCXML and CallXML) apps multi-channel: add SMS and IM today…

Tuesday, August 25th, 2009

With our announcement of Prophecy 10 today, you can now add SMS and instant messaging (IM) to any existing VoiceXML, CallXML or CCXML application. When you login to our Evolution developer portal (and you can sign up for a free account if you don’t have one) and go into the settings for one of your applications through the Application Manager, you will now see that you can choose to make an application a voice application, a text-messaging application, or both:

voicexmlsmsim.jpg

Once you have added text messaging capability to your application, you can switch to the Contact Methods tab where you can add an SMS-enabled phone number and/or attach IM IDs to the application:

evoconfigsmsim.jpg

Now you have one application accessible via multiple channels. We’ll write more in the next bit about how to tweak your apps to work with multiple channels… but for those who want to login right now and get started, go right ahead!

P.S. Note you can also do this with Tropo.com applications as well


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


Developer Jam Session, June 24: Integrating advanced call control in VoiceObjects applications using CCXML

Thursday, June 11th, 2009

jam_session_275.jpgWant to know how to build an outbound dialing app with VoiceObjects? Would you like to learn how to add call control capabilities to applications you build with VoiceObjects?

If so, please join us for our next Developer Jam Session on:

Wednesday, June 24, 2009
8am US Pacific, 11am Eastern, 5pm Central European Time

In this webinar, Tobias Göbel will discuss implementing call control in VoiceObjects applications. The abstract is:

VoiceXML has rather limited capabilities in the area of call control, basically restricting the scope to blind or bridged tranfers. This Jam session will introduce CCXML and explain how it can interact with VoiceObjects applications to build advanced voice services including both call control and voice automation. Examples include outbound dialing, two-party bridging, call whisper, and multi-party conferences. Demo code will be provided so that participants can test the applications themselves using the free downloads of Voxeo´s Prophecy platform and VoiceObjects phone application server.

sign-up-now.gif

If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook or following us on Twitter.


Technorati Tags: , , ,


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


Leveraging a CCXML Wrapper for Post-call Cleanup

Wednesday, December 17th, 2008

The default CCXML wrapper that quietly powers many VoiceXML applications on Voxeo’s Prophecy platform is certainly sufficient for many simple applications. So why should I bother diving into yet another markup language to do re-invent the wheel? Because your application isn’t that simple and you’re a control freak. Or maybe I am. Who knows.

Typically, we can handle post-call cleanup in VoiceXML easily enough by using the <submit> or <data> elements to our server-side cleanup scripts.

  <catch event="connection.disconnect">
     <submit next="cleanup.php" method="POST"/>
  </catch>

While this is a valid way to handle this, VoiceXML requires that we either transfer control to another document(<submit>) or respond with valid XML(<data>). Instead, we can leverage the disconnect event and any other portion of the application that we’d like the call to end to send this data back to our CCXML handler and let it do all the work asynchronously. The bonus here is we can have unfettered control of our voice applications. Once we have this in place, it’s simple work to leverage CCXML to control call duration, pre/post-processing and more.

When using a custom CCXML wrapper to handle post-call cleanup, our VoiceXML disconnect handler will look something like this:

  <catch event="connection.disconnect">
     <exit namelist="my_var1 my_var2 my_var3"/>
  </catch>

Here we’re using the namelist attribute of <exit> to send back our values back to CCXML. We can now handle this inside our CCXML wrapper with a dialog.exit transition:

  <transition event="dialog.exit">
    <log expr="'**** DIALOG COMPLETE - SENDING POST CALL CLEANUP'"/>
    <assign name="dialog_active" expr="false"/>
      <log expr="'my_var1 = ' + event$.values.my_var1"/>
      <log expr="'my_var2 = ' + event$.values.my_var2"/>
      <log expr="'my_var3 = ' + event$.values.my_var3"/>
      <assign name="my_var" expr="event$.values.my_var1"/>
      <!-- sends a POST to our cleanup script -->
    <disconnect connectionid="conn_id"/>
      <send name="'user.call.cleanup'" target="'cleanup.php'" targettype="'basichttp'" namelist="my_var1"/>
  </transition>

The values of our VXML variables are stored in the object event$.values. We can then grab them from the event$.values object by referencing them as event$.values.variablename – in this case, event$.values.my_var1. Since our VoiceXML dialog is complete, we’re ready to end the call. We issue a disconnect to the caller’s connectionid and send our post call cleanup. CCXML’s <disconnect>, unlike VoiceXML’s, physically disconnects the call leg. So now the call leg is ended, we’re free to handle our post-processing without paying to keep that call leg up. Brilliant!

Now that we’ve shot off our post-processing request, we can handle the send.successful event and close the session out, right? Well, we could do that, but how do we know the request was received successfully? Note, this next portion is a Voxeo specific extension and is not part of the W3C spec and requires the Voxeo namespace - <ccxml version=”1.0″ xmlns:voxeo=”http://community.voxeo.com/xmlns/ccxml”>.

Instead of assuming everything went swimmingly with our post-processing, we can be sure by having our server-side send back an event to the CCXML browser if we format the body of the response like this:

  user.cleanup.successful
  my_var1=foo
  my_var2=bar

Note that we can inject not only an event here, but name/value pairs, though they are entirely optional. Now that my server side has responded, with an event, I’ll need to handle this in my CCXML:

  <transition event="user.cleanup.successful">
    <log expr="'**** POST CALL CLEANUP COMPLETED SUCCESSFULLY'"/>
    <log expr="'**** EXITING SESSION'"/>
     <exit/>
  </transition>

Last, but very definitely not least, we will want to ensure our session does not stay alive after the call leg has disconnected. Since we are doing a little post-processing, we don’t want to end the session immediately, as we’ll want to give that time to process. So, we’ll simply shoot off a delayed user event to kill the session 60 seconds after a disconnect and prevent the zombie apocalypse.

  <transition event="connection.disconnected">
     <!-- send to unconditionally end a runaway session -->
     <send name="'user.kill.unconditional'" target="session.id" delay="'60s'"/>
  </transition>

  <transition event="user.kill.unconditional">
     <log expr="'**** UNCONDITIONAL KILL - EXITING SESSION'"/>
       <exit/>
  </transition>

That’s it. Find the complete CCXML below.

<?xml version="1.0"?>
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">

      <meta name="author" content="Dustin Hayre"/>
      <meta name="maintainer" content="YOUR_EMAIL@HERE.COM"/>

<!-- how long to wait before assuming a session is a runaway and tearing it down -->
<var name="conn_id"/>
<var name="dialog_id"/>
<var name="my_var"/>

<eventprocessor>
  <transition event="connection.alerting">
    <assign name="conn_id" expr="event$.connectionid"/>
    <accept connectionid="conn_id"/>
  </transition>

  <transition event="connection.connected">
    <log expr="'**** STARTING DIALOG TO CONNECTION ID ' + conn_id"/>
     <!-- edit SRC attribute to point to VXML dialog -->
     <dialogstart src="'dialog.vxml'" connectionid="conn_id" dialogid="dialog_id"/>
  </transition>

  <transition event="dialog.exit">
    <log expr="'**** DIALOG COMPLETE - SENDING POST CALL CLEANUP'"/>
      <log expr="'event$.values.my_var1 = ' + event$.values.my_var1"/>
      <assign name="my_var" expr="event$.values.my_var1"/>
      <!-- sends a POST to our cleanup script -->
      <send name="'user.call.cleanup'" target="'cleanup.php'" targettype="'basichttp'" namelist="foo"/>
  </transition>

  <transition event="user.cleanup.successful">
    <log expr="'**** POST CALL CLEANUP COMPLETED SUCCESSFULLY'"/>
    <log expr="'**** EXITING SESSION'"/>
     <exit/>
  </transition>

  <transition event="error.*">
    <log expr="'**** ERROR - REASON: ' + event$.reason"/>
      <exit/>
  </transition>

  <transition event="connection.disconnected">
     <!-- send to unconditionally end a runaway session -->
     <send name="'user.kill.unconditional'" target="session.id" delay="'60s'"/>
  </transition>

  <transition event="user.kill.unconditional">
     <log expr="'**** UNCONDITIONAL KILL - EXITING SESSION'"/>
       <exit/>
  </transition>

  <transition event="connection.failed">
    <log expr="'**** CONNECTION FAILED - REASON: ' + event$.reason"/>
      <exit/>
  </transition>

</eventprocessor>
</ccxml>

Feel free to comment with any questions or suggestions.

-Dustin


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


Moshe Yudkowsky updates his CCXML video tutorials…

Monday, September 8th, 2008

Back in April, I wrote about some video tutorials about CCXML that Moshe Yudkowsky had made available. While the videos worked okay, Moshe has gone and re-encoded the videos and made them available in both Flash Video and AVI formats. You can now get them at:

Each video runs between 1 to 1.5 hours and are part of a half-day tutorial session that Moshe gave a year ago at SpeechTEK 2007.

Technorati Tags: , , , ,


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


New tutorial on passing variables between CCXML and VoiceXML

Monday, August 11th, 2008

Ever wanted to pass variables between a CCXML and VoiceXML app and weren’t sure how? Well, now you can learn in a recently posted tutorial from Voxeo staff member Jeff Menkel: Passing variables to and from VoiceXML and CCXML. This tutorial builds on the previous piece about passing variables to CCXML applications as well as other pieces of the CCXML documentation. It’s well worth a read and shows how easy it is to use CCXML and VoiceXML together.

Technorati Tags: , , , , , ,


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


Never forget to make a call with scheduled conferencing

Thursday, July 10th, 2008

We all forget to make important calls from time-to-time. With this tutorial, you will be able to schedule a call ahead of time, so that Voxeo’s IVR system calls you at that time in the future, and then links you with the party you intended to call.

While you’re utilizing your free Voxeo developer account, you might as well keep the whole shabang free, right? Head on over to x10hosting.com or forwardhosting.com, and register for an account. These are two of the very few hosting companies that will allow you to run cron jobs for free. Now that you are all setup, let’s get into the design aspect, cron job first.

While cron web interfaces will certainly be different, the underlying principal is the same: cron will wait until the system time matches your job time, and then will execute an action. Most web portals to cron jobs will allow you specify minute, hour, day, month, and weekday.

Let’s assume you have to call your wife every Friday night at 5 pm to let her know that you’re coming straight home from work. We’ll set minute to “00″, the hour to “17″, the weekday to “4″, and the rest to “*”. This will make the cron job execute on Fridays at 1700. You may need to adjust the time on your cron job to account for differences between system time and your time. For example, the x10hosting box on which my cron job runs is set to US central time. For the cron job command, use the Unix command “curl” like so:

curl http://api.voxeo.net/SessionControl/CCXML10.start?tokenid=dd5a1d7f44e97f49856eb6e894c9c669d152e89a571f6201eb3b265045b7a1d2bb52ff8d9856fbbbbbbbbbba\&numdial=5551231234

This command sends an http request to api.voxeo.net for our CCXML 1.0 token. The request also contains the variable “numdial.”

( Please note that the backslash is used in cron to escape the ampersand. This request will not work properly from a browser window )

Cron job interface

Now for the XML part:

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">

<var name="state0" expr="'init'"/>
<var name="callid_out1"/>
<var name="callid_out2"/>
<var name="pin"/>
<var name="holdMusicDlg"/>

<eventprocessor statevariable="state0">

  <transition state="init" event="ccxml.loaded">
    <createcall dest="'tel:+15555555555'" connectionid="callid_out1" callerid="'1112223333'" timeout="'30s'"/>
  </transition>

  <transition state="init" event="connection.connected">
    <assign name="callid_out1" expr="event$.connectionid"/>
    <assign name="state0" expr="'enterpin'"/>
    <dialogstart src="'null://?termdigits=#&text=Press 1 and then pound if you want to dial' + session.values.numdial"&
    type="'application/x-fetchdigits'"/>
  </transition>

  <transition state="enterpin" event="dialog.exit">
    <log expr="'PIN = [' + event$.values.digits + ']'"/>
    <if cond="'1' != event$.values.digits">
      <exit/>
    <else/>
      <assign name="pin" expr="event$.values.digits"/>
    </if>

    <assign name="state0" expr="'calling'"/>
    <dialogstart src="'holdingPattern.vxml'" type="'application/xml+vxml'" namelist="pin" dialogid="holdMusicDlg"/>
    <createcall dest="'tel:+1' + session.values.numdial" connectionid="callid_out2" callerid="'5555555555'"/>

  </transition>

  <transition state="calling" event="connection.failed">
    <assign name="state0" expr="'callfailed'"/>
    <dialogterminate dialogid="holdMusicDlg"/>
  </transition>

  <transition state="callfailed" event="dialog.exit">
    <assign name="state0" expr="'playingCallFailed'"/>
    <dialogstart src="'callFailure.vxml'" type="'application/xml+vxml'" connectionid="callid_out1"/>
  </transition>

  <transition state="playingCallFailed" event="dialog.exit">
    <disconnect/>
  </transition>

  <transition state="calling" event="connection.connected">
    <if cond="event$.connectionid == callid_out1">
      <exit/>
    <else/>
      <assign name="state0" expr="'beforeBridging'"/>
      <dialogterminate dialogid="holdMusicDlg"/>
    </if>
  </transition>

  <transition state="beforeBridging" event="dialog.exit">
    <send name="'pause'" target="session.id" delay="'200ms'"/>
  </transition>

  <transition state="beforeBridging" event="pause">
    <assign name="state0" expr="'bridged'"/>
    <join id1="callid_out1" id2="callid_out2"/>
  </transition>

  <transition event="error.conference.join">
    <log expr="'*** ERROR DURING JOIN ***'"/>
    <exit/>
  </transition>

  <transition event="error.*">
    <log expr="'an error has occured (' + event$.reason + ')'"/>

    <voxeo:sendemail to="'yourEmail@there.com'"
      from="'myApp@here.com'"
      type="'debug'"
      body=" 'generic error detected ! ' "/>
    <exit/>
  </transition>
</eventprocessor>
</ccxml>

This application has a fairly simple flow. It calls 1-555-555-5555, and then asks the callee to press 1 and then # to connect to whatever number was passed in via the http request (in this case numdial=5551231234).

That’s it. To make this work for you, you need to change four values:

1. token ID in http request 2. numdial variable in http request 3. “5555555555″ is found twice in the CCXML file – both instances should be changed to your number 4. sendemail “to” and “from” in CCXML file

Good luck with your development – mix in a little MySQL and PHP action to make adding more cron jobs easier.

Till next time,

Jeremy McCall Voxeo Network Operations


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


What is a “State Machine”? And how does it apply to CCXML (and James Bond)?

Monday, May 12th, 2008

ccxml.jpgWhen people come to CCXML from other languages, one concept that is sometimes difficult to understand is the whole notion of a “state machine”. Once you are comfortable with that idea, CCXML becomes rather easy to work with. While the Wikipedia page on state machines gets quite complex, let’s reduce the concept to some basics.

First, some vocabulary. In a “state machine”, there are a series of “states“, such as being “on” or “off”. There are then “events” that cause there to be a “transition” between states.

Now to illustrate this, let’s take the typical action hero film (such as any one of the James Bond movies) and describe it as a series of “states”:

  1. Hero is relaxing on a beach with a drink in some exotic locale.

  2. Hero is preparing for mission (getting briefing, gadgets, etc.)

  3. Hero is hunting for evil villain.

  4. Hero is fighting evil villain and his minions.

  5. Hero is relaxing on a beach in some other exotic locale in the company of rescued beautiful woman.

There are obviously other “states” that occur in an action movie, many of which involve beds, but in an effort to: a) keep this blog “safe for work”; and b) keep our example simple, we’ll reduce it to this list. Graphically, we could depict this as something like:

statemachineactionhero.jpg

The hero can remain in any one of these “states” indefinitely (and in some films it seems like the hero does!) until there is some event that triggers a “transition” between the states. Let’s look at our list again and add in some events:

  1. Hero is relaxing on a beach with a drink in some exotic locale.

    • Receives visit from courier who says his assistance is needed immediately. (Alternatively and more exciting for a movie, a team of assassins attempts to kill him.)
  2. Hero is preparing for mission (getting briefing, gadgets, etc.)

    • Receives final briefing, heads to airport, etc.
  3. Hero is hunting for evil villain.

    • Finds evil villain (or is found by evil villain).
  4. Hero is fighting evil villain and his minions.

    • Blows up villain and his lair, saves world, rescues beautiful woman.
  5. Hero is relaxing on a beach in some other exotic locale in the company of rescued beautiful woman.

At a 10,000 foot level, you can describe most action movies in this pattern. A series of states where events trigger transitions between those states.

So what does this have to do with CCXML, eh?

Well, you could take the basic successful inbound call to a CCXML application and describe it in the following states and events:

  1. CCXML application is waiting for connections.

    • Call is received.
  2. Application enters “Alerting” state to decide what to do with the call.

    • Application accepts call.
  3. Application is connected to incoming call and performs actions such as playing dialogs, accepting input, etc..

    • Application finishes – or caller hangs up.
  4. Application is disconnected from call and performs any final actions.

    • Application finishes post-call activity and exits.
  5. Application returns to waiting for connections.

Graphically, we could illustrate it like this:

statemachineccxmlsimplified.jpg

Conceptually, this is what it looks like. I would, though, note, that the “waiting” state I’ve shown here is not typically a part of the actual CCXML application but rather is part of the application platform on which your CCXML application is housed. For instance, the “platform” could be our Evolution hosted platform or a copy of our Prophecy premise platform running on your network. When a call is received by either Evolution or Prophecy, your CCXML application is loaded and (in this example) the “connection.alerting” event is sent which triggers the transition into the “Alerting” state.

You can think of this in a similar fashion to a web server. Your Apache (or other) web server is sitting there waiting for connections. When it receives a connection, it loads the appropriate page which may contain an application which is then executed. CCXML works in a similar fashion (and yes, there are exceptions… remember, I’m trying to keep this tutorial simple!).

In any event, let’s see what this looks like in CCXML code:

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
  <eventprocessor>
    <transition event="connection.alerting">
    <log expr="'*** Incoming call from Caller ID: ' + event$.connection.remote"/>
    <accept/>
    </transition>
    <transition event="connection.connected">
      <log expr="'*** Call was accepted ***'"/>
      <disconnect/>
    </transition>
    <transition event="connection.disconnected">
      <log expr="'*** Call was disconnected ***'"/>
      <exit/>
    </transition>
  </eventprocessor>
</ccxml>

That’s it. The <transition> tag indicates what actions should be taken when the event included in the “event” attribute occurs. Conceptually this is a transition between states. So when the event “connection.alerting” is received by this application the code in the first <transition> is executed. At the end of that block you can see the <accept/> command which is the action that causes a new event (“connection.connected“) to occur. Likewise, <disconnect/> and <exit/> in later states signal that a new event has occurred and a transition needs to occur.

Your task, then, is to write the actions that occur in each state since this code above does really nothing except accept and then hangup a call (and generate log entries). During the “alerting” state, for instance, maybe there are some phone numbers from which you do not want to accept calls. You may have some conditional logic there that rejects calls from some numbers and then accepts calls from all others. In the “connected” state, obviously, is where the meat of your application goes. What are you going to do with the caller?

With this framework in mind, you can now dive into the “Learning CCXML” section of our CCXML documentation and see the examples there that flesh out the very simple outline I’ve given here.

I should note, of course, that my simple example doesn’t even closely illustrate all the “states” in CCXML. What happens if a call fails in some way other than just a disconnect? What if there are errors in your application? How about outbound calls where the “alerting” concept doesn’t make sense? We go into the different states in our documentation and the actual CCXML specification from the W3C also has this nice diagram (click on the image to see it larger):

ccxmlstatediagram.jpg

(Hint: For an outbound call, the initial state equivalent to “alerting” is “progressing“.) This, too, does not show all the states, but does provide a richer view of the flow of a typical CCXML application. As you’ll see in the documentation, there’s a lot more you can do with states in CCXML. You can create your own events that you us the <send> command to trigger a transition to a new state. There are a range of pre-defined states as well, that both our documentation and the W3C CCXML specification describe in more detail.

Again, it is all about the CCXML application describing a series of “states” and what actions occur during that state. Events trigger transitions between states.

Got it? Ready to start actually building applications? If so just head over to www.voxeo.com/free and sign up for either a free developer account on our Evolution hosted platform or download our free Prophecy premise platform to run on your own server. Figure out your states and away you go…

P.S. If you are really intrigued by all the theory around state machines, you might want to check out the “Semantics” section of another W3C draft language called SCXML (“State Chart XML”) which dives into the theory around Harel State Tables and much more. The aim of the (draft) SCXML effort is to create a more generic state machine language which is not tied to telephony as CCXML is. If all you want to do is write voice applications, feel free to skip these links entirely! :-)

Technorati Tags: , , , , , , , , , , ,


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


CCXML and SIP, Part 1: Accessing SIP headers

Tuesday, May 6th, 2008

ccxml.jpgIf you use SIP to connect to your voice appliction, one of the very nice things about CCXML is that you have full access to the underlying SIP headers that were sent as part of the SIP connection. With access to the SIP headers, you can then record information or make decisions in your code based on the contents of those headers.

First, let’s take a look at a typical SIP INVITE message that begins a call between two parties:

INVITE sip:1234@company2.com SIP/2.0
Via: SIP/2.0/UDP proxy.company2.com:5060;branch=z9hG5bK21ghi7ab34
Via: SIP/2.0/UDP sip.company1.com:5060;branch=z9hG4bKnashds7
To: sip:1234@company2.com
From: sip:dan@company1.com;tag=451248
Call-ID: 324817637683475998ababcc10
CSeq: 1 INVITE
Contact: sip:dan@company1.com
Max-Forwards: 50
P-Asserted-Identity: "Dan York" <sip:dan@company2.com>

In CCXML, any and all of those headers are available to you using the following syntax:

event.connection.protocol.sip.headers['To']

You can use this information in a conditional statement, in a variable, or in a log statement such as this:

<log expr="'*** The SIP To header is ' + event$.connection.protocol.sip.headers['To']"/>

Note that for the headers whose names do not include a dash in them, there is also a shorter style:

<log expr="'*** The SIP From header is ' + event$.connection.protocol.sip.headers.to"/>

If the header names do include a dash in them, then they do need to be enclosed in brackets and single quotes. Here are some more examples of accessing the SIP headers from a connection object:

event.connection.protocol.sip.headers['To']
event.connection.protocol.sip.headers['P-Asserted-Identity']
event.connection.protocol.sip.headers.from

Let’s take a look at where you might see this code (shown in red) appear within a (admittedly VERY basic and not very useful) CCXML file:

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
  <eventprocessor>
    <transition event="connection.alerting">
    <log expr="'*** The calledID is ' + event$.connection.local"/>
    <log expr="'*** The caller ID is ' + event$.connection.remote"/>
    <log expr="'*** The SIP From header is ' + event$.connection.protocol.sip.headers.from"/>
    <accept/>
    </transition>
    <transition event="connection.connected">
      <log expr="'*** Call was accepted ***'"/>
      <disconnect/>
    </transition>
    <transition event="connection.disconnected">
      <log expr="'*** Call was disconnected ***'"/>
      <exit/>
    </transition>
    <transition event="connection.failed">
      <exit/>
    </transition>
  </eventprocessor>
</ccxml>

Now here all we did was access the SIP header and then log one piece of information. Next time we’ll take a look at a more involved example where we use the SIP headers to change the actions inside the CCXML application.


If you would like to try out this code in a working environment head on over to www.voxeo.com/free and either join our (free) hosted development platform or download our (free) Prophecy software.

Technorati Tags: , , , , , ,


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.


Accessing Web Services From CCXML

Monday, April 28th, 2008

This is a guest post from Mark Headd, a voice application developer who was one of the first 10,000 users of our platform, and was originally published on his Vox Populi blog on April 21, 2008.


This is the first in a series of posts that will highlight how to accomplish specific things using the Voxeo Prophecy platform. All of the examples that will be discussed draw directly from the GreenPhone project discussed in a previous post.

The first issue that will be discussed – accessing web services from CCXML using PHP.

One of the very cool things about Prophecy is that it comes bundled with the PHP scripting language. In fact, I have on occasion referred to PHP as Prophecy’s “embedded scripting language.” PHP 5 comes with an abundance of features that will be of interest to IVR developers – chief among them, the ability to create SOAP clients to interact with web services, and the ability to easily work with data in XML format using the SimpleXML extension.

If you’ve read my previous post on the GreenPhone Project, you will know that I am using a collection of web services from StrikeIron that includes a web service to provide information on U.S. area codes. If we pass this web service an area code, it will return the U.S. state that area code is in. Ultimately, what the GreenPhone application will do is look up E85 and bio-diesel stations by state. So when a person calls the application, we want to use their area code to look up what state they are in – thereby saving them the trouble of entering this information manually.

In CCXML, we can access the caller’s ANI via the Connection Object:

<transition state="initial" event="connection.alerting">
 <log expr="'*** Call is coming in.  Lookup area code information. ***'"/>
 <assign name="ani" expr="event$.connection.remote"/>
 <assign name="areacode" expr="ani.substring(0,3)"/>
 <send target="'php/areaCodeLookup.php'" name="'lookupEvent'" targettype="'basichttp'" namelist="areacode"/>
</transition>

This block of code show how to set up a transition to access the ANI on an incoming call. When an incoming call is detected by Prophecy, the “connection.alerting” event is delivered and we have access to the Connection Object’s “remote” property – this property exposes the telephone URL for the device that is calling into the platform. Note – in my previous post, I explained the process of setting up the Prophecy SIP phone to deliver a specific ANI. This is how we access the value that is set in the Prophcy SIP phone.

We assign the ANI value to a variable we have previously declared and (very cleverly) called “ani”, and then we grab the first 3 characters of this string (using the ECMAScript substring method) and assign them to another variable called “areacode”. We then pass the area code value to a PHP script that will interact with the StrikeIron area code web service.

Using the CCXML <send/> element in this fashion is identical to an HTTP GET with the areacode variable appended to the URL of the PHP script, like this:

http://myserver/php/areaCodeLookup.php?areacode=123

There several possible outcomes of this HTTP request:

  1. Our PHP script was able to successfully interact with the StrikeIron web service and lookup the U.S. state information for the submitted area code;
  2. Our PHP script was able to successfully interact with the StrikeIron web service but was not able to lookup the state information for the submitted area code (bad area code);
  3. Something went wrong (an exception occurred) while trying to interact with the web service; or,
  4. Something really went wrong and our HTTP request resulted in a bad response from the server.

We need to set up handlers for each possible outcome – we won’t discuss them in detail until after we look more closely at the PHP components that are interacting with the StrikeIron web service, but to summarize what we’ll need, here they are:

<transition state="lookup" event="areaCodeLookupSuccess">
</transition>
<transition state="lookup" event="areaCodeLookupFailure">
</transition>
<transition state="lookup" event="error.send.failed">
</transition>

The first two handlers react to custom events that we will toss into the CCXML event stream (more on that shortly), and the last will take care of instances where we get an invalid response back from the server (e.g., a 404 response). Now lets look at the PHP components that interact with the StrikeIron web services.

When the HTTP request from Prophecy that holds our area code information is received in PHP, we can access the submitted value by using the PHP $_REQUEST superglobal:

$areacode = (int) $_REQUEST['areacode'];

You’ll notice that we also typecast the value as a way of cleansing the input – as with any other kind of web application, never trust user input. Even though we’re not using the submitted information in a SQL query, this is a really good habit to get into. There are certainly other ways to achieve this, but type casting is simple and effective for our purposes.

The PHP version that comes bundled with Prophecy has support for PHP’s SOAP extension right out of the box. Since we’re going to be accessing several different web services over the course of one telephone call, I decided to set up a very simple class to handle all of the interactions with the StrikeIron web services.

class greenSoapClient {
  private $client;
  private $headers;
  function __construct($type) {
    global $WSDL, $USER, $PSWD;
    $this->client = new SoapClient($WSDL[$type], array('trace' => 1,
                                          'exceptions' => 0));
    $headerArray = array("RegisteredUser" => array("UserID" => $USER,
                                          "Password" => $PSWD));
    $this->headers = new SoapHeader("http://ws.strikeiron.com",
                                          "LicenseInfo", $headerArray);
  }
  function makeSoapCall($name, $params) {
    $result = $this->client->__call($name, array($params), NULL, $this->headers);
    return $this->client->__getLastResponse();
  }
  function __destruct() {
    unset($this->client);
  }
}

This class has only three functions – a constructor, a destructor and a function to make the call to the SOAP method we want information from.

When we instantiate the greenSoapClient class, we pass in a reference to a WSDL file for the service we want to invoke. In this case, we will pass in a reference to the WSDL file for the U.S. Area Code Information Web Service. (Actually, the string “areaCode” is used to access the WSDL reference from a pre-established associative array holding the URL references for all of the WSDL files used by the greenPhone application.)

$mySoapClient = new greenSoapClient("areacode");

Now that we have our area code information, and a shiny new greenSoapClient object to work with, we can make our SOAP call:

$param = array('AreaCode' => $areacode);
$response = $mySoapClient->makeSoapCall('GetAreaCode', $param);

The variable $response now holds the XML response that was returned from the web service. We’ll need to process this response in order to properly format the information we want to return to CCXML.

One of the very cool things about the Voxeo implementation of CCXML is that developers can toss custom events into the CCXML event stream using simple HTTP responses. Prophecy lets us send back a custom event, as well as any data that we want to access in CCXML as properties of that event. We do this by formatting our response as follows:

First line of body of HTTP response = custom event name. Data to be returned to CCXML = name value pair appearing on successive lines of the HTTP body, one pair per line.

The U.S. Area Code Information Web Service returns two pieces of information that we want to access in CCXML – a count of the number of locations identified for each area code (typically 1), and the name of the U.S. state that area code belongs to. A snippet of the raw response returned from the web service might look something like this (for the 610 area code):

<ServiceResult>
 <Count>1</Count>
 <AreaCodes>
  <AreaCodeInfo>
   <AreaCode>610</AreaCode>
   <Location>Pennsylvania</Location>
  </AreaCodeInfo>
 </AreaCodes>
</ServiceResult>

We want to format our raw XML response like so:

areaCodeLookupSuccess
count=1
location=Pennsylvania

The easiest way to do this in PHP is to use the SimpleXML extension:

$xml = new SimpleXmlElement($response);
$result = $xml->soapBody->GetAreaCodeResponse->GetAreaCodeResult;
$output = "areaCodeLookupSuccess\n";
$output .= "count=".$result->ServiceResult->Count."\n";
$output .= "location=".$result->ServiceResult->AreaCodes->AreaCodeInfo->Location."\n\n";

We take the response from the StrikeIron web service and use it to create a new SimpleXML object. We can then access the values we want and build our HTTP response.

How do we deliver our response once we’re done constructing it, we simply use the PHP “echo” language construct to write it out:

echo $output;

Now that we’ve returned our values to CCXML, how do we access them? For the answer to that,we need to go back to the handlers we set up previously, most importantly the handler for the custom “areaCodeLookupSuccess” event:

<transition state="lookup" event="areaCodeLookupSuccess">
 <assign name="count" expr="event$.count"/>
 <if cond="count == 1">
  <assign name="location" expr="event$.location"/>
  <assign name="stateCode" expr="getStateCode(event$.location)"/>
  <assign name="myState" expr="'accepting'"/>
  <accept connectionid="connection_id"/>
 <else/>
  <log expr="'*** Could not look up area code. ***'"/>
  <reject/>
 </if>
</transition>

When we write out our web service response in PHP, we can cause a custom event to drop into the CCXML event stream – the name of this event is the first line of the HTTP response we just constructed – areaCodeLookupSuccess.

We access the values we just returned to CCXML as properties of the areaCodeLookupSuccess event using the “event$.” vernacular. This allows us to assign these values to ECMAScript variables that we have previously declared. It also lets us decide how we want our application to react, based on certain conditions (e.g., if count = 0).

Similarly, our other event handlers can be used if we get an unexpected response form the web service – we could send back a “areaCodeLookupFailure” event. If something really bad happens – like an invalid response from the web server we will get an “error.send.failed” event, so we’ll want to have a handler ready for that as well.

Now that you have a flavor for how to access web services using CCXML and PHP, we’ll look at two different techniques for returning information from a web service to VoiceXML. We’ll cover these two techniques in the next two posts. Stay tuned…

Technorati Tags: , , , , , ,


If you found this post interesting or helpful, please consider either subscribing via RSS, becoming a fan on Facebook, or following us on Twitter.