Monday, January 24, 2011

Fun with RFID


Recently I've been attempting to take advantage of the fancy new hardware packed into the Nexus S. More specifically reading rfid cards using the Nexus's nfc hardware. This turned out to be a bit more tricky than I thought.

Easy part:

Google provides source code for a demo application that will greatly aid you in figuring out the api. The android.nfc btw is stupid simple. In fact you don't have to worry about connections, listeners, any of that stuff. The google nfc service is always on, constantly polling for new card scans. When it detects a card, it issues a nfc intent. You just have to make sure that your applications manifest file, is setup for that intent.

As in: Make sure to have this in your main activity.

<intent-filter>

<action android:name="android.nfc.action.TAG_DISCOVERED"/>

<category android:name="android.intent.category.DEFAULT"/>

intent-filter>

Also make sure you enable nfc permissions and hardware requirement.

<uses-permission android:name="android.permission.NFC" />

<uses-sdk android:minSdkVersion="9">uses-sdk>

<uses-feature android:name="android.hardware.nfc" android:required="true" />


Next in your main activity all you have to do is use the getIntent() to retreive information picked up from a scan. Once again , 'YOU DONT HAVE TO WORRY ABOUT LISTENING FOR SCANS ' which is awesome!


byte[] byte_id = getIntent().getByteArrayExtra(NfcAdapter.EXTRA_ID);


This one above line, retrieves the unique id from the rfid chip, and pushes it into a bytearray.


Tricky Part:


Now that you have your card_id in the array, you cant just push it out to screen. By default android attempt to convert the bytearray to UTF-8, so you would get some weird symbols. In my case I needed the hexadecimal from that to store in a DB. I'm going to list the exact sort of rfid chip I dealt with, in hopes that this will help someone else attempting to do something similar. This is because there is 0 information on the internet that will help you figure this out otherwise. With the exception of a technical specification document that I'll link.



My card type and rfid chip:

High quality CR80 30mil white PVC RFID

cards HF Icode SLI

CR80ICODESLI

Operating frequency 125KHZ


Link to documentation: http://www.nxp.com/acrobat_download2/other/identification/SFS052611.pdf


Your chip type is important, because it will let you know how to read your uid. In the case of my chip, it's a 64 uid, with MSB as the left most.

This is very important in being able to correctly convert your bytearray to binary, hex whatever. There's several code examples of how to convert to hex, but unless you know if you're dealing with little endian, big endian, where your lsb, msb is, it won't work, even though you'll get a hex output.

In my case I used the below function

//Modified from function, I found on internet to suit specific needs.(Not trying to take credit :) )

public String ConvertbyteArrayToHexString(byte in[]) {

byte ch = 0x00;

int i = in.length-1;


if (in == null)

return null;


String HEXSET[] = {"0", "1", "2","3", "4", "5", "6", "7", "8","9", "A", "B", "C", "D", "E","F"};

//Double length, as you're converting an array of 8 bytes, to 16 characters for hexadecimal

StringBuffer out = new StringBuffer(in.length * 2);


//You need to iterate from msb to lsb, in the case of using iCode SLI rfid

while (i >= 0) {

ch = (byte) (in[i] & 0xF0); // Strip off high nibble

ch = (byte) (ch >>> 4); // shift the bits down

ch = (byte) (ch & 0x0F); // must do this is high order bit is on!

out.append(HEXSET[ (int) ch]); // convert the nibble to a String Character

ch = (byte) (in[i] & 0x0F); // Strip off low nibble

out.append(HEXSET[ (int) ch]); // convert the nibble to a String Character

i--;

}

return (new String(out));

}


Using this, I was able to successfully parse though the bits of my 8 bytes, and convert all necessary to hex. I really hope this helps someone, and I'm sure there are many glaring inefficiencies with this code, and any comments left with suggestions to improve it are greatly appreciated.