RFID Door Access V2.0
 Page :   [ 1 ]    [ 2 ]    [ 3 ]    [ 4 ]    [ 5 ]    [ 6 ]  

Software on Pi

Will be needing some software for listing to the data sent from the card readers.  Luckily the PIGPIO site has some excellent examples and just so happens to have some Wiegand examples!

Since I plan to interact with the GPIO wia the PIGPIOD daemon then I will need the correct examples and code considerations going forward.

 
cd ~/

mkdir wiegand

cd wiegand

wget http://abyz.co.uk/rpi/pigpio/code/WD.zip

unzip WD.zip

gcc -Wall -pthread -o WD test_WD.c WD.c -lpigpiod_if2

The wiring of the data wires from the card readers are as follows:

Door 1
======
D0    gpio 14
D1    gpio 15

Door 2
======
D0    gpio 24
D1    gpio 23

Test the code by running it like this. (e.g. for "Door 1") I had to add -m3500 because the default of -m2000 didn't seem to accumulate all the bits before sending them back.  -m3500 gave the correct results of reading all the bits properly.

./WD -g14 -w15 -m3500

Now scan the card reader.  You should see some output that shows the card number and how many bits.

 

Create a databse for the system to use.  Login to MySQL and do the following:


create database rfid;

use rfid;


create table card(
    cardId     int unsigned not null primary key auto_increment,
    facility   int unsigned,
    number     int unsigned,
    isMaster   tinyint unsigned not null default 0,
    label      varchar(16),
    person     varchar(32),
    isVisible  tinyint unsigned not null default 1   
);

create unique index ix_card_facility_num on card (facility, number);



create table location(
    locationId       int unsigned not null primary key auto_increment,
    locationName     varchar(32) unique
);



create table locationCard(
    locationCardId    int unsigned not null primary key auto_increment,
    cardId            int unsigned not null,
    locationId        int unsigned not null,
    isVisible         tinyint unsigned not null default 1    
);

create unique index ix_locationcard_cid_lid on locationCard (cardId, locationId);



create table locationCardDayTime(
    locationCardDayTimeId  int unsigned not null primary key auto_increment,
    locationCardId         int unsigned,
    day                    int,    
    begin                  varchar(8),
    end                    varchar(8)    
);



create table history(
    historyId       int unsigned not null primary key auto_increment,
    locationCardId  int unsigned,
    inserted        timestamp not null default now()
);

 A little data populating for testing:

insert into location (locationName) values ('DOOR_01');

 

Modify the wiegand example a bit for my own use.  just edited their example file "test_WD.c".

/*
TO BUILD

gcc -Wall -pthread -o WD test_WD.c WD.c -lpigpiod_if2

TO RUN

./WD -gGPIO -wGPIO

*/

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>

#include <pigpiod_if2.h>

#include "WD.h"


#define false 0
#define true 1
typedef int bool;

void fatal(char *fmt, ...){
    char buf[128];
    va_list ap;

    va_start(ap, fmt);
    vsnprintf(buf, sizeof(buf), fmt, ap);
    va_end(ap);

    fprintf(stderr, "%s\n", buf);

    fflush(stderr);

    exit(EXIT_FAILURE);
}

void usage(){
    fprintf(stderr, "\n" \
        "Usage: WD [OPTION] ...\n" \
        "   -g value, gpio green (0), 0-31,           default None\n" \
        "   -w value, gpio white (1), 0-31,           default None\n" \
        "   -m value, message gap, 1000-65000 micros, default 2000\n" \
        "   -l string, location,                      default NULL\n" \
        "   -r value, relay,                          default none\n" \
        "EXAMPLE\n" \
        "WD -g10 -w12 -m3500 -r17 -lDOOR_01\n" \
        "   Read a Wiegand device connected to GPIO 10/12.\n\n");
}

int optGpioGreen = -1;
int optGpioWhite = -1;
int optGap = 3500;
int optRelay = -1;
char *optLocation   = NULL;

bool masterMode = false;  // if in master mode
double startMasterMode;   // when master mode started
char outBuffer[512];      // bufferfor command to call php script
bool doorOpen = false;    // should door be currently open
double startDoorOpen;     // time door opened



static uint64_t getNum(char *str, int *err){
    uint64_t val;
    char *endptr;

    *err = 0;
    val = strtoll(str, &endptr, 0);
    if (*endptr) {*err = 1; val = -1;}
    return val;
}

static void initOpts(int argc, char *argv[]){

    int opt, err, i;

    while ((opt = getopt(argc, argv, "g:w:m:l:r:")) != -1){
        switch (opt){
            case 'g':
                i = getNum(optarg, &err);
                if ((i >= 0) && (i <= 31)) optGpioGreen = i;
                else fatal("invalid -g option (%s)", optarg);
                break;

            case 'w':
                i = getNum(optarg, &err);
                if ((i >= 0) && (i <= 31)) optGpioWhite = i;
                else fatal("invalid -w option (%s)", optarg);
                break;

            case 'm':
                i = getNum(optarg, &err);
                if ((i >= 1000) && (i <= 65000)) optGap = i;
                else fatal("invalid -m option (%s)", optarg);
                break;

            case 'r':
                i = getNum(optarg, &err);
                if ((i >= 0) && (i <= 31)) optRelay = i;
                else fatal("invalid -r option (%s)", optarg);
                break;

            case 'l':
                optLocation = malloc(sizeof(optarg)+1);
                if (optLocation) strcpy(optLocation, optarg);
                break;

            default: /* '?' */
                usage();
            exit(-1);
        }
    }
}

void cbf(WD_data_t w){

    sprintf(outBuffer,"/usr/bin/php /var/www/html/wiegand.php \"%llu\" \"%d\" \"%s\" \"%d\" ", (long long)w.code, w.bits, optLocation, masterMode);

    int i = system(outBuffer);

    if (i == 1024){
        if (!masterMode){
            doorOpen = true;
            startDoorOpen = time_time();
        } else {
            doorOpen = false;
        }
    } else if (i == 1280) {
        doorOpen = false;
        masterMode = true;
        startMasterMode = time_time();
    }

}

int main(int argc, char *argv[]){
    
    int pi;
    WD_t * w;

    initOpts(argc, argv);

    if ((optGpioGreen < 0) || (optGpioWhite < 0) || (optRelay < 0) || (optGpioGreen == optGpioWhite)){
        fprintf(stderr, "You must specify the green and white and relay GPIO.\n");
        exit(0);
    }

    if (optLocation == NULL){
        fprintf(stderr, "You must specify a location. i.e. DOOR_01\n");
        exit(0);
    }

    pi = pigpio_start(NULL, NULL); /* Connect to Pi. default host, port */

    if (pi >= 0){

        w = WD(pi, optGpioGreen, optGpioWhite, optGap, cbf);
      
        while(1){

             if (masterMode){

                if ((time_time() - startMasterMode) < 10.0){
                    masterMode = true;
                } else {
                    masterMode = false;
                }

            } else {

                if (doorOpen){
                    if ((time_time() - startDoorOpen) < 5.0){
                        doorOpen = true;
                        gpio_write(pi,optRelay, 0);
                    } else {
                        doorOpen = false;
                        gpio_write(pi,optRelay, 1);
                    }
                }

            }

            usleep(250000);

        }

        WD_cancel(w);

        pigpio_stop(pi);
    
    }
    
    return 0;

}

Build it and copy it to an appropriate location:

gcc -Wall -pthread -o WD test_WD.c WD.c -lpigpiod_if2

sudo cp WD /usr/local/bin

Then add this to "/etc/rc.local" for it to run when the Pi boots and will "listen" to the card reader.

sudo pico -w /etc/rc.local

#add the following to /etc/rc.local
# in this example i have D0 and D1 of
# the card reader going to GPIO 14 and 15 of the Pi
# the signal GPIO for the relay in my setup is 17
# also i named this particular location "DOOR_01"
# which was previously inserted into the location
# table of the database

/usr/local/bin/WD -g14 -w15 -r17 -m5000 -lDOOR_01 > /dev/null &

 

 

(Page 5 of 6)