Build a bluetooth Chat Application

1

Bluetooth 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

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.

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).

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.

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.

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).

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):

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 “Cab\Debug” 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).

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 Files\Microsoft Visual Studio .NET 2003\CompactFrameworkSDK\v1.0.5000\Windows CE\wce300

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.

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).

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!

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.