Basics of automating outgoing phone calls using a GSM modem and a computer
Dialing
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:
- Querying the status of the call
- Waiting for unsolicited response codes
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 Next strDevices = strDevices & "COM1" & vbCrLf & "COM2" & vbCrLf & "COM ..." & vbCrLf & "(NOTE: device names are case sensitive!)" & vbCrLf ' Set device Do 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 ) & ")" WScript.Quit End If ' Set Number Do 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 ) Loop 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 Loop End Sub ' ********************************************************************