' This is sample IVR application written in "classic" Visual Basic. It speaks the current weather ' condition to a caller whose has identified the locality whose weather he wants by speaking ' the digits of its ZIP code. ' ' Please note that while the sample may not be considered short, that has to do with what the ' sample does and not the form of its user interface. To put that another way, the entirety of ' the voice user interface code is held in the short (3 dozen exectuable lines) subroutine named ' Answer() which is immediately below. Sub Answer(kall As ComClientCall) Dim i As Integer Dim Ok As Boolean Dim Zip As String Dim Rec As ComRecognizer Dim Syn As ComSynthesizer Dim conf As Integer Dim Done As Boolean Dim Char As String Dim Forecast As String Dim Properties(4) As String ' In this application we use 65% as a confidence threshold for recognition. You can use ' whatever makes sense in your application. A more robust application might have two ' thresholds. Confidence scores below the lower number might cause the application to ' prompt again, confidence scores above the higher number might cause the application to ' accept the recognition, and scores between the two numbers might require confirmation Const ReqdConfidence As Integer = 6500 ' Grammar IDs are arbitrary as we demonstrate with these oddball numbers Const ZipGrammarId As Integer = 22 Const QuitGrammarId As Integer = 76 ' Get an instance of the synthesizer and greet the caller Set Syn = kall.getSynthesizer() Syn.speak ("Welcome to the weather demonstration application. " + _ "Say good bye or hang up when you are done.") ' Do some initialization while speaking Properties(0) = "Digit1" Properties(1) = "Digit2" Properties(2) = "Digit3" Properties(3) = "Digit4" Properties(4) = "Digit5" ' Get an instance of the recognizer ' Load a grammar that handles the request for the ZIP code ' Load another that handles the request to quit the application ' Mark the grammars as active but not dynamic (modifiable) Set Rec = kall.getRecognizer() Ok = Rec.loadGrammar("ZIP", ZipGrammarId, True, False) Ok = Rec.loadGrammar("Quit", QuitGrammarId, True, False) ' Wait for the speech to end now that the initialization is done Syn.wait (-1) Done = False Do While (Not (kall.isDisconnected() Or Done)) ' Start listening first and then prompt the caller Call Rec.listen Ok = Syn.speak("Please tell me the ZIP code for the town whose weather forecast you want to hear.") ' Wait for the recognizer to tell us how it did. ' We will wait at most 10 seconds for the user to begin to speak. ' In no case will we wait more than 30 seconds. conf = Rec.wait(10000, 30000) ' Stop listening Call Rec.stopListening ' Dump the state of the recognition for debugging Call Rec.dump ' On an error or disconnect we are done If conf < 0 Then Done = True ElseIf conf >= ReqdConfidence Then ' If we recognized a phrase in Quit grammar then we are done } If Rec.getGrammarId() = QuitGrammarId Then Done = True ' Otherwise we need a five digit ZIP code } Else Zip = "" For i = 0 To 4 Zip = Zip + Rec.getPropertyTextByName(Properties(i)) Next i If Len(Zip) <> 5 Then conf = 0 End If End If ' Apologize if we didn't understand If Not Done And conf < ReqdConfidence Then Call NoRecognition(Rec, Syn) ' If all is well, we proceed ElseIf Not Done Then ' Tell the caller to wait Syn.speak ("Please wait ...") ' Amuse him with "music on hold" kall.loopMessage ("strumming") ' Get his forecast while he listens to music Forecast = DoRequest(kall, Zip) ' Stop playing music and put a delay between the music and the speech kall.stopPlaying kall.wait (500) ' Speak the forecast and display it for debugging Syn.speak (Forecast) kall.writeln (Forecast) ' Log the input and output to the call detail records table Ok = kall.cdrStatusMessage(0, Zip) Ok = kall.cdrStatusMessage(1, Forecast) ' Let him hear the forecast before we ask if he wants to go again Syn.wait (-1) End If Loop ' If he is still on the line we will say good bye If Not kall.isDisconnected() Then Syn.speak ("Good bye.") Syn.wait (-1) End If End Sub Sub NoRecognition(Rec As ComRecognizer, Syn As ComSynthesizer) Call Rec.Reset Call Rec.listen Syn.speak ("I'm sorry, but I didn't get that.") Syn.wait (-1) End Sub ' Access a web service to retrieve the weather Function DoRequest(kall As ComClientCall, ZipCode As String) As String Dim QueryString As String Dim ObjXmlHttp As Object Dim ObjXmlDoc As Object ' Build a query string by appending a specific ZIP code to the base QueryString = "http://weather.yahooapis.com/forecastrss?p=" + ZipCode ' We use the XML HTTP object to send the request and fetch the response Set ObjXmlHttp = CreateObject("Msxml2.XMLHTTP") ObjXmlHttp.open "GET", QueryString, False ObjXmlHttp.send ' Either apologize if we failed to get the forecast or ' or build an intelligible response if we succeeded If ObjXmlHttp.Status <> 200 Then DoRequest = "We are sorry but we had trouble determining the weather for your ZIP code. " + _ "If the ZIP code is valid you can try again later." kall.writeln ("The weather service fails us: " + ObjXmlHttp.statusText + "(" + Str(ObjXmlHttp.Status) + " )") Else Set ObjXmlDoc = CreateObject("Msxml2.DomDocument.4.0") ObjXmlDoc.async = False ObjXmlDoc.loadXML (ObjXmlHttp.responseText) Call ObjXmlDoc.SetProperty("SelectionLanguage", "XPath") Call ObjXmlDoc.SetProperty("SelectionNamespaces", "xmlns:yweather='http://xml.weather.yahoo.com/ns/rss/1.0'") DoRequest = TranslateXMLtoForecast(ObjXmlDoc) End If End Function ' Crack open the XML document Function TranslateXMLtoForecast(XML As Object) As String Dim City As String Dim State As String Dim Outlook As String Dim Temperature As String ' For now we are interested in the city, wind speed and direction, ' current condition and temperature City = GetCity(XML) State = GetState(XML) Wind = GetWind(XML) Outlook = GetOutlook(XML) Temperature = GetTemperature(XML) ' Build two sentences from the five components above TranslateXMLtoForecast = "In " + City + " " + State + _ " the weather is " + Outlook + _ " with a temperature of " + Temperature + _ ". The winds are " + Wind + "." End Function ' Pull the city information from the XML Function GetCity(XML As Object) As String Dim Node As Object Dim Attr As Object Set Node = XML.selectSingleNode("//channel/yweather:location") Set Attr = Node.Attributes.getNamedItem("city") GetCity = Attr.Text End Function ' Pull the state information from the XML Function GetState(XML As Object) Dim Node As Object Dim Attr As Object Set Node = XML.selectSingleNode("//channel/yweather:location") Set Attr = Node.Attributes.getNamedItem("region") GetState = ExpandState(Attr.Text) End Function ' Pull the wind information from the XML Function GetWind(XML As Object) Dim Node As Object Dim Attr As Object Dim Speed As String Dim Degrees As String Set Node = XML.selectSingleNode("//channel/yweather:wind") Set Attr = Node.Attributes.getNamedItem("speed") Speed = Attr.Text Set Attr = Node.Attributes.getNamedItem("direction") Degrees = Attr.Text GetWind = "from the " + Direction(Degrees) + " at " + Speed + " miles per hour" End Function ' Pull the forecast from the XML Function GetOutlook(XML As Object) Dim Node As Object Dim Attr As Object Set Node = XML.selectSingleNode("//channel/item/yweather:condition") Set Attr = Node.Attributes.getNamedItem("text") GetOutlook = Attr.Text End Function ' Pull the temperature information from the XML Function GetTemperature(XML As Object) Dim Node As Object Dim Attr As Object Set Node = XML.selectSingleNode("//channel/item/yweather:condition") Set Attr = Node.Attributes.getNamedItem("temp") GetTemperature = Attr.Text + " degrees Fahrenheit" End Function