Ruby and RFID tags

Posted by – September 19, 2009

It’s been forever since I’ve written a blog entry, so LETS DO THIS. I want to talk about reading RFID tags with Ruby. I am a nerd, so even though I can’t think of a good application, I am compelled to be able to read RFID tags. I love programming Ruby, so of course, I have to do this with Ruby.

Getting an RFID Reader

First thing to do, is buy an RFID reader. After searching around, I found the touchatag reader. I bought the touchatag starter pack. It’s only $40, USB, and comes with 10 RFID tags. Most importantly, it works well with libnfc (more about that later).

IMG_0315

The tags that come with the reader have an adhesive back, so you can stick them to stuff. They also have the unique identifier printed on them so that you can make sure your program output is correct.

IMG_0317IMG_0318

Interfacing with the reader

Now that we’ve got the reader, let’s do something with it! I mentioned earlier that the touchatag reader works with libnfc. Libnfc is a C library that knows how to work with NFC devices (nerd talk for “RFID readers”). I’ve written a gem called nfc that wraps up the C library in to something we can use in Ruby.

First thing we need to do is install libnfc. I use macports with OS X. With macports, installing libnfc is quite easy:

    $ sudo port install libnfc

Installing on linux should be just as easy, but you’ll need to consult your package manager. Make sure to install the devel packages too!

After that, simply install the nfc Ruby gem:

    $ sudo gem install nfc

Now that that is out of the way, we can actually read an RFID tag. Here is our code:

require 'rubygems'
require 'nfc'
# Find a tag
NFC.instance.find do |tag|
  # Print out the tag we find
  p tag
end

That’s it! Run the code, then touch a tag to the reader, and boom! We have output. With the tag I’m using, the output looks like this:

$ ruby -I lib test.rb
(NFC) ISO14443A Tag
 ATQA (SENS_RES): 00  44
    UID (NFCID1): 04  D7  62  91  21  25  80
   SAK (SEL_RES): 00

The important part of this output is the UID field. That field is the unique identifier for this tag. The identifier comes back as a list of integers, but they are printed on the tag as hex. We can adjust the program just a little bit to see that list, or to get the same string that’s printed on the tag:

# Find a tag
NFC.instance.find do |tag|
  # Examine the raw numbers
  p tag.uid
  # Get just the UID as a string
  puts tag.to_s
end

The output looks like this:

$ ruby -I lib test.rb
[4, 215, 98, 145, 33, 37, 128]
04D76291212580

That’s pretty much it. Unfortunately, I can’t think of anything fun to do with my tags, but maybe you can! I hooked my tags up to the “say” command that comes with OS X and made each tag say something different.

Non-Blocking NFC interaction

Our previous example blocked until an RFID tag was read. If you run the program without having an RFID tag on the reader, it will just sit there until it can read a tag. Sometimes we might want to tell whether or not there is a tag on the reader right now. In other words, we don’t want our program to block.

Calling find without providing a block will return immediately:

p NFC.instance.find.to_s

You’ll get a return value immediately. The tag returned will either contain a blank uid, or an actual UID. Here is the output run once with a tag sitting on the reader, and once without a tag:

$ ruby -I lib test.rb
"04D76291212580"
$ ruby -I lib test.rb
""

Conclusion

That’s pretty much it. Interacting with the touchatag reader is quite simple and straight forward. Currently the nfc gem supports reading ISO1443A tags (the tags that come with the reader). The reader should be able to read other tag types, but I haven’t had a chance to get other tags to test.

Touchatag provides an official API for their readers. But the API seems difficult and is dependent on a network connection.

Here is a video of me reading some tags.
Here is the code from the video.
Here you can find more photos of the reader.
Finally, here is the source of the NFC gem.

Have fun reading some RFID tags!

20 Comments on Ruby and RFID tags

Respond

  1. Tys von Gaza says:

    Thanks! I’ve been thinking about working on a trail running timing application using RFID tags. This could really help!

  2. Tys von Gaza says:

    Awesome! Was thinking about toying with a timing system for running races and needed some way to interface with RFID’s.

  3. taelor says:

    This would be great to interface with some sort of locking system to use for a automatic door unlock.

  4. Ya, I was thinking of some sort of door lock too. Unfortunately, getting that set up with the location of my apartment door is just too difficult.

  5. Matt Todd says:

    There was a 24-hour bike race held recently here in Atlanta that used RFID to track the progress of the riders at specific checkpoints.

    Also, instead of still going the polling approach for non-blocking use, have you thought of implementing it with an EventMachine callback?

  6. I haven’t thought about using EM. The blocking / non-blocking support comes from libnfc itself. Since it’s built in, I’m not sure what using EM would buy me. I’ll have to investigate.

  7. Steven says:

    WTF? Dup post? I read this ages ago… Damn dawg…

  8. @Steven I never wrote an article about this. :-P

  9. Dr Nic says:

    I don’t have the cool touchtag kit but I felt compelled to install the libnfc thingy from the README. Except it failed.

    $ sudo port install libnfc
    Error: Port libnfc not found

    Yes, I cannot believe I managed to get this wrong some how. Thoughts?

  10. @DrNic maybe this:

      $ sudo port selfupdate -v
      $ sudo port install libnfc
    

    ?

  11. Dr Nic says:

    Awesome, upgraded from 1.7 to 1.8 macports and its installing. Thanks.

  12. Delvis says:

    Okidata uses a similar looking chip to identify their cartridges. Would love to be able to read these chips and reset them.

  13. [...] around with an rfid reader which was made oh so easy thanks to the hard work of a developer called Aaron Patterson whose Ruby wrapper of the C libnfc library really helped me get started on my voyage of all things [...]

  14. Martin says:

    I installed MacPorts and libnfc (1.2.1) and then the gem but I get

    ./nfc.rb:4: uninitialized constant NFC (NameError)
    from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `gem_original_require’
    from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in `require’
    from nfc.rb:2

    when running your example on Mac OS X Leopard with this Ruby version

    ruby 1.8.7 (2009-06-08 patchlevel 173) [universal-darwin10.0]

    Any thoughts as to why this would be?

  15. Martin says:

    I hate answering my own question (so I won’t) but the problem seems to have been resolved by installing Ruby 1.9 following (more or less) these instructions

    http://hivelogic.com/articles/compiling-ruby-rubygems-and-rails-on-snow-leopard

    It now reads NFC tags without complaining about the undefined constant – which may have been related to this perhaps?

    http://stackoverflow.com/questions/2031980/what-are-the-uppercase-and-lowercase-rules-of-ruby-method-name

  16. jerik says:

    Hi,

    tried to install “gem1.9.1 install nfc” but get always the error:
    /usr/bin/ruby1.9.1 extconf.rb
    checking for libnfc/libnfc.h in [...] no
    libnfc is missing.

    i have install libnfc and it is working fine. unfortunatly libnfc.h is not existing on my system. I checked out http://libnfc.googlecode.com/svn/trunk/ to retrieve it from there, but here it is neither. how do i solve this problem best?

    Following libs are available:
    /usr/lib/libnfc.a
    /usr/lib/libnfc.la
    /usr/lib/libnfc.so
    /usr/lib/libnfc.so.0
    /usr/lib/libnfc.so.0.0.0
    /usr/lib/pkgconfig/libnfc.pc
    /usr/local/lib/libnfc.a
    /usr/local/lib/libnfc.la
    /usr/local/lib/libnfc.so
    /usr/local/lib/libnfc.so.0
    /usr/local/lib/libnfc.so.0.0.0
    /usr/local/lib/pkgconfig/libnfc.pc

    can I use somehow another one?

    fyi: running ubuntu linux, not osx.

    cheers — jerik

  17. Jerik, make sure to install the development packages. Probably nfc-devel or something. That should have the header file included.

  18. Matt says:

    I’m having the same exact issue as Jerik. I can’t find nfc-devel anywhere. I’m compiling libnfc from source rather than using mac ports. Aaron, how did you install the development version and get the necessary header files (libnfc.h)?

  19. Ben says:

    Hey, this is a really cool demo. I just got my reader in the mail, but this doesn’t seem to work with touchatag reader anymore (tried with ruby 1.9.2 and 1.8.7 using rvm):

    lib/nfc.rb:52:in `connect’: could not find NFC device (RuntimeError)
    lib/nfc.rb:52:in `device’
    lib/nfc.rb:28:in `deactivate_field’
    lib/nfc.rb:96:in `find’

    Device is plugged in and scanning codes just fine, and I confirmed I’m using libnfc 1.5. Code is identical to example.

  20. Ben says:

    My bad, I must’ve done something wrong…

Respond

Comments

Comments