Volume 2, Issue 2 - Feb./March 2002
   
   

Call Control and Voice Apps: CCXML

By RJ Auburn

(Continued from Part 1)

What does CCXML look like?

Let's create a CCXML application. The following example was written on the Voxeo CCXML platform implementation. You can access Voxeo CCXML platform for free by signing up at http://community.voxeo.com.

The First Step

Lets start with the equivalent of a hello world application that conditionally answers the phone based on your caller id, plays a VoiceXML dialog and then hangs up. Being able to conditionally answer a call is one of the new features that CCXML brings to VoiceXML applications.

To start off we create a XML tag and a <ccxml> tag for the document. These are required in all CCXML documents.

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
</ccxml>    

 

Event Handlers

CCXML is based on a state machine model.

In general, a state machine is any program that stores the status of something at a given time and can operate on input (ie: telephony events) to change the state of the "machine" and can optionally cause an action to occur. State machines are used to develop and describe specific device or program interactions.

To summarize, a state machine can be described as:

  • An initial state or record
  • A set of possible input events
  • A set of new states that may result from the input
  • A set of possible actions or output events that result from a new state
In their book Real-time Object-oriented Modeling, Bran Selic & Garth Gullekson view a state machine as:
  • A set of states
  • A description of the initial state
  • A set of input events
  • A set of output events
  • A function that maps states and input to output
  • A function that maps states and inputs to states called a state "transition"

There are a number of ways to represent state machines, from simple tables, to C switch and case statements, to graphical design tools. CCXML uses XML tags to represent the state machine which will control one or more telephone calls.

If you're not familiar with State Machines, you might enjoy the interactive (and funny!) tutorial at http://www.theory.csc.uvic.ca/~mmania/machines/story/fsm.htm

The CCXML <eventhandler> tag contains all the event handlers, or "transitions" for our call-control application. In CCXML you write an event handler for your application and then the handlers transition tags will receive all the matching events that occur during a call.

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
<eventhandler>
<!-- Lets handle the incoming call ->
<transition event="connection.CONNECTION_ALERTING" name="evt">
<log expr="'The caller ID is ' + evt.callerid + '.'"/>
<if cond="evt.callerid == '8315551234'">
<accept/>
<else/>
<reject/>
</if>
</transition>
</eventhandler>
</ccxml>
 

We Are Now Connected

Next we add a <transition> tag for the call that we just answered. We are looking for the "connection.CONNECTION_CONNECTED" event. This event will only come into the CCXML platform once the call has been connected.

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
<eventhandler>
<!-- Lets handle the incoming call ->
<transition event="connection.CONNECTION_ALERTING" name="evt">
<log expr="'The caller ID is ' + evt.callerid + '.'"/>
<if cond="evt.callerid == '8315551234'">
<accept/>
<else/>
<reject/>
</if>
</transition>

<!-- Lets handle the call being answered ->
    
    <transition event="connection.CONNECTION_CONNECTED">
    </transition>
  </eventhandler>
</ccxml>
 


Running a Dialog

Next let's start a VoiceXML dialog script from the connected call event handler on the call we are connected to. We do this with the <dialogstart> tag and by specifying the URL source of the VoiceXML document we want to run. Once we do this the CCXML platform will connect the call to a VoiceXML resource and play the script to the caller.

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
<eventhandler>
<!-- Lets handle the incoming call -->
<transition event="connection.CONNECTION_ALERTING" name="evt">
<log expr="'The caller ID is ' + evt.callerid + '.'"/>
<if cond="evt.callerid == '8315551234'">
<accept/>
<else/>
<reject/>
</if>
</transition>

<!-- Lets handle the call being answered -->

<!-- Lets handle the call being answered -->

       <transition event="connection.CONNECTION_CONNECTED">
           <log expr="'Call was answered. We are going to start a dialog.'"/>
               <dialogstart src="'hello.vxml'"/>
       </transition>
    </eventhandler>
</ccxml>

Here is the content of hello.vxml:

<?xml version="1.0"?>
<!DOCTYPE vxml PUBLIC '-//Nuance/DTD VoiceXML 1.0//EN' 'http://voicexml.nuance.com/dtd/nuancevoicexml-1-2.dtd' >
<vxml version="1.0">
  <form id="Form">
     <block>
        Hello World.
          <exit/>
     </block>
   </form>
</vxml>

Ending a Dialog

We now add the <transition> tag to catch the event that indicates the VoiceXML dialog has ended. We do this by catching the "dialog.exit" event.

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
  <eventhandler>
  <!-- Lets handle the incoming call -->
    <transition event="connection.CONNECTION_ALERTING" name="evt">
    <log expr="'The caller ID is ' + evt.callerid + '.'"/>
      <if cond="evt.callerid == '8315551234'">
        <accept/>
      <else/>
        <reject/>
      </if>
    </transition>

    <!-- Lets handle the call being answered -->

    <transition event="connection.CONNECTION_CONNECTED">
      <log expr="'Call was answered. We are going to start a dialog.'"/>
        <dialogstart src="'hello.vxml'"/>
    </transition>

    <transition event="dialog.exit">
    </transition>
  </eventhandler>
</ccxml>


Disconnecting

Next we add the <disconnect> tag to the dialog exit handler to disconnect the caller from the CCXML platform. We will also write to the log using Voxeo's <log> tag.

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
  <eventhandler>
  <!-- Lets handle the incoming call -->
    <transition event="connection.CONNECTION_ALERTING" name="evt">
    <log expr="'The caller ID is ' + evt.callerid + '.'"/>
      <if cond="evt.callerid == '8315551234'">
        <accept/>
      <else/>
        <reject/>
      </if>
    </transition>

    <!-- Lets handle the call being answered -->

    <transition event="connection.CONNECTION_CONNECTED">
    <log expr="'Call was answered. We are going to start a dialog.'"/>
      <dialogstart src="'hello.vxml'"/>
    </transition>

    <transition event="dialog.exit">
    <log expr="'We got a dialog.exit event.'"/>
      <disconnect/>
    </transition>
  </eventhandler>
</ccxml>

Ending the Call

We are almost done with our first CCXML script. We only need to add some clean up code to exit the CCXML interrupter. We do this by adding a <transition> tag to catch the "call.CALL_INVALID" event:

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
  <eventhandler>
  <!-- Lets handle the incoming call -->
    <transition event="connection.CONNECTION_ALERTING" name="evt">
    <log expr="'The caller ID is ' + evt.callerid + '.'"/>
      <if cond="evt.callerid == '8315551234'">
        <accept/>
      <else/>
        <reject/>
      </if>
    </transition>

<!-- Lets handle the call being answered -->

    <transition event="connection.CONNECTION_CONNECTED">
    <log expr="'Call was answered. We are going to start a dialog.'"/>
      <dialogstart src="'hello.vxml'"/>
    </transition>

    <transition event="dialog.exit">
    <log expr="'We got a dialog.exit event.'"/>
      <disconnect/>
    </transition>

<!-- Lets clean up the call -->

    <transition event="call.CALL_INVALID">
    </transition>
  </eventhandler>
</ccxml>

The End Is Nigh

Finally we add a handler for the call_invalid event that occurs when a call ends, including an <exit> tag to leave the CCXML platform:

<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0">
  <eventhandler>
  <!-- Lets handle the incoming call -->
    <transition event="connection.CONNECTION_ALERTING" name="evt">
    <log expr="'The called ID is ' + evt.calledid + '.'"/>
      <if cond="evt.callerid == '8315551234'">
        <accept/>
      <else/>
        <reject/>
      </if>
    </transition>

<!-- Lets handle the call being answered -->

    <transition event="connection.CONNECTION_CONNECTED">
    <log expr="'Call was answered. We are going to start a dialog.'"/>
      <dialogstart src="'hello.vxml'"/>
    </transition>

    <transition event="dialog.exit">
    <log expr="'We got a dialog.exit event.'"/>
      <disconnect/>
    </transition>

<!-- Lets clean up the call -->

    <transition event="call.CALL_INVALID">
    <log expr="'The End is Nigh!.'"/>
      <exit/>
    </transition>
  </eventhandler>
</ccxml>


Congratulations, you have now written your very first CCXML application! If you would like to learn more about CCXML there are a number of tutorials that will help get you up to speed on of CCXML that you can access at http://community.voxeo.com

Comments?

The Call Control sub group would love to hear feedback on CCXML. You can get more information by visiting http://www.w3.org/Voice and subscribing to the www-voice@w3.org e-mail list or you can also contact me by sending e-mail to rj@voxeo.com.

back to the top

 

Copyright © 2001-2002 VoiceXML Forum. All rights reserved.
The VoiceXML Forum is a program of the
IEEE Industry Standards and Technology Organization (IEEE-ISTO).