devxlogo

Make Bluetooth Work for You: Build a Sample Chat Application

Make Bluetooth Work for You: Build a Sample Chat Application

luetooth is one of today’s most exciting technologies. It is a short-range radio wave wireless technology operating in the 2.4 GHz frequency spectrum. With an operating range of 30 feet (10 meters) and a maximum transmission rate of a mere 1Mbps, Bluetooth is widely touted as the “cable replacement” solution.

Bluetooth has been around for awhile but there seem to be few developers who have experience in building applications that will run over Bluetooth. In this article, I will show how you can build a Bluetooth chat application using the .NET Compact Framework. Once you’ve built a chat application using this simple example, you should have a good foundation for building any number of killer Bluetooth applications.

The chat application enables two users with Bluetooth-enabled Pocket PCs to communicate with each other so long as they are within the 30-foot range of Bluetooth. It is useful as a communication tool during meetings, where private conversations can take place without affecting the meeting or as a mobile substitute for instant messenger.

What You Need
  • Visual Studio .NET 2003 Final Beta (available now to MSDN subscribers)
  • Two Pocket PCs with Bluetooth capabilities. (Most new Pocket PCs today ship with Bluetooth capability. For Pocket PCs without built-in Bluetooth, you can purchase Bluetooth expansion jackets/cards from the respective vendors.)
  • Microsoft ActiveSync 3.6
  /assets/articlefigs/5256.png
Figure 1: Two Pocket PCs. To build and test the chat application I used two Pocket PC devices from Compaq: an iPaq 3870 (with Bluetooth built-in) and an iPaq 3630 (with the Bluetooth Expansion Pack for the iPaq 3630).

The Pocket PCs I used in preparing this article are shown in Figure 1.

Building the User Interface>
To create the sample application, start Visual Studio .NET 2003 and create a new Smart Device Application Project.

  /assets/articlefigs/5257.png
Figure 2: Build Form1 for the Main UI. Form1 is populated with three controls?a TextBox, a Button, and a MainMenu.

Let’s first populate the default Form1 with the following controls:

  • TextBox (for entering the text of a chat message)
  • Button (for sending the text)
  • MainMenu

The populated Form1 is shown in Figure 2.

Communicating using Bluetooth
Windows CE 3.0?the operating system for Pocket PC devices?does not come with any API for Bluetooth communication. As such, you have to use other methods, such as platform invoke, to communicate using Bluetooth. The lack of an API for Bluetooth means that you are not able to program Bluetooth communications in the same way you use sockets for TCP/IP communications. Instead, Bluetooth is just another serial port. And so, Bluetooth communication is actually done via serial connections. You can see for yourself by going to Bluetooth Manager?>Tools?>Settings for All Devices?>Serial Port in your Pocket PC’s main menu (see Figure 3).

  /assets/articlefigs/5258.png
Figure 3: Serial Connections. The Bluetooth connection is just another pair of serial ports, in this case ports 7 and 8.

The Bluetooth connection is actually mapped to two COM ports?one for incoming and one for outgoing traffic. On my test device the incoming port is COM7 and the outgoing port is COM8 (see Figure 3). We will program the Bluetooth application using serial communication techniques.

Unfortunately, the .NET Compact Framework class library does not contain managed classes for serial communication. You have to rely on the operating system calls to provide that. In particular, we need to make use of functions provided by Windows CE 3.0’s “coredll.dll” library.

In the .NET CF, use the attribute to import the library that you want to use. In our case, I have imported four functions from the coredll.dll library. They are:

  • CreateFile()?Opens a connection to a COM port.
  • ReadFile()?Reads data from a COM port.
  • WriteFile()?Writes data to a COM port.
  • CloseHandle()?Closes a COM port.
Author’s Note: Many of the details involved in serial communications are beyond the scope of this article. For more information on building serial-comm applications in Windows CE, refer to http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wceseril/htm/cmconProgrammingSerialConnections.asp. The example in this article does not contain all the error-handling mechanisms required for serial communications.

The VB.NET code for the import is shown in Listing 1.

Now that you have the functions that you’ll need, you can begin building the applications. Start by declaring some global variables:

    Dim infileHandler As Long    Dim outfileHandler As Long    Dim numReadWrite As Integer    Dim t1 As System.Threading.Thread    Dim stopThread As Boolean = False

We need to create a Connect menu item that, when tapped, will call the connect() method to open the serial connections. We need to open the connections to the inbound and outbound port so that data can be both received and sent. The code below handles the Connect menu selection:

    Private Sub MenuItem2_Click(ByVal sender As System.Object, _                          ByVal e As System.EventArgs) _                          Handles MenuItem2.Click        connect()        MenuItem2.Enabled = False '---disable the Connect item        MenuItem3.Enabled = True '---enable the Disconnect item    End Sub

The method we are using for reading incoming messages, ReadFile() is a blocking one. Therefore, we need to invoke a thread to continuously poll for incoming data while allowing our application to be responsive to users’ input at the same time.

    Public Sub connect()        '---port number for Bluetooth connection        Dim inPort As Short = 7        Dim outPort As Short = 8        '---Opens the port for Bluetooth        infileHandler = CreateFile("COM" & inPort & ":", _                                    &HC0000000, 0, 0, 3, 0, 0)        Application.DoEvents()        outfileHandler = CreateFile("COM" & outPort & ":", _                                    &HC0000000, 0, 0, 3, 0, 0)        Application.DoEvents()        '---invoke the thread to receive incoming messages        stopThread = False        t1 = New Threading.Thread(AddressOf receiveLoop)        t1.Start()    End Sub

The send() method writes a message to the COM port using the WriteFile() method. After a message is sent, a copy of the message is added to the TextBox control:

    Public Function send(ByVal message As String) As Integer        '---send the message through the serial port        Dim value As String = message & vbCrLf        Dim retCode As Integer = WriteFile(outfileHandler, _                                           stringToByteArray(value), _                                           value.Length(), _                                           numReadWrite, _                                           0)        txtMessageLog.Text += value        Return retCode    End Function

The receiveLoop() method continuously polls for incoming messages. As Windows controls are not thread-safe, accessing Windows controls within a thread will have unpredictable results. As such, you need to use a delegate method to call the updateMessage() method to update the TextBox control with the received message.

    Public Sub receiveLoop()        '---receive the message through the serial port        Dim inbuff(300) As Byte        Dim retCode As Integer = ReadFile(infileHandler, _                                          inbuff, _                                          inbuff.Length, _                                          numReadWrite, _                                          0)        Application.DoEvents()        While True            If retCode = 0 Or stopThread Then                '---either error or stop is requested                Exit While            Else                Dim updateDelegate As New _                    myDelegate(AddressOf updateMessageLog)                updateDelegate.Invoke(byteArrayToString(inbuff))                ReDim inbuff(300)                retCode = ReadFile(infileHandler, _                                   inbuff, _                                   inbuff.Length, _                                   numReadWrite, _                                   0)                Application.DoEvents()            End If        End While    End Sub

The myDelegate() method has the same signature as the updateMessageLog() method. myDelegate() is called when updating the TextBox control. You should not directly call the updateMessageLog() within the thread; only the main thread can directly call it.

    Public Delegate Sub myDelegate(ByVal str As String)    Public Sub updateMessageLog(ByVal str As String)        If str.Length > 0 Then            txtMessageLog.Text += "-->" & str        End If    End Sub

Clicking the Send button invokes the send() method:

    Private Sub Button1_Click(ByVal sender As System.Object, _                              ByVal e As System.EventArgs) _                              Handles Button1.Click        If send(txtMessage.Text) = 0 Then            MsgBox("Error sending message.")        End If    End Sub

Finally, clicking on the Disconnect menu item invokes the disconnect() method:

    Private Sub MenuItem3_Click(ByVal sender As System.Object, _                                ByVal e As System.EventArgs) _                                Handles MenuItem3.Click        disconnect()        MenuItem2.Enabled = True '---enable the Connect button        MenuItem3.Enabled = False '---disable the Connect button    End Sub

The disconnect() method will set a global flag for the thread to stop receiving incoming messages. It will also close the two open ports:

    Public Sub disconnect()        stopThread = True        CloseHandle(infileHandler)        CloseHandle(outfileHandler)    End Sub

Byte to String and Back Again
Throughout this application, we have used two supporting methods: stringToByteArray() and byteArrayToString(). These two methods are necessary as the ReadFile() and WriteFile() methods both take in a byte array containing the message to be read and sent, respectively.

The stringToByteArray() method converts a string into a byte array:

    Public Function stringToByteArray(ByVal str As String) As Byte()        '---e.g. "abcdefg" to {a,b,c,d,e,f,g}        Dim s As Char()        s = str.ToCharArray        Dim b(s.Length - 1) As Byte        Dim i As Integer        For i = 0 To s.Length - 1            b(i) = Convert.ToByte(s(i))        Next        Return b    End Function

The byteArrayToString() method converts a byte array into a string:

    Function byteArrayToString(ByVal b() As Byte) As String        '---e.g. {a,b,c,d,e,f,g} to "abcdefg"         Dim str As String        Dim enc As System.Text.ASCIIEncoding        enc = New System.Text.ASCIIEncoding        str = enc.GetString(b, 0, b.Length())        Return str    End Function

When sending a message, the message to be sent would need to be converted to a byte array, and vice versa, when a message is received as a byte array, it needs to be converted back to a string so that it can be displayed on the device.

  /assets/articlefigs/5259.png
Figure 4: Make a Connection. Use the Bluetooth Manger on the Pocket PC device connected to your development machine to make it recognize another Bluetooth device.

Testing the Application
To test the application, you need to install the sample application on both Pocket PCs. The easiest way to do this is to connect one of the Pocket PCs to your development machine and use Visual Studio .NET 2003 to deploy the application on the device. Then press F5 to automatically copy the application onto the device.

The next step is to copy the application onto the other Pocket PC. There are two steps involved here. First, you need to generate a CAB file for the application so that it can be copied and installed on the target Pocket PC. Second, you need to install the .NET Compact Framework on it (this only needs to be done once).

  /assets/articlefigs/5260.png
Figure 5: Generate a CAB. This button generates a CAB file for your application.

But before you can do either task, you need to establish a Bluetooth connection between the two Pocket PCs using the Bluetooth Manager to create a bond between them (see Figure 4.

Now that the two devices recognize each other, you can go about sending the CAB file and the framework to the remote device. To generate a CAB file for your application, click on the “Build Cab File” button in Visual Studio .NET 2003 (see Figure 5):

  /assets/articlefigs/5261.png
Figure 6: Pick a CAB. Visual Studio.NET will automatically generate CAB files for all platforms supported by the Compact Framework.

When the CAB file is generated, you can locate it in the “CabDebug” folder of your application. Visual Studio .NET 2003 will generate the CAB files for the various platforms that are supported by the .NET Compact Framework (see Figure 6. Make sure to identify the right one for your platform.

To copy the CAB file to your Pocket PC, connect your Pocket PC to your machine and use Microsoft ActiveSync’s Explore option. Drag and drop the CAB file onto the desired directory (see Figure 7).

  /assets/articlefigs/5262.png
Figure 7: Use ActiveSynch. Copy the CAB file to your device using ActiveSync.

Once the CAB file is copied to the device, you can use Bluetooth to send the CAB file to the other Pocket PC, as shown in Figure 8.

The next step is to copy the .NET Compact Framework to the Pocket PC. You can find the CAB file for the .NET Compact Framework in the following directory on your development machine (with Visual Studio .NET 2003 installed):
C:Program FilesMicrosoft Visual Studio .NET 2003CompactFrameworkSDKv1.0.5000Windows CEwce300

  /assets/articlefigs/5263.png
Figure 8: Send the CAB Across. Use the Bluetooth Manager again to transfer the CAB file from one device to the other.

Choose the appropriate platform for your Pocket PC (see Figure 9). For example, my second Pocket PC is an iPaq 3630, so I chose the “arm” platform as it runs on an ARM processor. (To find out the type of processor your Pocket PC is running on, go to Start?>Settings and tap on the System tab, and click on the About icon. Under the “Processor” category, you should see the processor type. Both my Pocket PCs runs on the ARM SA1110 processor.)

Copy the “netcf.core.ppc3.arm” file (or the appropriate one for your device) to the Pocket PC via ActiveSync. Again, use Bluetooth to send the file from one device to the other.

  /assets/articlefigs/5265.png
Figure 10: Install on the Second Device. Install the .NET CF and the sample application.

On the other Pocket PC, you can now install the .NET Compact Framework and the application by tapping on the two CAB files (see Figure 10). The order of installation is important?install the .NET CF first.

Once the application is installed, you should find a BluetoothChat application icon in the Programs folder (see Figure 11).

  /assets/articlefigs/5266.png
Figure 11: Launch the App. Locate the icon for the chat application in the Programs folder.

Before you load the application, make sure that you have a Bluetooth bond between the two Pocket PCs. Tap on the Settings?>Connect menu item to establish a serial connection. The other Pocket PC will receive an authorization request for the use of the serial port. Click on Accept to start chatting!

  /assets/articlefigs/5267.gif
Figure 12: Chat Away. The two screens show the dialog between the two Pocket PCs using the sample chat application in this article.

In this article, you have seen how to you can program Bluetooth applications using serial communication programming. The initial release of the .NET Compact Framework is not expected to contain classes for Bluetooth communications. However, expect to see Bluetooth managed classes and APIs appearing in Windows CE .NET and the next release of the .NET Compact Framework.

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist