| CCXML 1.0-W3C Development Guide | Home | Frameset Home |
|
<send> element
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
</ccxml>
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="myState" expr="'init'"/>
<eventprocessor statevariable="myState">
<transition event="connection.alerting" state="init">
<log expr="'***** CONNECTION ALERTING *****'"/>
<accept/>
</transition>
<transition event="connection.connected" state="init">
<log expr="'***** CALL WAS ANSWERED *****'"/>
</transition>
<transition event="error.*">
<log expr="'an error has occured (' + event$.reason + ')'"/>
<log expr="'*** EVENT$.NAME = ' + event$.name"/>
<log expr="'*** EVENT$.REASON = ' + event$.reason"/>
<log expr="'*** EVENT$.TAGNAME = ' + event$.tagname"/>
<log expr="'*** EVENT$.EVENTID = ' + event$.eventid"/>
<log expr="'*** EVENT$.EVENTSOURCE = ' + event$.eventsource"/>
<log expr="'*** EVENT$.EVENTSOURCETYPE = ' + event$.eventsourcetype"/>
<voxeo:sendemail to="'youremail@somewhere.com'"
from="'myApp@here.com'"
type="'debug'"
body="'We had an error! \n Time to panic! \n
Flee the cities, abandon all hope!'"/>
<exit/>
</transition>
</eventprocessor>
</ccxml>
error.* handler, right? Wrong. Try copying this code by typing it out, and the laws of probability suggest that you will make a tpyo, (That last was on purpose. Get it?). When this happens, the <log> statements in this handler will show us in the real-time logger exactly where the goof occurred. And we are going to remember to change the 'sendmail' attribute to, you know, a valid email address at this point. That would be just swell.<dialogstart> element, of course. Later on in this tutorial, we may, (read: will), have need to access a user-defined 'dialogid' value, so let's declare this value at the start of our document. While we are at it, lets also apply what we learned about the connection object, and add the inevitable <log> statements to display some sweet, sweet connection object values in the debugger:
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="myState" expr="'init'"/>
<var name="myDialogID"/>
<eventprocessor statevariable="myState">
<transition event="connection.alerting" state="init">
<log expr="'***** CONNECTION ALERTING *****'"/>
<accept/>
</transition>
<transition event="connection.connected" state="init">
<log expr="'***** CALL WAS ANSWERED *****'"/>
<log expr="'***** EVENT$.CONNECTION.CONNECTIONID = ' + event$.connection.connectionid"/>
<log expr="'***** EVENT$.CONNECTION.PROTOCOL.NAME = ' + event$.connection.protocol.name"/>
<log expr="'***** EVENT$.CONNECTION.PROTOCOL.VERSION = ' + event$.connection.protocol.version"/>
<log expr="'***** EVENT$.CONNECTION.STATE = ' + event$.connection.state"/>
<log expr="'***** EVENT$.CONNECTION.LOCAL = ' + event$.connection.local"/>
<log expr="'***** EVENT$.CONNECTION.REMOTE = ' + event$.connection.remote"/>
<log expr="'***** EVENT$.CONNECTION.ORIGINATOR = ' + event$.connection.originator"/>
<dialogstart src="'myDialog.xml'" type="'application/voicexml+xml'" dialogid="myDialogID"/>
</transition>
<transition event="error.*">
<log expr="'an error has occured (' + event.reason + ')'"/>
<log expr="'*** EVENT$.NAME = ' + event$.name"/>
<log expr="'*** EVENT$.REASON = ' + event$.reason"/>
<log expr="'*** EVENT$.TAGNAME = ' + event$.tagname"/>
<log expr="'*** EVENT$.EVENTID = ' + event$.eventid"/>
<log expr="'*** EVENT$.EVENTSOURCE = ' + event$.eventsource"/>
<log expr="'*** EVENT$.EVENTSOURCETYPE = ' + event$.eventsourcetype"/>
<voxeo:sendemail to="'youremail@somewhere.com'"
from="'myApp@here.com'"
type="'debug'"
body="'We had an error! \n Time to panic! \n
Flee the cities, abandon all hope!'"/>
<exit/>
</transition>
</eventprocessor>
</ccxml>
<dialogstart> element is rather straightforward -- we hand it a source URL and a dialog name (the name is for CCXML event purposes only). That script is then executed by a VoiceXML server, running parallel to our CCXML session. Our beautiful, titanic, asynchronous state machine chugs along (la la la), waiting for a reply from the off-loaded dialog. <dialogstart> element:
<?xml version="1.0" encoding="UTF-8" ?>
<vxml version="2.0">
<meta name="maintainer" content="youremail@here.com"/>
<form id="dialogContainer">
<field name="F_1">
<grammar type="text/gsl">[(when its a jar) (what kind of a question is that)]</grammar>
<prompt>
<audio src="question.wav">
Greetings, and welcome to our humble Voice X M L dialog.
The burning question of the day is as follows:
When is a door not a door?
</audio>
</prompt>
<filled>
<log expr="' ***** CALLER SAID ' + F_1 + ' *****'"/>
<exit namelist="F_1"/>
</filled>
</field>
</form>
</vxml>
<field> gathers some caller input to a really simple riddle, and then passes this value back to the CCXML 1.0 layer via the <exit> command. Notice the "namelist" attribute: like all VoiceXML namelists, we can pass multiple variables back to our call control layer, and then access the value there if we desire. Which we do, thank you very much for asking. <send> to fire off an event to the CCXML interpreter, (or other external systems that make use of an Event I/O Processor). For the purposes of illustration, we will setup a call timer that will send a notification to the CCXML interpreter that kicks the user out of the dialog after 15 seconds. This event we will need to have a handler for it, so that we can direct the application to kill the dialog via the <dialogterminate> element, and bring the caller back into the CCXML context before we exit application execution. In order to do so, we will need to make a slight change to our state machine so that we can clearly define when the user is in the VoiceXML dialog, and when he is out of it entirely. To do so, we set the statevariable to 'dialogActive' right after the dialog starts. Let's now switch gears back to our fledgling CCXML 1.0 script, and take a gander at how this would look:
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="myState" expr="'init'"/>
<var name="myDialogID"/>
<eventprocessor statevariable="myState">
<transition event="connection.alerting" state="init">
<log expr="'***** CONNECTION ALERTING *****'"/>
<accept/>
</transition>
<transition event="connection.connected" state="init">
<log expr="'***** CALL WAS ANSWERED *****'"/>
<log expr="'***** EVENT$.CONNECTION.CONNECTIONID = ' + event$.connection.connectionid"/>
<log expr="'***** EVENT$.CONNECTION.PROTOCOL.NAME = ' + event$.connection.protocol.name"/>
<log expr="'***** EVENT$.CONNECTION.PROTOCOL.VERSION = ' + event$.connection.protocol.version"/>
<log expr="'***** EVENT$.CONNECTION.STATE = ' + event$.connection.state"/>
<log expr="'***** EVENT$.CONNECTION.LOCAL = ' + event$.connection.local"/>
<log expr="'***** EVENT$.CONNECTION.REMOTE = ' + event$.connection.remote"/>
<log expr="'***** EVENT$.CONNECTION.ORIGINATOR = ' + event$.connection.originator"/>
<dialogstart src="'myDialog.xml'" type="'application/voicexml+xml'" dialogid="myDialogID"/>
<assign name="myState" expr="'dialogActive'" />
<send name="'timeout'" target="session.id" delay="'15s'"/>
</transition>
<transition event="timeout" state="dialogActive">
<log expr="'***** TIMEOUT RECEIVED, NOW TERMINATING THE DIALOG *****'"/>
<dialogterminate dialogid="myDialogID" immediate="false"/>
</transition>
<transition event="send.successful" state="dialogActive">
<log expr="'***** SEND IS SUCCESSFUL *****'"/>
</transition>
<transition event="error.*">
<log expr="'an error has occured (' + event$.reason + ')'"/>
<log expr="'*** EVENT$.NAME = ' + event$.name"/>
<log expr="'*** EVENT$.REASON = ' + event$.reason"/>
<log expr="'*** EVENT$.TAGNAME = ' + event$.tagname"/>
<log expr="'*** EVENT$.EVENTID = ' + event$.eventid"/>
<log expr="'*** EVENT$.EVENTSOURCE = ' + event$.eventsource"/>
<log expr="'*** EVENT$.EVENTSOURCETYPE = ' + event$.eventsourcetype"/>
<voxeo:sendemail to="'youremail@somewhere.com'"
from="'myApp@here.com'"
type="'debug'"
body="'We had an error! \n Time to panic! \n
Flee the cities, abandon all hope!'"/>
<exit/>
</transition>
</eventprocessor>
</ccxml>
<transition> in there for the purposes of logging exactly when the <send> command bubbles back up to the CCXML 1.0 interpreter. You'll notice that both of our newly added handlers specifies that the state must have a value of 'dialogACtive' in order for these to be executed, as we indicated previously. We finally make use of the 'dialogID' attribute within the <dialogterminate> element, as this tells the CCXML 1.0 interpreter exactly which dialog we want to shut down in this case. <log> statements, (this time for the dialog object properties), and see the user utterance from the VoiceXML session bubble back up to the CCXML 1.0 layer:
<?xml version="1.0" encoding="UTF-8"?>
<!-- NOTE THAT WE *MUST* DECLARE THE xmlns ATTRIBUTE -->
<ccxml version="1.0" xmlns:voxeo="http://community.voxeo.com/xmlns/ccxml">
<var name="myDialogID"/>
<var name="myState" expr="'init'"/>
<eventprocessor statevariable="myState">
<transition event="connection.alerting" state="init">
<log expr="'***** CONNECTION ALERTING *****'"/>
<accept/>
</transition>
<transition event="connection.connected" state="init">
<log expr="'***** CALL WAS ANSWERED *****'"/>
<log expr="'***** EVENT$.CONNECTION.CONNECTIONID = ' + event$.connection.connectionid"/>
<log expr="'***** EVENT$.CONNECTION.PROTOCOL.NAME = ' + event$.connection.protocol.name"/>
<log expr="'***** EVENT$.CONNECTION.PROTOCOL.VERSION = ' + event$.connection.protocol.version"/>
<log expr="'***** EVENT$.CONNECTION.STATE = ' + event$.connection.state"/>
<log expr="'***** EVENT$.CONNECTION.LOCAL = ' + event$.connection.local"/>
<log expr="'***** EVENT$.CONNECTION.REMOTE = ' + event$.connection.remote"/>
<log expr="'***** EVENT$.CONNECTION.ORIGINATOR = ' + event$.connection.originator"/>
<dialogstart src="'myDialog.xml'" type="'application/voicexml+xml'" dialogid="myDialogID"/>
<assign name="myState" expr="'dialogActive'" />
<send name="'timeout'" target="session.id" delay="'15s'"/>
</transition>
<transition event="timeout" state="dialogActive">
<log expr="'***** TIMEOUT RECEIVED, NOW TERMINATING THE DIALOG *****'"/>
<dialogterminate dialogid="myDialogID" immediate="false"/>
</transition>
<transition event="send.successful" state="dialogActive">
<log expr="'***** SEND IS SUCCESSFUL *****'"/>
</transition>
<transition event="error.dialog.notstarted'">
<log expr="'****** ERROR.DIALOGNOTSTARTED.NAME = ' + event$.name"/>
<log expr="'***** EVENT$.NAME = ' + event$.name"/>
<log expr="'***** EVENT$.DIALOGID = ' + event$.dialogid"/>
<log expr="'***** EVENT$.DIALOG = ' + event$.dialog"/>
<log expr="'***** EVENT$.CONFERENCEID = ' + event$.conferenceid"/>
<log expr="'***** EVENT$.CONNECTIONID = ' + event$.connectionid"/>
<log expr="'***** EVENT$.REASON = ' + event$.reason"/>
<log expr="'***** EVENT$.EVENTID = ' + event$.eventid"/>
<log expr="'***** EVENT$.EVENTSOURCE = ' + event$.eventsource"/>
<log expr="'***** EVENT$.EVENTSOURCETYPE = ' + event$.eventsourcetype"/>
<exit/>
<exit/>
</transition>
<transition event="error.send.targetunavailable">
<log expr="'***** SEND TARGET UNAVAILABLE *****'"/>
<exit/>
</transition>
<transition event="dialog.exit" state="'dialogActive'">
<log expr="'***** DIALOG EXIT IN DIALOG ACTIVE STATE *****'"/>
<exit/>
</transition>
<transition event="dialog.exit">
<log expr="'***** CALL EXITING *****'"/>
<log expr="'***** event$.VALUES.F_1 =' + event$.values.F_1"/>
<log expr="'***** EVENT$.NAME = ' + event$.name"/>
<log expr="'***** EVENT$.DIALOGID = ' + event$.dialogid"/>
<log expr="'***** EVENT$.CONFERENCEID = ' + event$.conferenceid"/>
<log expr="'***** EVENT$.CONNECTIONID = ' + event$.connectionid"/>
<log expr="'***** EVENT$.EVENTID = ' + event$.eventid"/>
<log expr="'***** EVENT$.EVENTSOURCE = ' + event$.eventsource"/>
<log expr="'***** EVENT$.EVENTSOURCETYPE = ' + event$.eventsourcetype"/>
<!-- DIALOG OBJECT PROPERTIES -->
<log expr="'***** EVENT$.DIALOG.DIALOGID = ' + event$.dialog.dialogid"/>
<log expr="'***** EVENT$.DIALOG.CONNECTIONID = ' + event$.dialog.connectionid"/>
<log expr="'***** EVENT$.DIALOG.CONFERENCEID = ' + event$.dialog.conferenceid"/>
<log expr="'***** EVENT$.DIALOG.TYPE = ' + event$.dialog.type"/>
<log expr="'***** EVENT$.DIALOG.SRC = ' + event$.dialog.src"/>
<log expr="'***** EVENT$.DIALOG.INPUT = ' + event$.dialog.input"/>
<log expr="'***** EVENT$.DIALOG.OUTPUTS = ' + event$.dialog.outputs"/>
<exit/>
</transition>
<transition event="error.*">
<log expr="'an error has occured (' + event$.reason + ')'"/>
<log expr="'*** EVENT$.NAME = ' + event$.name"/>
<log expr="'*** EVENT$.REASON = ' + event$.reason"/>
<log expr="'*** EVENT$.TAGNAME = ' + event$.tagname"/>
<log expr="'*** EVENT$.EVENTID = ' + event$.eventid"/>
<log expr="'*** EVENT$.EVENTSOURCE = ' + event$.eventsource"/>
<log expr="'*** EVENT$.EVENTSOURCETYPE = ' + event$.eventsourcetype"/>
<voxeo:sendemail to="'youremail@somewhere.com'"
from="'myApp@here.com'"
type="'debug'"
body="'We had an error! \n Time to panic! \n
Flee the cities, abandon all hope!'"/>
<exit/>
</transition>
</eventprocessor>
</ccxml>
<log> statements. The real 'guts' of our new additions to the code are the event handlers for 'error.send.targetunavailable', and 'error.dialog.notstarted': In both of these cases, we log the event, and skeedaddle. The other important additions are both kinds of 'dialog.exit' event handlers: you'll notice that one defines that the state must be set to 'dialogActive', which means that this will be kicked off when a 'timeout' event is thrown. The other 'dialog.exit' handler is going to be kicked off when we receive a valid utterance in the VoiceXML, and the <exit namelist> event transfers control back to the CCXML 1.0 context. Within here, we log some event object properties, and some dialog object properties. This is somewhat redundant in this case, as we have a bit of overlapping data. No matter. Looking closely, you'll also see the 'evt.values.F_1' <log> statement: This contains the value returned form the VoiceXML dialog, just like we promised. Since our <field> is christened "F_1" within the VoiceXML dialog, we then reference the value within the CCXML 1.0 as a property of the dialog object, (ie, 'event$.values.F_1'). If we are passing in more than one value back to the CCXML, we can log each one independently of one another, and reassign these values to local CCXML 1.0 variables, if we so desire.<log> statements are really handy, sometimes! <log> statements in your CCXML 1.0 applications<send> element| ANNOTATIONS: EXISTING POSTS |
steve1_rm
|
|
| Hello,
I am just wondering about the following statement: <filled> <log expr="' ***** CALLER SAID ' + F_1 + ' *****'"/> <exit namelist="F_1"/> </filled> Will this return the contents of field F_1? I am currently working on a project that will allow the user to input a 4 digit pin number for call forwarding. So my F_1 will return the 4 digits that will be used for call forward inside the ccxml. <dialogstart src="'myDialog.xml'" type="'application/voicexml+xml'" dialogid="myDialogID"/> The above line will call the dialog, but where will the F_1 field be returned to. Many thanks for any advice, Steve |
|
VoxeoDustin
|
|
| Hey Steve,
That will return the interpretation value of the field to CCXML. You can access in CCXML within your dialog.exit event like so: [code] <transition event="dialog.exit"> <assign name="myVar" expr="event$.values.F_1"/> <log expr="'****** DIALOG EXIT - F_1 = ' + myVar"/> </transition> [/code] Hope this helps. Thanks, Dustin |
|
weichen
|
|
| I am bit confused about the two dialog.exit transition.
When <transition event="dialog.exit"> happens, what is the value of myState variable? If the value is dialogActive, what's the difference between the two dialog.exit transitions? |
|
VoxeoDustin
|
|
| Hey Wei,
CCXML will execute in a top-down manner until it reaches a transition that matches. A dialog.exit without a state variable will match anytime that event is thrown, so the state variable's value is not evaluated. There is no major difference in this particular example, except that one dialog logs a few more things before exiting. It is simply exhibiting how we can handle an event differently depending on the value of our state variable. Let me know if this clarifies. Thanks, Dustin |
|
weichen
|
|
| Hi, Dustin,
When a dialog.exit event occurs while myState == dialogActive, CCXML should go to <transition event="dialog.exit" state="'dialogActive'"> since CCXML is running top-down. Is this right? However, my test shows CCXML goes to <transition event="dialog.exit"> while myState == dialogActive. ----- 00241 3059 00:29:38 AM matched transition (, dialog.exit, ) @ eventhandler (, myState) 00242 3059 00:29:38 AM log: ***** CALL EXITING ***** 00243 3059 00:29:38 AM log: mystate = dialogActive ...!!!!... 00244 3059 00:29:38 AM log: ***** event$.VALUES.F_1 =when its a jar 00245 3059 00:29:38 AM log: ***** EVENT$.NAME = dialog.exit ----- That's where I am confused. |
|
voxeoJohn
|
|
| Hey Wei,
If this is your transition [code] <transition event="dialog.exit" state="'dialogActive'">[/code] then you need to remove the single quotes from the state variable. <transition event="dialog.exit" state="'dialogActive'"> <transition event="dialog.exit" state="dialogActive"> Its hard to see here but this is why it is defaulting to the other dialog.exit handler. Hope that helps! Regards, John Voxeo Supporteon |
|
weichen
|
|
| Hi, John,
I assume sample code in Step 5 in the above document should be fixed. Here is the piece from the Step 5 sample code. [code] ... <transition event="dialog.exit" state="'dialogActive'"> <log expr="'***** DIALOG EXIT IN DIALOG ACTIVE STATE *****'"/> <exit/> </transition> ... [/code] After I change it to [code] ... <transition event="dialog.exit" state="dialogActive"> <log expr="'***** DIALOG EXIT IN DIALOG ACTIVE STATE *****'"/> <exit/> </transition> ... [/code] Things work as expected. The last question is, in what circumstance (or never), this CCXML will transition into <transition event="dialog.exit">, given 1)there is only one dialog in this CCXML 2)myState is always set to dialogActive once the dialog is started? Thanks. |
|
voxeoJeffK
|
|
| Hi,
We apologize if that part of the tutorial was confusing to you. I believe the transition for dialog.exit that specifies state="'dialogActive'" is there for example purposes, and that's why the author included the single quotes to effectively disable the transition. That is to say the author wanted to show examples of dialog.exit transitions. One included a state designation, and one did not. You are correct in the statement that, after removing the single quotes, this particular script will always hit the first dialog.exit transition since it is always in state=dialogActive. Regards, Jeff K. |
| login |
|