Listkeeper run view
Article / 10th Jan 2020

The RFID Checklist

On my very first trip to the US, I managed to forget my phone charger at home. This might seem like a minor issue today, but these were the halcyon days of 2008, when every phone had a slightly different barrel-plug charger. Try as I might, I couldn't find a replacement, and so I just had to go without for a week.

Note

The phone? A Nokia 6280. I miss slide phones.

Ever since that trip, I keep a travel checklist. This is very on trend for me; I like to keep things organised and know where everything is. If you've met me in person, I'm sure I've praised the checklist as a solution to many problems. Naturally, this means I am also always on the lookout for ways to automate the process.

Running a checklist each time I head out on a trip is not particularly exhausting, at least for relatively normal trips. However, if you add in a trip to the Arctic, camping somewhere remote, or taking my drone and video gear, it gets more complicated. In each of these cases, I have ended up forgetting something.

My first attempt at automating this, three years ago, was barcodes; that quickly failed as it merely added even more manual labour to the process. For a long time afterward, I've made do with a series of todo or checklist apps; none quite fitting my needs, but working well enough that there's no need to change.

A few months ago, though, it dawned on me that the problem must have already been solved in industry logistics - there's no way they would stand for having to manually scan everything, and barcodes have this annoying property that makes them very hard to scan at range unless you plaster them all over boxes. Enter long-range RFID.

RFID

RFID is incredibly common in the modern world - I'm sure many of you have interacted with an RFID keyfob to get into a building, or used contactless credit cards or transit cards.

Confusing NFC and RFID is a common mistake - NFC is a subset of RFID technologies, working in the 13MHz frequency range. NFC, specifically, is what passports, credit cards, transit passes and phones all use.

Note

RFID keyfobs are their own separate standard again - operating on 125MHz.

RFID has more to offer, however - specifically in terms of range. NFC readers rarely work well beyond a few centimetres, whereas other RFID technologies can work at a range of tens of metres. There are dedicated RFID implementations just for logistics and item tracking, aimed at range and reliability, and the best one of these is EPC Class 1 Generation 2.

Now, while that's quite a mouthful - I'll call it C1G2 from now on - it has a lot of really interesting properties. High power readers can read tags over a distance of metres or more; it's designed to read hundreds of tags per second from a single reader thanks to some statistical magic; and tags are cheap and don't need batteries.

In short, it's perfect for tracking a bag or car full of items. Tags can be purchased for $0.10 or less in bulk, and come in a dizzying array of sizes, form factors, and mounting options.

Armed with this knowledge, and being reasonably sure that C1G2 was the answer to my inventory-tracking needs, I set about acquiring some readers and some tags.

A Tale Of Three Readers

If you look online, you'll find that C1G2 readers come in roughly one of three styles - small, short-range desktop readers, handheld medium-range readers, and fixed long-range readers.

Now, while the cost per tag for C1G2 is very reasonable, the hardware is very much not in the same bucket. Only the low-power desktop readers are reasonable to purchase new, and even that means buying them from a Chinese reseller. Handheld or fixed readers are close to a thousand dollars new, and more if you want good ones.

ALR-9650

An Alien ALR-9650 reader

This meant that, while I could quickly purchase a small desktop reader for testing, I had to scour eBay for used devices in the other two categories. Luckily, I found an Alien ALR-9650 for only $100 - a very capable fixed reader that runs off of Power Over Ethernet (PoE) as well as having a built-in antenna (most fixed readers require separate antennas and power supplies).

Once they arrived, I had to turn to working out how to interface with them. The Alien device is fantastic - you log into its web UI, tell it where to send tags to and how often to scan. It'll periodically open a TCP connection, shove a list of tags over it (one per line), and then close it again. It's the sort of thing that's trivially easy to handle in Python and I had a server for that running after only half an hour.

The desktop reader, however, is more special. It shows up as a USB-to-serial converter when you plug it in, so you know you're in for a good time. Some digging, and helpful pointing by some people who've already tried interfacing with these devices, finally turned up a full spec document for the serial protocol, written in mostly-correct English.

I'm a bit rusty at serial interfaces, and so it was several hours with Python's struct module and PySerial before I had it scanning tags and reporting them back over the serial connection. Nevertheless, the serial protocol is actually quite well designed and has good error reporting, so I quickly spun out a Python script that could continuously scan for tags and report when new ones were seen.

Happy with my initial exploration and proof-of-concept, I now had to turn to making an actual running system out of all this, and flex that small part of me that is a product designer.

What makes a good checklist?

It's always a lot easier to design something when you are also the customer - an endless set of Silicon Valley startups that fail to appeal to anyone who is not a software engineer will tell you that - but it's still important to sit down and work out what you actually want.

My short pitch to myself was that I wanted to be able to drop my bag on the scanner, have a checklist mostly completed with all the items it found, and then check things off manually that couldn't be tagged (we'll get into that more later).

The first stop is a logical data model. We know we want multiple tags per item, and while C1G2 tags are programmable to change the EPC (tag ID), I still wanted the ability to have multiple EPCs per item - it skips the slightly-annoying programming step and lets you just take them off a roll of tags and slap them on. Items also have a name, and niceties like a description and photo.

Note

The annoying thing about programming tags is that it will write to a random tag in the device's field - meaning you have to make sure every other tag is shielded or far enough away.

Secondly, I know I want a checklist that describes a set of items I should have, and is able to match them to the actual items present. Rather than force a one-to-one link to a specific item, I instead opted for a "label" system - items have labels, and checklists require items with certain labels (and optionally a quantity - e.g. "I want 2 of multi-adapter").

The rough flow, then, is that a reader scans a bag, uploads the set of seen EPCs to the system, which then proceeds to match the EPCs into a set of items. That set of items is then marked as in the bag, and a checklist item is marked as completed if it has labels that match one of the seen items.

There's plenty of polish to make this into a finished system, but that comes later - when I am still sounding out a project like this, I want to build the core logic quickly to ensure my assumptions are correct before applying the final fit-and-finish to turn it into something pleasant to use.

System Architecture

Naturally, my inclination for the main part of the system - the business logic and web interface - was to write it in Django. Nothing else gives me quite the speed and toolset to rapidly design a data model and interaction pages that are actually usable at the end of the day, rather than being throwaway prototypes.

A few hours of models, migrations and generic views later, I had my basic data model built out with some rather cheap-looking templates - enough to interact with the system and make sure it was going to work. A basic token-based API model and some JSON later and I also had an API for ingesting EPC tags from a reader.

I used this project as a chance to finally try out Google Cloud Run, since I'm a little tired of running my own Kubernetes cluster. I liked it so much, in fact, I then proceeded to move all my sites over to it - but that's a topic for another blog post. Using it, though, I quickly had the Django app running, and a nice deploy pipeline built out of Github Actions.

Unfortunately, both the Alien reader and the desktop reader needed a host machine to proxy data to the main Django site - the Alien reader is only capable of transmitting to local IPs, and the desktop reader is a USB device. A small proxy app running on my home server handled the first problem - taking the raw TCP lines from the ALR-9650's updates, formatting them into JSON, and handing them off to Django. A Raspberry Pi running a similar script but with a serial interface solved it for the desktop reader.

Add all these things together and I had the bones of my system. I could place an item with tags on the scanner, and it sent EPCs up to the Django site - where I could click on them and create a new item to assign to them, along with labels to automatically match into checklists.

Frontend Polish

I have avoided writing "modern" JavaScript for many years, in part because I'm stubborn but mostly because the majority of my work is deep backend work. This means I'm a little rusty and tend to fall back to jQuery when I need some interaction.

This time, though, I knew I should take the plunge and finally use modern, reactive JavaScript - it's the perfect use case for a checklist-style app. React is the most popular choice, but on the advice of some friends I also checked out Vue.js.

I'm not going to get into an endless debate about which is better, but Vue's increased focus on how to run it with just a script tag appealed much more to me - I don't want to have a whole NPM toolchain or have to run webpack on every build. I could easily write Vue apps as single ES6 modules and include them directly in the page without ever installing npm, and so that's what I chose.

Reactive JavaScript frameworks really are as good as they claim - writing frontend code for browsers is finally like using a really good GUI toolkit that understands data binding, and while I miss jQuery's batteries-included approach, my need for nice AJAX requests was quickly covered by Axios (including built-in CSRF support, so good on them!)

Getting Django and a frontend to reliably synchronise changes does, of course, continue to be a challenge - I definitely see some things here we could do with Django to make it better, and my renewed enthusiasm for writing UIs after all of this may drive me to get those changes rolling. That said, a basic load/save loop with a frontend lock does a good enough job for me as a single user who occasionally has two tabs open on the same checklist.

I also took the time to go over the UI and make it look somewhat more presentable. I'm certainly no graphic designer, but design is a key part of making something usable, and so I made sure to make it clear, readable, and add UI affordances to tell me when things were going wrong (like a background save not working correctly).

The Trouble with Tags

I mentioned earlier that I needed manual checklist editing for some items that were untagged. Why, you may ask, would everything not have a tag? Well, ignoring checklist entries that aren't even physical items - like "Download Videos" - the other part of the answer is down to physics and effort.

RFID tags come in three basic types - fabric tags, designed to be sewn into garments or sheets; "label-type" tags, designed to be stuck onto plastic or cardboard; and on-metal tags, designed to work on metal surfaces. They are all basically a microchip the size of a speck of dust with antennas coming out of them, just in different form factors and with different tolerances.

RFID Tags

A selection of C1G2 tags

Why are there specific tags for metal? Well, if you are not familiar with antenna tuning, count yourself lucky. In short, antennas are designed for a specific frequency - in the case of C1G2 in the USA, that's around 915MHz. This is mostly a function of length, but also of the surfaces around the antenna that also interact with radio waves and cause capacitance or inductance.

Look at a label-type RFID tag, like in the picture, and you can see the antennas - they're the long traces, designed to be an exact length to match the wavelength (in fact, most have two - one for the US frequency, and a slightly shorter one for the EU frequency of ~867MHz). Stick them on plastic or cardboard, and they work great - the larger the antennas, the further away they read well.

This all fails when it comes to putting RFID tags next to metal components, though. The metal detunes the antennas, causing the tag to no longer receive the signal and thus not even get enough power to turn on. If you get it close enough to a powerful reader, you can probably energise it, but it's not going to be happy.

In these cases, you need special tags designed to be used on metal. You can tell those in the picture above as they're the thicker ones - they have a built-in ground plane to allow the antenna to tune properly with metal around. In fact, they are tuned for metal so much that they perform significantly worse if you put them on something non-metallic.

Note

Antenna design is somewhere between a dark art and a science and, despite my amateur radio license, I still don't know enough about it.

Of course, what this means is that most on-metal tags are thick and rigid, and this makes them a pain to stick on some consumer devices. While I can stick a tag on my laptop charger no problem, there's not really a good place to put it on my laptop's sleek, all-metal chassis, let alone smaller items like my Nintendo Switch - which, while it has a plastic shell, still has enough metal inside to detune the tags.

Now, let's talk about clothes. Not only do they make laundry-safe tags, they are actually widely used in both industrial laundries as well as some retailers. If you were to buy something in a Uniqlo shop, you'd notice they don't scan any barcodes - they put your shopping on an RFID reader next to the till and it simply reads the tags to work out what you bought.

The main issue here is cost and effort. I don't want to sew tags into every one of my ~100 t-shirts, and even if I did want to, they're not cheap to buy if you want nice, small ones that are going to go unnoticed when you're wearing them.

In general, tag costs aren't too bad; they range from $0.05 per tag for a roll of flexible sticker-type tags to around $5 a tag for the really nice on-metal ones. If you look around and aren't picky you can often find good clearance deals on bulk sets of tags.

I ended up with a large set of different tag types that mostly covers the things I want to tag, though I'm still looking for a good, sleek solution for things like my iPad and laptop. There are tiny, 3mm-wide tags for tracking small tools, though, so I need to try some of those out.

Privacy

I would be remiss to keep going without mentioning the dark side of walking around with a bag full of C1G2 tags. They are an incredibly easy way to track you - remember, each tag has a globally-unique ID, can be read from tens of metres away, and uses an easily-accessible industry standard that anyone can buy hardware for.

This dark future is already arriving, though, as retailers increasingly use C1G2 tags in their products. Uniqlo are hardly the only ones doing this; I know Decathlon do as well, and I'm sure there are many others. C1G2 has a part of the specification specifically designed to allow tags to be permanently "killed" - for example, as a customer walks out of a store past a special set of RFID interrogators - but these seem to be rarely set up.

When I initially turned on my RFID readers, they found over 20 C1G2 tags in my house that weren't part of my set of purpose-bought RFID tags - hidden in random product boxes, or in one case, the toll tag on my car. I even found one in my US Green Card when I took it out of the RFID-shielding sleeve they tell you to keep them in.

These things are everywhere, and it's only getting worse. I personally believe that if someone wants to track me, there are better ways, but it's worth bearing your threat models in mind before you rush out and cover all your belongings in long-range, globally-unique RFID tags.

I also suspect we have a greater privacy conversation to come with these tags, as they leak more and more into the consumer market.

The End Product

So, after all that work, and all those caveats, I do now have a fully automatic checklist system. It has a rich javascript checklist template editor, where you can create sections, items, drag things around, and even gate certain items behind "conditions" - for example, only show warm clothing items if the destination has cold weather.

Listkeeper template view

Template editor

Listkeeper run view

Running a checklist

Listkeeper device view

Device tag listing

Bag-Checklist-Animation

In action!

When you run a checklist, you can start it scanning with a reader and a location (the name of the bag, at this point), and you simply rotate the bag in front of the scanner for about ten seconds to get a good read of all the tags.

The checklist automatically updates and marks all the items it can find as completed, and then all you have to do is manually check off anything else. There's even some niceties like the ability to mark items as skipped rather than packed, and to see only the items that haven't been packed yet.

When spring rolls around, I have another reader I intend to mount in the garage to track what's in the car as I pack it for camping - here, the relatively larger size of camping items makes sticking nice, big, long-range tags on them a lot easier.

So far, it seems to work well - not only being a nice way to automate a good chunk of my checklist but also in that it is designed as a dedicated travel checklist, with things like the conditional items that vary based on location. I'm certainly happy, and while I'm not sure it was strictly worth the time investment building the system, I've learnt a lot along the way, especially about modern frontend coding.

There's plenty more ideas for the system, too - my original line of thought was about tracking every tool and device in my small workshop, and I'll likely return to that. If I ever move again - and I know I will have to at least once more in the near future - it would be great to track what is in each moving box, as well.

But, future plans aside - by this point, I'm sure several of you are thinking "Well, I would love one of those! I always worry when I'm packing for a trip!". In any other situation, I might be tempted to try and build a product around this, but the very high cost of entry to this system dissuades me from doing so, and will make it hard for you to make one for yourself.

Even buying used hardware and discounted tags, I've spent around $300 on this system; with everything bought new, it would be at least $2,500. That's not even counting the handheld scanner I'd like to eventually move to as the main way I scan things - powerful handheld scanners seem to be $500 even when used, and those are the ancient ones running Windows CE (shudder).

Just buying a bare RFID-scanning board to integrate into my own handheld reader design is $200 (I'm working on that, but embedded hardware design is a whole other blog post!)

I'd love to be able to bring something like this to more people - and, if you have a few million dollars just burning a hole in your pocket, please do send me an email - but I'm afraid that, until the technology involved becomes more commoditised and prices come down, it remains something for hobbyists to scrape together from the used devices that make their way out of industry. If you are interested, though, I have put the code up on GitHub, and I'm always happy to talk shop about travel or RFID!