Shelf Cleaner: what it does and Koha

Let’s get geeky about the functionalities of the RFID scanner and the integration with Koha, here at Deichman.

Note: This is a more technical followup of this previous article, you probably want to read it first, if you don’t have already.

There are 2 main areas of effect when using the RFID Scanner with Koha:

  1. the cleaning, when a book currently scanned during the inventory isn’t supposed to be there
  2. the inventory/history, after the inventory, to see where a book is and has been

But before diving into those, we need a bit of background on how the scanner works.

Shelf tags

One of the key features of using the scanner is the ability to use RFID tags identify containers (like shelves, boxes or bookcases) instead of just items.

Scanning those tags will set the “current location” of the scanner, and every item scanned after that will be bound to that location.

There are 2 different types of locations, permanent and temporary. The desk in the sorting office is a temporary location, while the shelves in the public area are permanent.

Here some examples of permanent locations:

  • main.stack.m3.15 — main branch, archives, room m3, bookcase 15
  • — ABC branch, public area, green room, bookcase a03

and some temporary locations:

  • xyz.pickup — pickup shelf for patrons in branch XYZ
  • abc.verify.damaged — virtual location for ABC’s damaged items
  • — self service machine, check out at XYZ
  • main.staff — staff desk at main

Each item will then have a permanent location (e.g.: main.stack.m3.15, the item belongs to the main branch archives) and a temporary location (e.g., the item has been checked out at a self service machine at XYZ branch)


I will focus on Deichman Library’s specifically now. Your library is probably different and will have different issues, but most of the concepts will still apply.
The CD is marked as “overdue, paid”

There are many situations we encountered while testing the scanner:

  • books that are good candidates for a hold/reserve
  • books that are on the shelves, but are still marked as on loan
  • books that are on the shelves, but belong to a different branch
  • books that are marked not for loan (this can means different things: they are not supposed to be on the shelf or someone forgot to check them in)
  • books that are marked as in transfer but they actually reached the destination already
  • books marked as lost or misplaced
  • books that belong to another library. (Inter Library Loan)

Each of those will act differently, they can either fix the problem “on the fly” (e.g. when the book is marked in transfer, but it is at the destination already), or instead signal the user that some action must be taken (the book needs to be picked up for a patron, the destination will be set to “abc.pickup”).

It also depends on where the book is scanned. A transfer will be marked as completed only when the item is at the right destination, otherwise a “pick me up” will be sent to the user to carry over the transfer.

Cleaning up those cases can be a priority. Mostly because in most of those cases those items won’t be available for loan on the web interface or on the “pickup list”. But also because some others can be incredibly hard to track or fix later.

All this logic is inside the API (/api/v1/location) that we added to Koha. It deals with all those combinations and will simply returns a “destination” for the item, or in other words where the book should be.

The scanner will simply compare the current shelf with the destination, and beeps if they don’t match. (It’s a bit more complicated than that, a book scanned in “” will match “abc”, or “”, but not “abc.verify.lost” or “xyz”)


The other area of effect for the scanner is the ability to track down the history of each item, and the current location along with other items.

Example: history of an item

The image above shows the history of a single item, sorted by the most recent events first. It can and will grow much more longer as long as the item is scanned and transfered.

You can read the history like this:

  • The scanner found the item the 23rd of October, and bound it to “” (“flam” branch, public area, 3rd floor, shelf d04).

The book was then requested by a patron for pickup from the main library:

  • a first check in by the staff happened 35 days ago (,
  • and the day after in hutl (which is our main library branch).
  • It was then checked out by the patron using a self service machine 6 days later (
same book in the Shelf view

Browsing the database for the same shelf (, you can see the item is still there. Even though the last seen location is the checkout machine in hutl, the “permanent” location is remembered and you can still see the loaned books on the shelf (even though the last location is different).

item’s details, with before/after

Here on the left, the details view of the same item, with the permanent “shelf” location (, and the “temp”-orary location or last-seen (

Some items have multiple parts and therefore multiple tags: each individual tag is shown here, and has it’s own history, so if one part was missing you can find out since when.

Quite interesting is the last part, where you can see which items where scanned before and after.

This information can be helpful when the book is misplaced, so instead of searching for it directly you can just search for which books were close by (which are hopefully not misplaced) and then look between them.

Of course it might still be easier to mark the item as misplaced in Koha and wait for the next inventory, but if you are in a hurry you can track it down this way as well.


Unfortunately Koha support for history and location is sub-optimal, so instead of adding new tables and interfaces to Koha we decided to setup a new system which will augment Koha by living alongside, and limit the integration with Koha to a single API entry point.

There are also some other technical reasons for this, mainly the scanner is just a micro-controller and it would be hard and clumsy to implement a full authentication system.

The server we developed is written in Perl and based on Plack. It acts as an interface between the scanner, the self service machines, the desk RFID readers and Koha. It also has a API interface itself which can be used to query for information. The idea is to add a Javascript front end to it (right now the Perl app can serve html pages as well)

On the Koha side, as mentioned already, a new API entry point was added: /api/v1/location

$ curl -s --data '[{"barcode":"03010738409003"}]' http://my.koha/api/v1/location | json_xs
"items" : [
"reserves" : {
"fnyd" : {
"count" : 1,
"oldest" : "29",
"need" : 1,
"avail" : 0
"hutl" : {
"count" : 2,
"need" : 1,
"oldest" : "28",
"avail" : 1
"author" : "Fennell, Melanie",
"homebranch" : "hutl",
"biblioitemnumber" : "738409",
"holdingbranch" : "hutl",
"barcode" : "03010738409003",
"title" : "Å bekjempe lav selvfølelse",
"itemnumber" : "650684",
"itype" : "BOK",
"copynumber" : "3",
"dest" : "hutl.onloan",
"itemcallnumber" : "158.1 Fen"

It accept a list of entries, with mandatory barcodes and an optional location. It performs the cleanup when needed, and returns a destination with some metadata (title, author, call number).

The RFID server uses this information to decorate the output, and to determine if the item needs to be moved, or if it should be left in place.

Note: Koha could store the location provided by the RFID Scanner in the “location” field. If so all the view will display is where the item was scanned last. Unfortunately we are already using this field for other internal reasons so we skipped this step.

What next?

This is pretty exciting: I’m working on a system which is able to detect misplaced items (and suggest the correct location). It works by comparing similar items (call number) in different shelf. It is way too early to share any results, but many of the detected misplaced items are already good, so it might be ready soon.

The server is still under development. All the images posted here came from a prototype which will be rewritten. As soon as we have something stable we will push it out on github here.

I will also add some documentation on how to write your own adapter if you are using a different ILS than Koha, but as you can see it will be fairly easy.