Building a book management system using a Raspberry Pi and an NFC Reader.
A project by:
Gabriel B. Soares
I recently made a large purchase of books for Alarm.com and began putting together an Engineering Library for the Device Team. With the purchase of so many new books (varying in size and cost) I wanted to build a system that would allow me to get some basic tracking as to where they are going, and be able to acquire some data on how many people in the team are utilizing these newly acquired resources. If I find that the team is taking advantage of these resources and there is a need to purchase more books, I can take the data and present it to upper management.
The idea to build a book management system is actually something that I have thought of in the past while I was building the bookshelves for my mom. For that project I envisioned creating a catalog system which would allow her to quickly search for a book on the computer and it would tell her in which area of the bookshelf she could find it. At the time, however, the cost of putting an NFC tag on each of the books and building the system was way beyond my budget.
For this project I decided to use a Raspberry Pi I had lying around at home, and an NFC reader (PN532) which a coworker had as a spare, to create a system that allows users to check books in and out as they wish and allows me to poll the system for useful data.
I have created a GitHub page for this project which contains the source code, CAD drawings, and detailed installation instructions. This page will cover the high-level design of the project.
As mentioned above, the main hardware components for this project are the Raspberry Pi (Model B) and the PN532 NFC breakout board from Adafruit. The Raspberry Pi communicates with the NFC breakout over UART and its role is to control the interaction with the user (through pushbuttons, and LEDs), update an internal database containing all the information about the library, and push statistics about the system to a web server.
The software components of this project consist mainly of: - MySQL database maintained locally on the Raspberry Pi - libnfc library which implements all the communications over UART to the NFC reader (open source library) - Python script which handles polling buttons, flashing LEDs, updating MySQL database, and pushing information to a server
I began this project by finding online instructions on how to interface the Raspberry Pi to the NFC breakout and found that I needed to install the libnfc open source library. The installation process took some time but the instructions I found online were very thorough and I've linked to it in the GitHub page. Once libnfc was installed on the RPi and I confirmed that it was functioning properly with the different Mifare NFC tags that I had, I began working on the MySQL installation.
This was the first time that I've worked with MySQL so it took me a while to get used to the syntax and figure out how to create and manipulate tables. Once I felt relatively comfortable with the syntax, I looked into ways of executing MySQL commands from a Python script and quickly ran into the MySQLdb library which makes short work of that task.
With these basic components I was ready to start putting together all the pieces and begin building the complete NFC library system.
In order to keep track of all the books in the system, I decided to install MySQL on the Raspberry Pi and create a few tables which are used to store key information for each book. The main table, whose columns are shown below, is used to track: - the NFC id of the tag that is placed on the book - the book title and authors - the status of the book (whether it is checked in or checked out) - the date of the last transaction - the user that checked the book out (currently not used) - the number of times this book has been checked out
+---------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+------------+------+-----+---------+----------------+ | row | int(11) | NO | PRI | NULL | auto_increment | | nfc_id | bigint(20) | YES | | NULL | | | book_title | text | YES | | NULL | | | book_author | text | YES | | NULL | | | status | tinyint(1) | YES | | NULL | | | date | date | YES | | NULL | | | user | int(11) | YES | | NULL | | | num_check_out | int(11) | YES | | 0 | | +---------------+------------+------+-----+---------+----------------+
There are also a few other tables on the database which are going to be used to associate an NFC tag to an employee (this will require me to hand out NFC tags to each employee wanting to use the system), and to keep track of basic statistics on the system (which book was last checked out, most read book, total number of books checked in/out, etc).
These tables are maintained from the Python scripts which are described in the next section. I can also SSH onto the Pi and access the database that way.
I began the project by writing a Python script to add a book to the library. This is a very simple script that just prompts the user for the title of the book, the author, and to present the tag to the NFC reader at the appropriate moment. The script then checks to make sure that there isn't an entry in the database with the same NFC id, and adds the entry to the database. If you click on the following image, it will load a gif showing what you would see if you ran the add_book.py script.
The second Python script that I wrote, which is the one that is continuously running, is a script responsible for polling the state of the buttons, updating the LEDs, interacting with the user, managing the database, and pushing data to a server. The script (called library.py in the GitHub project) is set up to run as a cron job and starts executing every time the RPi reboots. I also set up a cron job which restarts the RPi every night. This is to ensure that if for some reason the application stalls or isn't behaving properly, then it can recover after a boot-up.
The way the application behaves is as follows: - it begins by setting up the RPi GPIOs before entering an infinite loop - every pass through the loop it checks for a change in the state of the buttons and determines whether the user is trying to check a book in or out. - if the user pressed one of the buttons, the RPi turns on the yellow LED prompting the user to scan the book. - if the book was successfully scanned (NFC id detected, and database updated), the green LED will turn on indicating that the operation was a successful. - otherwise the red LED will turn on letting the user know that an error occurred.
The script also does a few other tasks. Every time a button is pushed, it starts a 30 seconds timer that will turn off any LEDs that were on. Any time that the script makes a change to the database, it gathers some basic statistics about the system and pushes those to data.sparkfun.com (information such as last book that was checked in/out, most read book, number of books that are checked in/out, etc) - see conclusion below. Since I want to be able to SSH to the RPi and it is not assigned a static IP, I had to add a way to read its current assigned IP. I added the function so that if both buttons are pressed at the same time, the RPi blinks the decimal representation of its IP address through the LEDs. I can then count the number of flashes, determine the IP, and SSH.
If at any point an exception is thrown, the script cleans up its GPIOs before exiting.
I built an enclosure for the system which I could mount next to the bookshelf and neatly house all the components. I had some spare 1/8" thick plywood and sheets of acrylic so I went down to the Techshop and quickly made a drawing for the enclosure following templates from a project I had worked on in the past. The back and sides of the enclosure are made out of wood, and the top is a clear acrylic (I left the protective film attached so that the color closely matched the wood.
For the acrylic piece I measured the position of the buttons and the LEDs and cut out the necessary holes for them to sit flush on the surface. I also etched text to indicate what each button does and what each LED represents as well as the location of where the NFC tags need to be scanned.
Lastly I cut out a slot on the side panel to feed power and ethernet cables to the Raspberry Pi.
With the scripts written, NFC reader tested, and enclosure built, the last thing to do was to put it all together. The images below show how I soldered, hot-glued, and connected all the components.
I thoroughly enjoyed putting this project together. I had been meaning to find something to do with my Raspberry Pi, and this proved to be a great application to use it. The system has been running for a few months and I haven't had any issues with it. Our library content is expanding, and I have been able to gather some information as to the types of books people have been reading.
This project also allowed me to play around with Sparkfun's free data stream service and learn how to display that information on this website: