Roll Your Own SMS Gateway

n the last few years, SMS (Short Message Service) has made a big impact on the way we communicate (or at least the youngsters). Instead of communicating over the phone using voice, more and more people are turning to using SMS for messaging. One of the popular uses of SMS is for voting. For example, you can vote for your favorite contestant on the television program “American Idol” by simply sending an SMS message to a particular phone number. This is then automatically tabulated into a final vote count for each participant. Traditionally, to implement such a system, you needed to buy an expensive SMS gateway, which is overkill for a small project with limited budget.

In this article, I will show you how you can use a Windows Mobile 5.0 Pocket PC device as an SMS gateway for voting purposes. Figure 1 shows the architecture of the example system you will build.

The following steps show the communication protocol between the Pocket PC application and the server application:

  1. The user (phone number +123456789) sends an SMS message to the Pocket PC, e.g. “VOTE A 987-65-4329.” The message format is: VOTE .
  2. The Pocket PC receives the message from the user and forwards it to the server application along with the phone number. The server receives the SMS message and tallies the vote count. The communication between the Pocket PC and the server is conducted over a Bluetooth connection.
  3. The server sends a command “SEND:+123456789:Thank you for your vote!” to the Pocket PC application.
  4. The Pocket PC receives the command from server and sends an SMS message “Thank you for your vote!” to the phone number +123456789.

In this system, there are altogether two components:

  • A Pocket PC application that sends and receives SMS messages
  • A Windows application that communicates with the Pocket PC application and keeps track of the number of votes.

What You Need
To build the SMS Gateway system described in this article, you need the following:

  • A Windows Mobile 5.0 Pocket PC Phone Edition device (with Bluetooth capability). You would also need to have a valid SIM card that allows you to send and receive SMS messages.
  • A Bluetooth USB adapter to connect to your PC.

Developing the Pocket PC Application
Let’s start by first developing the Pocket PC application. In Visual Studio 2005, create a new Windows Mobile 5.0 Pocket PC application and name it SMS. Populate the default Form1 with the controls shown in Figure 2.


Figure 1. The architecture of the SMS gateway system is shown.
 
Figure 2. Populate Form1 with the various controls as shown.

For the TextBox1 and TextBox2 controls, set their properties as follows:

  • Multiline?True
  • ScrollBars?Both

Add the following references to the project:

  • Microsoft.WindowsMobile
  • Microsoft.WindowsMobile.PocketOutlook

Switch to the code-behind of Form1 and import the following required namespaces:

Imports Microsoft.WindowsMobile.PocketOutlookImports Microsoft.WindowsMobile.PocketOutlook.MessageInterception

Declare the following constants and variables:

Public Class Form1    '---the constants for the commands---    Const VOTE_COMMAND As String = "VOTE"    Const SEND_COMMAND As String = "SEND"    Private msgInterceptor As MessageInterceptor    Private WithEvents serialPort As New IO.Ports.SerialPort

The first constant, VOTE_COMMAND, is used to filter out SMS messages sent by the user. For example, if the user wants to vote for participant A, then his SMS message will be sent in the following format:

VOTE  

An example would be “VOTE A 987-65-4329.” All incoming SMS messages beginning with the word VOTE would be filtered and processed by this application.

The second constant is used to filter the command sent by the server. When the server receives a SMS vote, it will send a command to the Pocket PC application so that it can send an acknowledgment SMS message back to the user. For example, the server might send the following command to the Pocket PC application: “SEND:+123456789:Thank you for your vote!.” The Pocket PC will then send an SMS message to the user.

The msgInterceptor object is used for intercepting incoming SMS messages. The serialPort object is used for communicating with the server over a Bluetooth connection.

In the Form1_Load event, create an instance of the MessageInterceptor class and set its filter to intercept for incoming SMS messages that start with the word “VOTE” (regardless of casing). Then, set an event handler to service this event (when a message is intercepted). At the same time, you will also open a serial connection (over Bluetooth) to connect with the server:

    Private Sub Form1_Load( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles MyBase.Load        '---create an instance of the MessageInterceptor class---        msgInterceptor = New MessageInterceptor( _           InterceptionAction.NotifyAndDelete, True)        '---set the filter for the message---        msgInterceptor.MessageCondition = _           New MessageCondition( _           MessageProperty.Body, _           MessagePropertyComparisonType.StartsWith, _           VOTE_COMMAND, False)        '---set the event handler for the message interceptor        AddHandler msgInterceptor.MessageReceived, _           AddressOf SMSInterceptor_MessageReceived        '---close the serial port if open---        If serialPort.IsOpen Then            serialPort.Close()        End If        '---open the serial port to connect to server---        Try            With serialPort                .PortName = "COM6"                .BaudRate = 9600                .Parity = IO.Ports.Parity.None                .DataBits = 8                .StopBits = IO.Ports.StopBits.One                .Handshake = IO.Ports.Handshake.None            End With            serialPort.Open()        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub
Author’s Note: I am assuming that COM6 is used by the Bluetooth serial port on the Pocket PC. Change this COM port according to the port number used on your Pocket PC.

When an SMS message is intercepted, the SMSInterceptor_MessageReceived event handler will be fired:

    '---event handler for the MessageReceived event---    Private Sub SMSInterceptor_MessageReceived( _       ByVal sender As Object, _       ByVal e As MessageInterceptorEventArgs)        '---extract the message received---        Dim msg As SmsMessage = e.Message        '---format as "+123456789,VOTE A 987-65-4329"---        Dim s As String = msg.From.Name & "," & msg.Body        '---update the textbox with the above data---        TextBox1.BeginInvoke(New _           myDelegate(AddressOf updateTextBox1), _           New Object() {s})    End Sub

Here, you will extract the sender’s phone number as well as the content of the SMS message. You need to cast the e.Message object into a SmsMessage object in order to retrieve the detailed information of the sender. The received data is then displayed in the TextBox1 control.

Author’s Note: Interestingly, if the sender’s phone number has already been saved in Contacts, the From.Name property will return the sender’s name (as saved in Contacts) instead of his phone number. In this case, you need to do some additional work to find out the sender’s phone number.

The delegate and the subroutine to update the TextBox control are defined as follows:

    '---delegate for updating the two TextBox controls---Public Delegate Sub myDelegate(ByVal str As String)    '---display received SMS data---    Public Sub updateTextBox1(ByVal str As String)        '---show the received data in the TextBox---        TextBox1.Text = str & vbCrLf & TextBox1.Text        '---Send the data to the server---        SendDatatoServer(str)    End Sub

Figure 3 shows the application when SMS messages are received.


Figure 3. SMS messages have been received by the application.
 
Figure 4. Messages from users and from the server are shown.

When the SMS message is shown on the TextBox control, it is also sent to the server, through the SendDatatoServer() subroutine:

    '---sends the received SMS data to the server---    Private Sub SendDatatoServer(ByVal str As String)        Try            '---write to the serial port---            serialPort.Write(str & vbCrLf)        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub

When the server receives the SMS message sent by the Pocket PC application, it will also send a command to the Pocket PC, asking it to send an acknowledgement message back to the sender. In this case, the command will be received on the Pocket PC via the serial port connection. Essentially, you will service the DataReceived event of the serialPort object:

    '---data received by the serial port (from server)---    Private Sub DataReceived( _           ByVal sender As Object, _           ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _           Handles serialPort.DataReceived        Dim data As String = serialPort.ReadLine()        '---update the textbox with the data from server---        TextBox2.BeginInvoke(New _           myDelegate(AddressOf updateTextBox2), _           New Object() {data})    End Sub

The received command is displayed in the TextBox2 control:

    '---update the TextBox with the data received from server---    Public Sub updateTextBox2(ByVal str As String)        '---show the received data in the TextBox---        TextBox2.Text = str & vbCrLf & TextBox2.Text        If str.StartsWith(SEND_COMMAND) Then            Dim fields() As String = str.Split(":")            '---.e.g. SEND:+123456789:Thank you for your vote!            '---fields(0) is SEND, fields(1) is +123456789,             '---fields(2) is "Thank you for your vote!"            '---send SMS to user---            SendSMS(fields(1), fields(2))        End If    End Sub

The Pocket PC application then sends an acknowledgement SMS message back to the sender using the SmsMessage class:

    '---send a SMS message to a recipient---    Private Sub SendSMS( _       ByVal receiptnumber As String, _       ByVal message As String)        '---from the Microsoft.WindowsMobile.PocketOutlook namespace---        '---compose a new SMS message---        Dim SMS As New SmsMessage        '---set the body of the message---        SMS.Body = message        '---add the recipient---        SMS.To.Add(New Recipient(receiptnumber))        '---send the message---        SMS.Send()    End Sub

Figure 4 shows messages received from users as well as commands sent by the server (more on this in the next section).

Developing the Server
Now that we have developed the Pocket PC application, let’s turn our attention to the server application. Using Visual Studio 2005, create a new Windows application and name it SMS_Desktop. Populate the default Form1 with the controls shown in Figure 5.

For the TextBox control, set the ScrollBars property to Vertical and the Multiline property to True.

The four ProgressBar controls are used to show the number of votes for each choice (participant)?A, B, C, or D.

For simplicity’s sake, you will use the Application Settings feature of Windows Forms 2.0 to store the vote count for each choice (in real-life you would use a database). Right-click on the project name in Solution Explorer and select Properties. Select the Settings tab and add the four application settings as shown in Figure 6.


Figure 5. Populate Form1 with the various controls as shown.
 
Figure 6. Add four application settings to the project.

In the code-behind of Form1, declare the following constants and variable:

Public Class Form1    '---the constants for the commands---    Const VOTE_COMMAND As String = "VOTE"    Const SEND_COMMAND As String = "SEND"    Private WithEvents serialPort As New IO.Ports.SerialPort

In the Form1_Load event, you will first call the UpdateBars() subroutine to initialize the progress bars with the current vote count for each choice (I will define this shortly). You will also open the serial connection with the Pocket PC over a Bluetooth connection:

    Private Sub Form1_Load( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles MyBase.Load        '---update the progressbars---        UpdateBars()        '---close the serial port if open---        If serialPort.IsOpen Then            serialPort.Close()        End If        '---open the serial port to connect to server---        Try            With serialPort                .PortName = "COM12"                .BaudRate = 9600                .Parity = IO.Ports.Parity.None                .DataBits = 8                .StopBits = IO.Ports.StopBits.One                .Handshake = IO.Ports.Handshake.None            End With            serialPort.Open()        Catch ex As Exception            MsgBox(ex.ToString)        End Try    End Sub
Author’s Note: I am assuming that COM12 is used by the Bluetooth serial port on the computer. Change this COM port according to the port number used on your computer.

Handle the DataReceived event when incoming data is received at the serial port:

    '---data received from Pocket PC---    Private Sub DataReceived( _       ByVal sender As Object, _       ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _       Handles serialPort.DataReceived        '---update it in the textbox---        TextBox1.BeginInvoke(New _           myDelegate(AddressOf updateTextBox), _           New Object() {})    End Sub

In this case, you simply display the received data in the TextBox1 control.

In the updateTextBox() control, incoming data is first read and then added to the TextBox1 control. You then write the data to a log file using the WriteToLog() subroutine. Finally, you will tabulate the vote count using the ProcessData() subroutine:

    '---delegate for updating the TextBox control---    Public Delegate Sub myDelegate()    '---display data received from Pocket PC---    Public Sub updateTextBox()        '---for receiving plan ASCII text---        Dim data As String = serialPort.ReadLine        '---e.g. "+123456789,VOTE A 987-65-4329"---        '---append it to the TextBox control---        With TextBox1            .AppendText(data & vbCrLf)            .ScrollToCaret()        End With        '---write to log file---        WriteToLog(data)        '---process the received data---        ProcessData(data)    End Sub

In the WriteToLog() subroutine, you simply write the received data to a text file for archival purpose:

    Private Sub WriteToLog(ByVal str As String)        My.Computer.FileSystem.WriteAllText("C:SMSVotes.txt", _           str, True)    End Sub

The ProcessData() subroutine splits the received data so as to extract the choice voted by the sender. It then updates the application setting for each choice:

    '---tabulate the scores---    Private Sub ProcessData(ByVal str As String)        Dim fields() As String = str.Split(",")        '---fields(0) is caller number---        '---fields(1) contains the data, e.g. VOTE A 987-65-4329        Dim subFields() As String = fields(1).Split(" ")        '---subfields(0) is Vote, subfields(1) is choice---        With My.Settings            Select Case UCase(subFields(1))                Case "A"                    .ChoiceA += 1                Case "B"                    .ChoiceB += 1                Case "C"                    .ChoiceC += 1                Case "D"                    .ChoiceD += 1            End Select            .Save()        End With        '---send a reply to the user---        SendReply(fields(0), "Thank you for your vote!")        '---update the progress bars---        UpdateBars()    End Sub

Upon tabulating the vote, you can also send a reply back to the sender. This is accomplished by the SendReply() subroutine. Here, you simply write a SEND command to the Pocket PC via the serial port:

    '---send message to the Pocket PC to ask it     ' to send a SMS to the user---    Private Sub SendReply( _       ByVal recipientNumber As String, _       ByVal message As String)        '---.e.g. "SEND:+123456789:Thank you for your vote!"---        serialPort.Write( _           SEND_COMMAND & ":" & recipientNumber & _           ":" & message & vbCrLf)    End Sub

The UpdateBars() subroutine updates the value of the four ProgressBar controls:

    '---update the progressbars---    Private Sub UpdateBars()        With My.Settings            Label1.Text = "Choice A (" & .ChoiceA & " vote(s) )"            ProgressBar1.Value = .ChoiceA            Label2.Text = "Choice B (" & .ChoiceB & " vote(s) )"            ProgressBar2.Value = .ChoiceB            Label3.Text = "Choice C (" & .ChoiceC & " vote(s) )"            ProgressBar3.Value = .ChoiceC            Label4.Text = "Choice D (" & .ChoiceD & " vote(s) )"            ProgressBar4.Value = .ChoiceD        End With    End Sub

Finally, the Reset button resets the vote count for each choice:

    '---reset all the scores---    Private Sub btnReset_Click( _       ByVal sender As System.Object, _       ByVal e As System.EventArgs) _       Handles btnReset.Click        With My.Settings            .ChoiceA = 0            .ChoiceB = 0            .ChoiceC = 0            .ChoiceD = 0            .Save()        End With        UpdateBars()    End Sub

Figure 7 shows data received from the Pocket PC and the various vote counts.

Figure 7. The screen shot shows messages received by the server and the vote counts.

Testing the System
To test the system:

  • Pair up your Pocket PC with your computer using Bluetooth.
  • Establish a serial connection between the Pocket PC and computer. This article assumes that your Pocket PC will use COM6 and your computer will use COM12. Remember to change it based on your own COM port number.
  • Deploy the Pocket PC application onto your Windows Mobile 5.0 Pocket PC and launch it.
  • Ensure that the Pocket PC application is running before you launch the Windows application on the server computer.
  • Use another mobile phone and send an SMS message to the Pocket PC. After a while, you should be able to see the Pocket PC showing the received message. At the same time, the message would also be received by the application running on the server.
  • Upon showing the updated vote, you should be able to receive an acknowledgement message from the Pocket PC.

In this article, you have seen how to build a simple SMS gateway for tabulating vote count. With some creativity and exploration, you can build more interesting applications using the SMS gateway. If you have a good idea for using the SMS gateway, send it my way at the email address in my bio at the bottom of this page.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: