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.


13 comments:

Chris said...

thanks - this is a huge help. do you know if the Tags app recognizes vcard data? I've been able to encode urls and text to nfc tags but when I try vcard data Tags doesn't seem to know what to do with it.

nellyspageli said...

I see that you used a 125KHz tag. I thought that NFC only supported 13.56MHz. Can you read and write to 125KHz tags?
Does the Nexus S contain a 125KHz tag built-in?
Thanks for the article!

FOG said...

Thanks so much for the blog is brings me a great sigh of relief..

sanpitten said...

Hi, Owens, thanks, ¡your article rocks!, but could you to publish your complete code?

Steve Jabs said...

I've been unable to read 125kHz tags with my Nexus S. Any chance you could open up some of the code that you're using to do that? Are you able to write to 125 as well? Please lemme know. Thanks!

osikes said...

Steve, When you say you're unable to read 125khz do you mean that the phone doesn't register the scan attempt at all? Because it might just be that you havent set your intent filter properly. We used 125khz cards in the program that I wrote my app for.

Mark said...

You're the only one I've found that has had any luck reading a 125KHz card. What's the secret?

mitraidos said...

Kudos for the info mate

Steve Westergaard said...

Owen have you figured out how to perform a simple inventory request from the chip via the transceive method? I'd love to see an example if so.

JWuethrich said...

seconding what others have said about 125khz, none of the programs i've found make any indication they know a card is with in proximity. if i have to code it myself i will but if you could point me in the right direction it would be awesome

eugcc said...

Can't read various types of 125khz RFID cards with nexus s. Could you advice?

Mario K├╝ster said...

Hey Owen,

could you please post your complete Source code and tell me what transponders you used exactly? I thought that NFC only supports 13.56MHz and I need a solution to solve this problem. Otherwise I have to use dual transponders or something like that.


Thank you!

osikes said...

Guys, I'm sorry it turns out the cards I've been using were 13.56MHz. The director of the department that I had been implementing a rfid solution ,had misinformed me about what frequency the cards were at. I apologize for all the questions about 125Khz tags. The world should make more sense now, I wasn't using some super secret code to make them work with 125Khz :p.