Ozeki VoIP SDK - Product Guide
Developers Guide
Visual Basic .NET DTMF IVR
![]() |
Download: | 34_DTMFIVR_VB.NET.zip |
This article introduces a DTMF navigated IVR system written in Visual Basic .NET programming language. The IVR tree is built up from an .xml file and the SIP communication is supported by Ozeki VoIP SIP SDK.
Introduction
Interactive Voice Response (IVR) systems use a tree structured menu that can be navigated by using the DTMF (Dual-tone multi-frequency) signals that are sent to a telephoning client when the remote user presses a button on the telephone or softphone keypad.
The DTMF signals are special sound frequencies that can be recognized in the VoIP client and if there is an implemented function for the use of these sounds, the VoIP client can use them for any purpose.
In the IVR systems the caller clients can navigate in the menu tree by using DTMF signals. This operation usually made by the IVR server playing an audio that instructs the user to press certain keypad buttons in order to get to the answer for their problem. When the user pressed the right button, the IVR system enters the appropriate branch of the menu tree and the instruction process continues. This process is done until the user reaches the bottom of the menu tree or presses a button for getting into connection with a human operator if possible.
Ozeki VoIP SIP SDK provides all the support for implementing an IVR system that can be navigated by DTMF signals. You only need to use the provided classes and methods and you will soon have your own IVR server.
The following program code uses the background support of Ozeki VoIP SIP SDK, therefore you will need to download and install the SDK on your computer before starting to use the program code. You will also need to have Visual Studio 2010 or compatible IDE and .NET Framework installed on your system, as the program code below is written in Visual Basic .NET language.
Source Code Explanation
This IVR system registers a softphone to a PBX with a SIP account that is defined in an
application configuration file. This file is a standard tool that can be used for configuration purposes.
Note that you need to set your own SIP data in the app.config file
if you want your IVR work properly.
Code 1 shows the part of the app.config file that defines the SIP information for the IVR system. You can set your own SIP account and PBX information in this file.
<appSettings>
<add key="IsRegRequired" value="true" />
<add key="displayname" value="oz879" />
<add key="username" value="oz879" />
<add key="registername" value="oz879" />
<add key="regpass" value="oz879" />
<add key="domainhost" value="192.168.112.100" />
<add key="port" value="5060" />
<add key="nat" value="0" />
<add key="ClientSettingsProvider.ServiceUri" value="" />
</appSettings>
Code 1 - SIP account data in the application configuration file
The app.config file is parsed in the Softphone class. There is a register() method (Code 2) taht does the parsing. The application configuration file can be handled by using a standard tool called ConfigurationManager that is a class in the System.Configuration namespace.
If you add the SIP information in the app.config file the same way as in this example, you can gain the information by using the ConfigurationManager.AppSettings tool. In this case you can use the key element in the app.setting to index the AppSettings array and you can get the values for the keys. In some cases, you need to convert the gained data as they are all stored as strings in the application configuration file.
Private Sub register()
Try
Dim cm = ConfigurationManager.AppSettings
IsRegRequired = Boolean.Parse(cm("IsRegRequired"))
displayname = cm("displayname")
username = cm("username")
registername = cm("registername")
regpass = cm("regpass")
domainhost = cm("domainhost")
port = Int32.Parse(cm("port"))
Select Case Int32.Parse(cm("nat"))
Case 0
natTraversal = NatTraversalMethod.None
Case 1
natTraversal = NatTraversalMethod.STUN
Case 2
natTraversal = NatTraversalMethod.TURN
End Select
Dim sa As New SIPAccount(IsRegRequired, displayname, username, registername, regpass, domainhost, port)
Dim nc As New NatConfiguration(natTraversal)
phoneLine = softPhone_Renamed.CreatePhoneLine(sa, nc)
AddHandler phoneLine.PhoneLineStateChanged, AddressOf phoneLine_PhoneLineInformation
softPhone_Renamed.RegisterPhoneLine(phoneLine)
Catch ex As Exception
MessageBox.Show(String.Format("You didn't set the right IP address. Please set your IP address and try again" & vbLf & " {0}", ex.Message), String.Empty, MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Code 2 - Parsing the app.config file
The IVR tree information in this example program is stored in an XML file those structures can be seen in Code 3. The tree is built up from this file, that can be modified in a simple way being a text file.
<?xml version="1.0" encoding="utf-8" ?>
<node>
<name>Name</name>
<message>Message</message>
<signal>signal</signal>
<children>
<node>...
</children>
</node>
Code 3 - The XML structure for the IVR tree information
The actual IVR tree is built up in the Softphone class within the buildTree method (Code 4). This method calls a recursive method in the TreeXMLParser class, specifies the .xml file of the IVR information and sets up the TreeView that will be the graphical representation of the IVR tree on thye GUI.
Private Sub buildTree()
root = TreeXMLParser.parse(TreeXMLParser.treedoc, Nothing)
treeView1.Nodes.Add(root.treeNode)
selectedNode = root
selectedTreeNode = root.treeNode
Try
treeView1.SelectedNode = selectedTreeNode
treeView1.SelectedNode.ForeColor = Color.Red
Catch e1 As Exception
MessageBox.Show("Error", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Sub
Code 4 - Building up the IVR tree using the TreeXMLParser class
The TreeXMLParser (Code 5) is a service class that only contains a recursive method for the XML parsing and the actual .xml file path that it parses. If you want to use a different IVR xml file for the tree, you can specify the file path in this class.
The parse function recursively parses the specified .xml file and builds up a tree structure of the IVRNode objects. The IVRNode class is also implemented in the example project.
Friend Class TreeXMLParser
Public Shared treedoc As XElement = XElement.Load("../../TreeData.xml")
Public Shared Function parse(ByVal element As XElement, ByVal parentNode As IVRNode) As IVRNode
Dim node As New IVRNode(element.Element("name").Value.ToString(), element.Element("message").Value.ToString(), parentNode)
For Each childnode As XElement In element.Element("children").Elements("node")
Try
node.AddChild(Int32.Parse(childnode.Element("signal").Value.ToString()), parse(childnode, node))
Catch ex As Exception
MessageBox.Show(String.Format("error {0}", ex), "error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Next childnode
Return node
End Function
End Class
Code 5 - The TreeXMLParser class
The IVRNode class (Code 6) represents a node in the IVR tree. A node stores the IVR message information, the name element, tha parent node (except for the root element) and a Dictionary object for the child nodes.
The key element in the children Dictionary stores the DTMF signal code that needs to be pressed for reaching that certain child node from the actual IVR node. The class also provides some functions that can be used for adding and getting child nodes to and from the node.
The addChild function is used when building up the IVR tree, while the getChild is typically the one used for the IVR tree navigation.
Friend Class IVRNode
Public treeNode As TreeNode
Private parent As IVRNode
Private children As New Dictionary(Of Integer, IVRNode)()
Private name As String
Public message As String
Public Sub New(ByVal name As String, ByVal message As String)
Me.name = name
Me.message = message
Me.parent = Nothing
treeNode = New TreeNode(name)
End Sub
Public Sub New(ByVal name As String, ByVal message As String, ByVal parent As IVRNode)
Me.name = name
Me.message = message
Me.parent = parent
treeNode = New TreeNode(name)
End Sub
Public Sub AddChild(ByVal signal As Integer, ByVal child As IVRNode)
children.Add(signal, child)
treeNode.Nodes.Add(child.treeNode)
End Sub
Public Function getChild(ByVal signal As Integer) As IVRNode
If children.ContainsKey(signal) Then
Return children(signal)
End If
Return Nothing
End Function
End Class
Code 6 - The class that stores the IVR tree nodes
The IVR tree navigation is made by receiving DTMF signals. This means that the call need to be subscribed for the DtmfReceived event and a specified event handler needs to be written like the one in Code 7.
The class always stores the actually selected IVRNode that stores in a Dictionary object all its children. When a DTMF signal is received, the method checks if it is a star of a hash mark as they hold special meaning. Pressing the star will always restart the actual tree node message, pressing the hash will navigate back to the root if you are not there already. When the caller pressed a number key on the keypad, the method tries to get the actual node's child that is attached to that DTMF signal. If there is no such child, the message will go on without any jumping in the tree structure. If the incoming DTMF signal refers to a valid child, the program will jump in the tree structure to the specified child and its message will be started. The GUI will also refreshed for showing the latest selected node.
Private Sub call_DtmfReceived(ByVal sender As Object, ByVal e As VoIPEventArgs(Of OzTuple(Of VoIPMediaType, DtmfSignal)))
InvokeGUIThread(Sub() label1.Text = String.Format("DTMF signal received: {0} ", e.Item.Item2.Signal))
'you can restart the actual message by pressing star
If e.Item.Item2.Signal = 10 Then
ivrReader.StopStreaming()
ivrReader.AddAndStartText(selectedNode.message)
End If
'pressing hash gets you back to the main menu
If e.Item.Item2.Signal = 11 AndAlso (Not atRoot) Then
atRoot = True
selectedNode = root
selectedTreeNode = root.treeNode
InvokeGUIThread(Sub()
treeView1.SelectedNode.ForeColor = Color.Black
treeView1.SelectedNode = selectedTreeNode
treeView1.SelectedNode.ForeColor = Color.Red
End Sub)
ivrReader.StopStreaming()
ivrReader.AddAndStartText(selectedNode.message)
End If
'stepping into a submenu if exists
If selectedNode.getChild(e.Item.Item2.Signal) IsNot Nothing Then
atRoot = False
ivrReader.StopStreaming()
selectedNode = selectedNode.getChild(e.Item.Item2.Signal)
selectedTreeNode = selectedNode.treeNode
InvokeGUIThread(Sub()
treeView1.SelectedNode.ForeColor = Color.Black
treeView1.SelectedNode = selectedTreeNode
treeView1.SelectedNode.ForeColor = Color.Red
End Sub)
ivrReader.AddAndStartText(selectedNode.message)
End If
End Sub
Code 7 - Navigating according to the received DTMF signal
The incoming call is automatically accepted (Code 8).
Private Sub softPhone_IncomingCall(ByVal sender As Object, ByVal e As VoIPEventArgs(Of IPhoneCall))
InvokeGUIThread(Sub()
'inComingCall = true;
[call] = e.Item
WireUpCallEvents()
[call].Accept()
End Sub)
End Sub
Code 8 - The IVR softphone automatically answers the incoming calls
The IVR tree information is read up using text to speech conversion (Code 9).
Case CallState.InCall
connector.Connect(ivrReader, mediaSender)
mediaSender.AttachToCall([call])
mediaReceiver.AttachToCall([call])
ivrReader.AddAndStartText(selectedNode.message)
Code 9 - The IVR node data is read up using text to sppech conversion
This article introduced you the basic knowledge about how you can build a simple IVR server in Visual Basic .NET and showed how Ozeki VoIP SIP SDK can help you to fulfill your wishes about this topic. If you have read through this page carefully, you already have all the knowledge you need to start on your own solution.
As you are now familiar with all the terms concerning this topic, now it is time to take a step further and explore what other extraordinary solution Ozeki VoIP SIP SDK can provide to you.
If you have any questions or need assistance, please contact us at info@voip-sip-sdk.com
You can select a suitable Ozeki VoIP SIP SDK license for your project on licensing page
Related Pages
- Setup Ozeki VoIP SIP SDK effectively: Quick start guide
- Download Ozeki VoIP SIP SDK form the Ozeki VoIP SIP SDK download page
- You can find licensing information of Ozeki VoIP SIP SDK on Pricing and licensing information page
INTERMEDIATE
VoIP technology walkthrough
Softphone development
Webphone development
Mobile development
Voice recording
GETTING AROUND
Sitemap
Search the manual
API documentation
FAQ
Appendix


