Fingerprint Bouncer

From XinCheJian
Jump to: navigation, search

Hacking the Xinchejian doorbot

a solution to allow members to use their fingerprint with a scanner (GT-511C3) to open the door of the xinchejian hackerspace in Shanghai. Using a small Linux Device / Router (TL-WR703N) to send a RESTful request to the bouncer (doorbot) to:

  • open the door if a successful
  • enroll a fingerprint to an existing XCJ user account
  • remove a fingerprint from an existing XCJ user account
  • deny access and do not open the door if the fingerprint is not recognised.

OpenWRT firmware we can toggle the state of GPIO pins which will be connected to the control pins of the door opener by an optoisolated relay board.


Installing OpenWRT via TFTP

Install TFTP Correctly:

First you install and start a TFTP server (or daemon) on your host and place the image(s) to be flashed in the <root directory> of this software (you may be required to do this as root). Example:

 sudo apt-get install tftpd-hpa tftp

Configuration Edit /etc/default/tftpd-hpa, run:

 vi /etc/default/tftpd-hpa

Sample configuration:


How do I start / stop / restart tftpd-hpa server?

Type the following commands:

service tftpd-hpa status service tftpd-hpa stop service tftpd-hpa start service tftpd-hpa restart service tftpd-hpa force-reload

Test the server:

 tftp localhost
 tftp> get (some file)
 tftp> quit
 cmp /var/lib/tftpboot/uboot.img uboot.img
 # no output other then a prompt means it worked correctly

Using the TFTP Server

Follow the installation procedure for this router + version:

Generally speaking we connect to the bootloader, and tell it to get the images on your harddisk via its TFTP client Example:

 Redboot> load uboot.img

after successful installation of OpenWrt, do not forget to deactivate the TFTP server again!

Get OpenWRT Running on the TL-WR703

OpenWrt is a highly extensible GNU/Linux distribution for embedded devices. After upgrade your router to OpenWRT, your router will become much more powerful (more features) than before.

Warning: Flashing wrong version firmware will brick the router.

  1. Download correct firmware version
  2. Uppgrade firmware to Openwrt
  3. Open up a browser and navigate to (this is the default router IP)
  4. Enter admin for both username & password
  5. Status screen should appear.
  6. Select System Tools and Firmware upgrade
  7. Click on Browse button and select the Openwrt file that you downloaded
  8. Click on upgrade button in order to start upgrade firmware
  9. Restart router once the upgrade process finish
  10. Configure Openwrt
  11. TP-LINK TL-WR703N Openwrt Login
  12. Open up the browser and navigate to
  13. Click on Login button without password
  14. Click on Go to password configuration in order to change the password, SSH will enabled automatically.
  15. Your router is ready. You can add and remove packages based on your requirement.

More info:

Wiring Fingerprint Scanner to the Arduino Uno

Pin # Fingerprint Scanner <-> Arduino Uno

1 UART_TX <-> RX (pin 4)

2 UART_RX <-> TX (pin 5)

3 GND <-> GND

4 Vin (3.3V~6V) <-> 5V

Connecting the Arduino to the TL-WR703N

Arduino Uno as a USB to TTL converter. The Arduino Uno uses a software serial port to connect to the fingerprint scanner because the only hardware serial port on the Uno is connected to the USB chip which is used as the interface to the router USB port.

Serial data is relayed between the fingerprint scanner and the router by a sketch running on the Arduino.

The Arduino is plugged into the USB port of TP-LINK TL-WR703N to allow the router to control the Arduino and to listen to serial data from the fingerprint scanner.

After upgrade router firmware to Openwrt, Login to it & change the password in order to enable SSH.

Install Serial to Net (ser2net)

Here I show you 2 different methods to control the Arduino, ser2net and socat.

To install ser2net, execute this code:

 opkg install ser2net

Option 1: Install Serial to Net

To make ser2net listen on TCP port 1234, append 1 line to the end of /etc/ser2net.conf

Using WinSCP to edit the configuration. The setting is added to the ser2net configuration as shown in figure below

This will open a tcp 1234 port & set to baud rate 9600. The usb serial port will be /dev/ttyUSB0

Option 2. Install socat

socat is much more powerful & features than ser2net. To install socat, enter the following command:

 opkg install socat

Start ser2net or socat

You will need to start ser2net or socat before you can control the Arduino. There is two way to start ser2net & socat. You can start it manually or automatically on every reboot.

Start ser2net manually


ser2net will start based on ser2net configuration file

Start socat manually (Arduino Duemilanove)

socat tcp-l:1234,reuseaddr,fork file:/dev/ttyUSB0,nonblock,raw,echo=0,waitlock=/var/run/tty,b9600

This will open a tcp 1234 port & set to baud rate 9600. The usb serial port will be /dev/ttyUSB0

Start socat manually (Arduino Uno R3 USB chip)

socat tcp-l:1234,reuseaddr,fork file:/dev/ttyACM0,nonblock,raw,echo=0,waitlock=/var/run/tty,b9600

This will open a tcp 1234 port & set to baud rate 9600. The usb serial port will be /dev/ttyACM0

Open the port

This is particular important, it use to prevent autoreset on initiation of serial. cat /dev/ttyUSB0

You can open the port on every router reboot

  1. Login to router
  2. Click System -> Startup
  3. Scroll down the screen until you see Local Startup
  4. Enter cat /dev/ttyUSB0 before exit 0 as shown in figure below.

Arduino Code

     16 Output Arduino Controller Ver. 0.1
     Released on 22 Oct 2012
     SerialEvent only support Arduino ver 1.00 and above
     serial command syntax must be ssnn or ss nn 
     where ss is a two character command, it can be ON; OF; RS; AC
     where nn is the relay number, nn ranged from 1 to 16
     ON01 or ON1 <--turn on channel1
     OF02 or OF1 <--turn off channel2
     RS03 or RS3 <--get the state of channel3
     AC <--toggle acknowledge ON of OFF
     return 0 if output is low
     return 1 if output high
     return 2 if send ON successful
     return 3 if send OFF successful
   #define RELAY1 2    //Arduino Digital 2
   #define RELAY2 3    //Arduino Digital 3 PWM
   #define RELAY3 4    //Arduino Digital 4
   #define RELAY4 5    //Arduino Digital 5 PWM
   #define RELAY5 6    //Arduino Digital 6 PWM
   #define RELAY6 7    //Arduino Digital 7
   #define RELAY7 8    //Arduino Digital 8
   #define RELAY8 9    //Arduino Digital 9
   #define RELAY9 10   //Arduino Digital 10
   #define RELAY10 11  //Arduino Digital 11
   #define RELAY11 12  //Arduino Digital 12
   //#define RELAY12 13    //Do not use digital 13 since it will blink if usb serial connecting to computer
   //you can use the analog pins as digital pins, by numbering them 14 - 19.
   #define RELAY12 14      //Arduino Digital 14 (Analog 0)
   #define RELAY13 15      //Arduino Digital 15 (Analog 1)
   #define RELAY14 16      //Arduino Digital 16 (Analog 2)
   #define RELAY15 17      //Arduino Digital 17 (Analog 3)
   #define RELAY16 18      //Arduino Digital 18 (Analog 4)
   #define REL_COUNT 16    //how many relay
   String inputString = "";         // a string to hold incoming data
   boolean stringComplete = false;  // whether the string is complete
   boolean ack = false; //whether return status after serial command received

   void setup() 
     for (int i=0;i<REL_COUNT;i++) {
       pinMode(Relays[i], OUTPUT);  // declare Relays as output
     inputString.reserve(5); //reserve 6 bytes for the inputString:
     Serial.println("Controller Ready.");

   void loop() {
     // process data when a carriage return arrives:
     if (stringComplete) {
       // clear the string:
       inputString = "";
       stringComplete = false;

   void processData ()
      int thisRelay, val; 
      char relayNumber[3], cmd[3];
      char inputString2Array[6]; //hold the serial data in array form
      inputString.trim(); //remove whilte space
      inputString.toUpperCase(); //covert to upper case   
      inputString.toCharArray(inputString2Array, 6); //convert string to array
      // first two character is the command
      cmd[0] = inputString2Array[0];
      cmd[1] = inputString2Array[1]; 
      cmd[2] = 0; //null terminate      Command = Chr(data(0)) + Chr(data(1))
      //next two character is the relay numner (third & forth charcter)
      relayNumber[0] = inputString2Array[2];
      relayNumber[1] = inputString2Array[3]; 
      relayNumber[2] = 0; // null terminate        value = Chr(data(2)) + Chr(data(3))
      thisRelay = atoi(relayNumber);  //convert string to integer
      if (strcmp(cmd,"ON")==0)
         digitalWrite(Relays[thisRelay-1], HIGH);
         if (ack) Serial.println("2");
         else if (strcmp(cmd,"OF")==0)
         digitalWrite(Relays[thisRelay-1], LOW);
         if (ack) Serial.println("3");
      else if (strcmp(cmd,"RS")==0)
         val = digitalRead(Relays[thisRelay-1]);   // read the input pin, return 1 if High, return 0 if Low
      else if (strcmp(cmd,"AC")==0)
          ack = ! ack;
          if (ack) {
            Serial.println("Acknowledge on");
          } else {
            Serial.println("Acknowledge off");
   }  // end of processData

     SerialEvent occurs whenever a new data comes in the
    hardware serial RX.  This routine is run between each
    time loop() runs, so using delay inside loop can delay
    response.  Multiple bytes of data may be available.
   void serialEvent() {
     while (Serial.available()) {
       // get the new byte:
       char inChar = (char); 
       // add it to the inputString:
       inputString += inChar;
       // if the incoming character is a newline, set a flag
       // so the main loop can do something about it:
       if (inChar == '\r') {
         stringComplete = true;

The above code is a 16 output Arduino Controller this gives an abstraction layer to control the arduino.

Communicate with Arduino

You have finishing install all the required modules/drivers for the router. It is time to test the Arduino.

To control from SSH, use the following code to turn on channel 3.

  echo "@00 on 3/r" > /dev/ttyUSB0

RealTerm Communicate with Arduino

  1. Run realTerm
  2. Click on Port tab
  3. Enter 9600 for Baud since the default baud rate for the Arduino is set to 9600
  4. Enter, where is the router IP & 1234 is the port. Make sure it match with the ser2net or socat settings.
  5. Click on Open button
  6. Click on Send tab
  7. Enable +CR from EOL since the Arduino require Carriage Return as the termination.
  8. Enter @00 on 1 & click on Send ASCII button

You will notice that the LED1 from Arduino is turned on.

  1. Enter @00 of 1 & click on Send ASCII button to turn off LED1

Install FTDI USB Serial

 opkg update
 opkg install kmod-usb-serial-ftdi

If you are using Teensy or Arduino Uno:

 opkg install kmod-usb-acm

If you are using PL2303 based USB/serial adapters

 opkg install kmod-usb-serial-pl2303

If you are using CP201x based USB/serial adapters

 opkg install kmod-usb-serial-cp210x

Verify USB Serial driver

After install the FTDI usb serial driver, it is advise to verify the driver is installed properly. Plug in Arduino to the USB port of router and execute the following command.

 dmesg | grep -i usb

FTDI USB Serial Device converter is attached to ttyUSB0 by default. Unplug the Arduino from the router will display disconnected from ttyUSB0.

Howto: SSH to the Router

  1. Run PuTTy
  2. Enter for Host Name (this is the default IP for Openwrt set in TL-WR1043ND)
  3. Change connection type to SSH
  4. Click on Open button
  5. Enter your router username (username is root if you didn't change it)
  6. Enter your password

Software Serial with the Arduino

This allows us to use the GPIO pins on the arduino to connect to the UART interface of the fingerprint scanner and read the serialised fingerprints.

Note that the code was designed for the Atmega328P on the Arduino Uno. More information:

Check this section of code to ensure the pins are correct as above:

FPS_GT511C3 fps(4, 5); //software serial pins for Arduino's / Atmega328P's


Scanner Not Recognizing your Fingers? There have been issues trying to enroll with the Arduino example code. This is usually due to fingers being dry and not having good contact on the scanner. The timing of your finger on the scanner is a little tricky too. I had to try enrolling a few times before it was able to enroll or identify my finger. This is common with any fingerprint scanner like the one that is on my smartphone. Try re-enrolling your finger.

Hardware Connections Resistors for Logic Level Conversion? The example code was originally used with an Arduino and the GT-511C3. Looking at the datasheet to compare, it looks like it might be 5V tolerant since it does not have 3.3V I/O limitations. If you are having issues using this fingerprint sensor with the resistors, try removing the resistors that were meant to voltage shift the signals. I had a customer that had problems using this with the resistors explained in the Instructable tutorial. When he removed it, he got it to work.

Loose Connections Make sure that there are no loose connections. The last thing to check is the connection between your scanner and Arduino. Each of the fingerprint scanners use the same command protocols so the Arduino example code in the Instructables tutorial can be used for any of the scanners.