In "The WAP Traffic Application," I explained how I created a Wireless Markup Language (WML) traffic application that lets you render the current traffic speeds for San Diego on any Wireless Application Protocol (WAP) device and HTML browser. In this column, I use VoiceXML to take that application a step further and make it voice or punch-key driven and add voice response. (If you're not familiar with VoiceXML, see "Adding VoiceXML to our .NET Wireless Repertoire" and "Adding VoiceXML to Our .NET Wireless Repertoire, Part 2".)
To get the traffic data I need, I call a Web service that one of my colleagues developed ( see, "Two Web Services Solutions"). Then, I create an XML Document Object Model (XMLDOM) object similar to the following:
<!DOCTYPE vxml PUBLIC "-//Tellme Networks//Voice Markup Language
1.0//EN" "http://resources.tellme.com/toolbox/vxml-tellme.dtd">
<vxml>
<meta name="scoping" content="new"/>
<form id="speed">
<block>
<%
Set xmlDoc = CreateObject("Microsoft.XMLDOM")
xmlDoc.async = False
xmlDoc.loadXML sXML
Set objNodeList = xmlDoc.getElementsByTagName("z:row")
. . .
This XMLDOM object provides access to the elements and the values I need from the XML that the GetTraffic method returns. Here's a sample of the XML that has the information I use:
<z:row TheFreeway='805 s' LocationDescription='Mira Mesa Blvd'
Speed='71' SourceTime='2001-06-10T13:42:00'/>
Below is the basic format of the information I need the system to read back to the caller:
<audio>Freeway exit name</audio> <audio> Speed</audio>
But I thought it would sound a lot better with a human voicenot just for the traffic speed, but also for the freeway exits. So I changed the above audio tags to the following:
<audio src="exitname.wav">Freeway exit name</audio>
<audio src="speed.wav"> Speed</audio>
Instead of letting the computer read out the exits and speeds, I use my recorded voice. Instead of letting the computer read out the exits and speeds, I use my recorded voice. If the application can't retrieve the .wav files, it generates a computer voice rendition of the attributes from the node list.
I created .wav files for each freeway exit and for speeds from 0 mph to 86 mph. Then, the trick was to get the application to read each .wav file that matched the exit name and its corresponding speed in the node list. I accomplished this with a For loop that matches the node list index with the exit name and repeats the same process to get the speeds. I saved all the exit name .wav files in the same format (e.g., 2_0.wav, which translates to the first exit on freeway 805). Because the exits aren't the same for the north and south freeways and the east and west freeways, I created different folders for each direction.
Then, I massaged each node to get it into a format that made sense to the caller when the system reads the data back. I wrote a couple of functions that strip out the date, time, and speed from the data that the GetTraffic method returns. However, I ran into one little challenge. The node list usually includes four attributes and their values. For some reason, sometimes the Web service (which relies on an outside source for its data) returns no speed attribute value. Below is the code and function I developed:
For intExitNameCount = 0 To (objNodeList.length - 1)
'See function below
strReturnSpeed = chkAttributeCount(objNodeList,intExitNameCount)
strReturnSpeedNoWav= strReturnSpeed 'If there is a problem
retrieving the wav file for the speed, then the actual value that
the Web service returns is used.
for intSpeedMatch = 0 To 86
if strReturnSpeed = intSpeedMatch then
strReturnSpeed = intSpeedMatch
end if
next
'Data Output:
Response.write "<audio src = "exitNameWavs/" & strFolderDirection &
"/" & _ strFreeWayID & "_" & intExitNameCount & "'>" & _
objNodelist.item(intExitNameCount).Attributes(1).Text & _
" </audio> <audio src='speedWavs/" & _
strReturnSpeed & ".wav'>" & strReturnSpeedNoWav & "</audio>"
next
Function chkAttributeCount(NodeObject,NodeNumber)
dim strSpeed
if NodeObject.item(NodeNumber).Attributes(2).name = "SourceTime"
then
'This happens only if there are only 3 Attributes
strTime = NodeObject.item(NodeNumber).Attributes(2).text
strSpeed = "No Value Returned"
chkAttributeCount = strSpeed
else strSpeed = objNodelist.item(NodeNumber).Attributes(2).Text
strTime = NodeObject.item(NodeNumber).Attributes(3).text
chkAttributeCount = strSpeed
end if
End Function
To access the application, dial 1-800-555-8355. You will hear a Tellme advertisement for about 15 seconds. When you hear the Main Menu, dial 1-24671.
End of Article