Monday, October 18, 2010

RFID in Ruby

Anyone who's been reading my blog recently know that I've been playing with some RFID pieces for a local project. The project itself isn't important, though I may go into that in another post. For now, what I want to talk about is the gem I've written to help you get a project up and running with active RFID technology.

It was actually kind of fun to slog through the process of pulling off the input stream from this devices serial port, character by character, and try to put together something useful; However, I wouldn't want to do it again. Enter tag-it, my newest micro-gem hosted on rubygems.org.

The problem was this: I bought this RFID receiver, which works great. It's got a built in serial-to-usb adapter, so as long as you have the right driver installed, you can just plug it into a USB port and it will report tag names and their Relative Signal Strength as they come into range (see my last post for details). Then they just continue repeating all the in range tags every 2.5 seconds until they go out of range again.

That's cool, but it needs to be filtered. If you have a webservice tracking which tags are near which receivers, it's not performance friendly to just keep pinging the server over and over and over again with the same information (this tag is still here, this tag is still here, etc). In my case, I really only care about a tag "arriving" (coming into range) and "departing" (moving out of range). Thus, I built tag-it as a gem that sets up a class monitoring your serial port, and dispatching events as it decides they occur.

Example:


require "tag_it"
port = SerialPort.new("/dev/tty.yourport",{:baud=>9600})
tracker = TagIt::TagTracker.new(port)
watcher = YourCustomWatcher.new
tracher.add_observer(watcher)
tracker.start!

tag-it uses the standard observer class to dispatch events through an "update" method defined on the watcher, and sends three parameters (tag_name, RSSI, and event).

So, your watcher should be built like this:

class YourCustomWatcher
  def update(tag,strength,event)
    if event == :tag_arrived
      # do something because a tag has come into range
    elsif event == :tag_departed
      # do something because a tag has gone out of range
    end
  end
end

Thus far, that's it. Couldn't be simpler (well, maybe it could, but the gem is opensourced on github, so if you COULD make it simpler, send me a patch!).

So far this thing only interacts with this receiver (the one linked to above), but as I procure other sources of hardware, I hope to make this a pretty general library able to interact with whatever other input formats are available out there from other manufacturers devices.

Happy tagging!

0 comments: