RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Fun with RFID : Page 3

You cannot avoid RFID as many large companies will require tags on their products in order to do business with them. Everyday items you purchase may have been tracked with RFID.

Coding the Application
With the UI of the application out of the way, you can now focus on writing the code to wire up all the controls. Switch to the code-behind of Form1 and import the following namespaces.

   Imports System.Data
   Imports System.Data.SqlClient
   Imports System.IO
Declare the member variables and constants shown below:

   Public Class Form1
      '---serial port to listen to 
      ' incoming data---
      Private WithEvents serialPort As New IO.Ports.SerialPort
      '---tag ID read from the reader---
      Private tagID As String = String.Empty
      '---the time that the tag ID was recorded---
      Private timeRecorded As DateTime = Now
      '---COM port to listen to---
      Const COM As String = "COM3"
      '---file name of the log file---
      Const FILE_NAME As String = "C:\Attendance.csv"
      '---the interval before the employee record is cleared 
      ' from the screen (in seconds)---
      Const INTERVAL As Integer = 3
When the form loads, you first clear the displayed employee by setting its filter to a non-existent tag ID. The Timer control clears the displayed employee after a certain amount of time, and in this case you will set it to three seconds (as defined by the Interval constant). That is to say, when an employee is identified using his RFID tag, his information will be cleared from the screen after three seconds.

As the Parallax's RFID Reader Module uses a serial connection, you will use the SerialPort class to communicate with the reader.

Author's Note: For this example, I have assumed that you'll connect the COM3 port to the RFID Reader Module. You need to change it to the correct port number for your own use.

Here's the code for the Form1_Load event.

   Private Sub Form1_Load(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles MyBase.Load
      'TODO: This line of code loads data into the NorthwindDataSet.
      ' Employees' table. You can move, or remove it, as needed.
      '---Clear the employee when the app is loaded 
      EmployeesBindingSource.Filter = "TAGID='xxxxxxxxxx'"
      '---set the timer interval to clear the employee record 
      ' convert to milliseconds
      Timer1.Interval = INTERVAL * 1000
      '---open the serial port connecting to the reader 
      If serialPort.IsOpen Then
      End If
         With serialPort
            .PortName = COM
            .BaudRate = 2400
            .Parity = IO.Ports.Parity.None
            .DataBits = 8
            .StopBits = IO.Ports.StopBits.One
            .Handshake = IO.Ports.Handshake.None
         End With
      Catch ex As Exception
      End Try
   End Sub
To receive incoming data from the SerialPort class, you need to service the DataReceived event. In this case, when incoming data is received, you will update the txtTagID control. Here's the code for the DataReceived event.

   Private Sub DataReceived(ByVal sender As Object, _
      ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) _
      Handles serialPort.DataReceived
      '---when incoming data is received, update the TagID 
      ' textbox 
      txtTagID.BeginInvoke(New myDelegate( _
         AddressOf updateTextBox), New Object() {})
   End Sub
You need to define a delegate to call a routine to update the txtTagID control. Here, define the myDelegate() delegate and the updateTextBox() subroutine.

   '--- update the Tag ID textbox
   Public Delegate Sub myDelegate()
   Public Sub updateTextBox()
      ' for receiving plain ASCII text
      With txtTagID
      End With
   End Sub
One important point you need to understand about RFID readers (at least for the two RFID readers shown in this article) is that while it's scanning a tag, it will continuously send the tag ID to the serial connection. For example, suppose a tag with ID of 0F0296AF3C is placed near the reader. In this case, the reader will continuously send the value of 0F0296AF3C to the serial connection. For the Parallax's reader, each value starts with the line feed character (character 10) and ends with a carriage return character (character 13). To make matters complicated, using the ReadExisting() method of the SerialPort class does not guarantee that you will read the tag ID in its entirety. This is because a value may be sent in four blocks, like this:

You may be tempted to use the ReadLine() method of the SerialPort class to read incoming data, but that will not work, because the ReadLine() method looks for <13><10> at the end of the line. But because the incoming data does not end with <10>, this will cause the application to go into an infinite loop.

In addition, if you don't clear the incoming data buffer fast enough, you may get a series of data queued up like this:

Instead of writing elaborate logic to process the incoming data, an easy way is to append all incoming data to a TextBox control (with the Multiline property set to True). Using the data just described, Figure 13 shows what the TextBox control will look like.

Figure 13: Appending incoming data to a TextBox control.
Figure 14: The state of the TextBox control containing the last incomplete tag ID.
The second to the last line will hence always contain the tag ID that you are interested in if the last line is an empty string. In contrast, if the tag ID is only partially received, the state of the TextBox control would be as shown in Figure 14.

As all incoming data is updated in the TextBox control, you can check if the tag ID belongs to an employee whenever there are changes in the content of the TextBox control. You'll use the TextChanged event (Listing 1) to detect the change.

The TextChanged event first examines if the last line in the txtTagID control is an empty string; if it is, then the scanned tag ID can be found in the second to last line. Using this tag ID, the code checks the time difference between the current time and the last time the tag ID was read. If it is less than three seconds and the tag ID is the same as the last read tag ID, it means that it is reading the same user, so the current tag ID should be ignored. Using this implementation, all users will be ignored for three seconds following an initial tag scan.

Using the tag ID, apply a filter to the EmployeesBindingSource control to look for an employee with a matching tag ID. If an employee is found, an entry will be written to the log file using the WriteToLog() subroutine.

Figure 15: The content of a typical log file.
   Private Sub WriteToLog( _
      ByVal employeeID As String, _
      ByVal employeeName As String)
      '--- write to log file 
      Dim str As String = employeeID & _
         "," & employeeName & ", " & _
         Now & Chr(13)
      My.Computer.FileSystem. _
         WriteAllText(FILE_NAME, str, True)
   End Sub
Figure 15 shows the content of a typical log file.

The Timer control will fire the Tick event every three seconds (as determined by the value set in its Interval property). Hence you need to service the Tick event so that every time it fires, you can clear the current employee information that is displayed. Here is the implementation of the Tick event.

   Private Sub Timer1_Tick(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles Timer1.Tick
      '--- clear the employee 
      EmployeesBindingSource.Filter = "TAGID='xxxxxxxxxx'"
      Timer1.Enabled = False
   End Sub
If the tag ID just scanned in does not belong to any user, the administrator can assign the tag ID to an employee. To do so, he can first click the Find button to find the user and then assign the tag ID to that user. Here is the implementation of the Find button.

   Private Sub btnFind_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles btnFind.Click
      '--- search for employee 
      If txtEmployeeID.Text = String.Empty Then
          EmployeesBindingSource.Filter = _
             "EmployeeID='" & txtEmployeeID.Text & "'"
      End If
   End Sub
Basically, you search for a user by applying a filter to the EmployeesBindingSource control. To assign a tag ID to the current employee, copy the tag ID onto the TagIDLabel1 control and then save the changes. Listing 2 shows the implementation of the "Assign Tag to Employee" button.

The "Deassign Tag From Employee" button allows a tag ID to be disassociated from an employee. This is easily accomplished by setting the TagIDLabel1 control to an empty string. Here's the implementation of the "Deassign Tag From Employee" button.

   Private Sub btnDeassign_Click( _
      ByVal sender As System.Object, _
      ByVal e As System.EventArgs) _
      Handles btnDeassign.Click
      If Trim(TagIDLabel1.Text) = String.Empty Then
         ToolStripStatusLabel1.Text = _
            "Current employee has no tag ID."
         Exit Sub
      End If
      '---deassociate tag ID from employee 
      TagIDLabel1.Text = String.Empty
      '---save the record 
      Me.EmployeesTableAdapter.Update( _
      ToolStripStatusLabel1.Text = _
         "Tag deassociated from employee."
   End Sub

Close Icon
Thanks for your registration, follow us on our social networks to keep up-to-date