Contact Info

Crumbtrail » Serial Port Component » Tutorials » Creating outgoing calls

Basics of automating outgoing phone calls using a GSM modem and a computer


Automating outgoing calls is not a simple matter. Dialing the number itself is very easy, but you probably want to know

if the called party responds. There are 2 ways to do this:

Using the query method, you can be sure that your code will work on any mobile, because you can use standardized AT commands (ETSI GSM 07.07)to do this.

The disadvantage of this method is that you have to query for the status multiple times until the receiver picks up the line.

When using the response codes method, you only have to wait for a single string from the modem.

The disadvantage of this method is that these response codes are different between different modem brands.

The command to initiate the phone call is the same for both methods. The AT command for outgoing calls is described below:

Command Description
ATD4412345678 Dial '4412345678'. The connection is setup as a data connection. When the connection is setup, the modem responds with 'CONNECT: XXXXX' where XXXX is the baudrate.
ATD4412345679; Dial '4412345679'. The semi-column indicates that the call has to be setup as a voice call. No modem handshaking is involved. The modems responds with 'OK' directly after the AT command.
ATDL Redial the last called number. If the last dialed number was terminated by a semi-column, the call will be setup as a voice call.
ATDS<n> Dial stored number at location 'n'.

Determining the state of the call

After the call has been initiated, we like to know when the phone is ringing at the other site, and most important, when the receiver picks up the phone.

To query the status of the outgoing call, use the 'AT+CLCC' command. If there are no outgoing calls, the 'AT+CLCC' command will respond with 'OK'.

If there is an outgoing call active the command will respond using the following format:

+CLCC: <id>,<dir>,<stat>,<mode>,<mpty>[,<number>,<type>]

id Call Identification
dir Direction of the call, 0 = outgoing, 1 = incoming call.
stat State of the call. Can be one of the following values:

0 - Active
1 - Held
2 - Dialling
3 - Alerting
4 - Incoming
5 - Waiting
mode Type of call. Possible values are:

0 - Voice
1 - Data
2 - Fax
mpty Indicates if this is a multiparty call or not
number Number to dial
type Type of number

Below you can find examples of some 'AT+CLCC' responses during a call setup:

+CLCC: 1,0,2,0,0,"0742781722",129 Line 1 is dialing a number in voice mode (Dialling)

+CLCC: 1,0,3,0,0,"0742781722",129 The phone is ringing at the remote party (Alerting)

+CLCC: 1,0,0,0,0,"0742781722",129 The remote party picked up the phone (Active)

Sample script

The following scripts demonstrates the AT commands discussed above.

The script asks for the device to use and the phone number to dial.

After dialing the number using the ATD command, the script will query the modem with the AT+CLCC command, and displays the current call state

until the receiver picks up the phone. If an error occur the script will terminate.

To run the following script, you need a GSM modem or phone connected to your phone, and you should have the Serial Port Component installed.

Option Explicit

' Declare variables
Dim objComport
Dim nNumDevices, strDevices, i, strCommand, strResponse, strAddress, str
Dim bConnected

bConnected = False

' Create Comport object
Set objComport = CreateObject ( "ActiveXperts.Comport" )

' Display available devices and serial ports
nNumDevices = objComport.GetDeviceCount()
strDevices  = "*** Enter one of the following device names *** " & vbCrLf & vbCrLf

For i = 0 To nNumDevices-1
    strDevices = strDevices & objComport.GetDevice( i )
    strDevices = strDevices & vbCrLf 

strDevices = strDevices & "COM1" & vbCrLf & "COM2" & vbCrLf & "COM ..." & vbCrLf & "(NOTE: device names are case sensitive!)" & vbCrLf

' Set device
    objComport.Device = inputbox( strDevices, "Input" )
Loop until objComport.Device <> ""

' Set logfile
objComport.LogFile = "c:\CommandLog.txt"    ' Trace log to see what's going on
objComport.ComTimeout = 200

' Open Device
objComport.Open ()

If ( objComport.LastError <> 0 ) Then
	WScript.Echo "Failed to open device, error #" & objComport.LastError & " (" & objComport.GetErrorDescription ( objComport.LastError ) & ")"
End If

' Set Number
    strAddress = inputbox( "Enter the phone number to dial", "Input" )
Loop until strAddress <> ""

' Compose ATD command
strCommand = "ATD" & strAddress & ";"

' Set devicespeed ( optional )
objComport.BaudRate = 9600

' Reset Modem
WriteStr objComport, "ATZ"	
ReadStr  objComport

' Turn off Echo
WriteStr objComport, "ATE0"	
ReadStr  objComport

' Dial Number
WriteStr objComport, strCommand

' Check line status  until the receiving party picks up the phone
Do Until 1 = 0 
    Dim nStatus 
	objComport.WriteString ( "AT+CLCC" )
	strResponse = ""
	strResponse = strResponse + objComport.ReadString		' Read +CLCC Response
	strResponse = strResponse + objComport.ReadString		' Read OK
	' Strip OK
	strResponse = ReplaceEx( strResponse, "OK", "" )
	If ( InStr ( strResponse, "NO CARRIER" ) = 1 ) Then
		WScript.Echo "No Carrier reported while calling remote party"
		Exit Do
	End If
	If ( InStr ( strResponse, "BUSY" ) = 1 ) Then
		WScript.Echo "Busy tone received while calling remote party"
		Exit Do	
	End If
	If ( InStr ( strResponse, "ERROR" ) = 1 ) Then
		WScript.Echo "Error occured while calling remote party"
		Exit Do	
	End If

	If ( InStr ( strResponse, "+CLCC: " ) = 1 ) Then
		nStatus = Split ( strResponse, ",", 5 )	
		Select Case nStatus ( 2 )
			Case 0
				bConnected = True
				Exit Do
			Case 2
				WScript.Echo "Dialing"
			Case 3
				WScript.Echo "Ringing"
		End Select
	End If
	WScript.Sleep ( 500 )

If ( bConnected = True ) Then 
	WScript.Echo "Receiver picked up the phone !!!"
	WScript.Sleep ( 5000 )
End If

' Terminate Call
WriteStr objComport, "ATH0"	
ReadStr  objComport

' ********************************************************************
' Sub Routines
' ********************************************************************

Sub WriteStr( obj, str )
    obj.WriteString str
    WScript.Echo "-> " & str
End Sub

' ********************************************************************

Sub ReadStr( obj )
    str = "notempty"
    obj.Sleep 200
    Do While str <> ""
        str = obj.ReadString
        If( str <> "" ) Then
            WScript.Echo "<- " & str
        End If
End Sub

' ********************************************************************