- Concepts
- Demonstration
- Working flow
- Things used in this project
- Wiring Diagram between PHPoC and Adafruit PN532
- Source codes
- A normal lock using RFID
- Simple IoT Lock
- Database design
- Libraries
Concepts
- Normal RFID Lock: a device which prevents something such as a door being opened and which you can only open with some specific RFID Tags.
- Simple IoT Lock: a RFID lock connected to internet with some additional features:
- Access permission is managed by a server which allows flexibility in managing the system especially with multi-door and multi-user.
- The accessed history is stored in database
Demonstration
This video introduces a demonstration of unlocking the door of manager’s room.
Working flow
A normal lock using RFID
IoT Lock
Normal RFID lock is simple to implement. It does not require internet connection and database query as well. However, it has some drawbacks. Memory of embedded system is limited. The number keys are, therefore, limited. In the other hand, it’s inflexible to add/remove a key to/from the system (when loosing key, changing key or adding new key for new user) and change the privilege as well.
In comparison with the normal RFID Lock, the simple IoT lock is a little more complicated. However, it overcomes all drawbacks of the normal RFID lock. Additionally, history of access is stored, allowing to monitor/check who opens the door when needed.
Things Used In This Project
- PHPoC Blue or Black
- PN532 NFC/RFID controller (in my case, I used Adafruit PN532 RFID/NFC Breakout)
- Some NFC/RFID tags
- PHPoC bread board (Optional)
- Jumper wires
Wiring Diagram between PHPoC and Adafruit PN532
- PHPoC------------- Adafruit PN532
- 3V----------------3.3V (Red wire)
- SCK ----------------SCK (Yellow wire)
- MISO---------------MISO (Green wire)
- MOSI---------------MOSI (Blue wire)
- 4 ------------------SSEL (White wire)
- GND---------------GND (Gray wire)
Source codes
A normal lock using RFID
<task0.php>
PHP Code:
<?php
if(_SERVER("REQUEST_METHOD"))
exit; // avoid php execution via http request
include_once "/lib/sd_340.php";
include_once "vd_pcd_pn532.php";
include_once "vd_mifare_classic.php";
$uid = "";
$pre_uid = "";
$access_list = array("FE65B0AB"); //add more Key here
function access_list_look_up($uid)
{
global $access_list;
$count = count($access_list);
for($i = 0; $i < $count; $i++)
if($access_list[$i] == $uid)
return true;
return false;
}
reader_init(); //RFID reader init
while(1)
{
if(reader_ISO14443A_is_present($uid))
{
if($pre_uid == $uid)
continue;
$pre_uid = $uid;
$uid = bin2hex($uid);
//lookup in access list
$result = access_list_look_up($uid);
if($result == false) //Not found in access list
{
echo "IoT Lock: Access is denied\r\n";
// TODO: add alert function here
}
else
{
echo "IoT Lock: Access is authorized, door is openning\r\n";
//TODO: open the door.
}
}
}
?>
IoT Lock
<task0.php>
PHP Code:
<?php
if(_SERVER("REQUEST_METHOD"))
exit; // avoid php execution via http request
include_once "/lib/sd_340.php";
include_once "/lib/sn_dns.php";
include_once "/lib/sn_mysql.php";
include_once "vd_pcd_pn532.php";
include_once "vd_mifare_classic.php";
define("PRIVILEGE_UNAUTHORIZED", 0);
define("PRIVILEGE_EMPLOYEE", 1);
define("PRIVILEGE_MANAGER", 2);
//Check and print error messages from DB server
function chk_error($result)
{
if($result !== false)
{
$error = mysql_error($result);
if(strlen($error) != 0)
echo "Error: $error\r\n";
}
}
//Enter your DB Server's hostname or IP address!
$server_addr = "192.168.0.3";
//Enter your account information!
$user_name = "your_username";
$password = "your_password";
$uid = "";
$pre_uid = "";
$door_id = "00000001"; // Change door id here.
$allow_privilege = PRIVILEGE_MANAGER; // mininum privilege level is required to open door. Change it according to each access permision of each door.
reader_init(); //RFID reader init
//Connect to DB Server
if(mysql_connect($server_addr, $user_name, $password))
{
$result = mysql_select_db("iot_lock");
chk_error($result);
}
while(1)
{
if(reader_ISO14443A_is_present($uid))
{
if($pre_uid == $uid)
continue;
$pre_uid = $uid;
$uid = bin2hex($uid);
/**
Note: In this code, I use Tag's UID as key ID.
To make it more flexible, You can wire your own design key ID to user memory.
And then read it to update to database as key ID.
**/
//Inquiry the last record
$result = mysql_query("SELECT * FROM tbl_key WHERE key_id='$uid';");
chk_error($result);
//get result of the inquiry
$result_arr = mysql_fetch_row($result);
if($result_arr === false) //Not found in database
{
echo "IoT Lock: Unknown key\r\n";
// TODO: add alert function here
continue;
}
$user_privilege = (int)$result_arr[1];
if($user_privilege < $allow_privilege)
echo "IoT Lock: Access is denied. The key doesn't have privilege\r\n";
else
{
//TODO: open the door.
echo "IoT Lock: Access is authorized, door is openning\r\n";
//create a history record
$result = mysql_query("INSERT INTO tbl_history(key_id, door_id, date_time) VALUES ('$uid', '$door_id', NOW());");
chk_error($result);
}
}
}
mysql_close();
?>
Database design
For the sake of simplicity, I design only two simple tables in database without any FOREIGN KEY constraint.
- Key table: to store key id and privilege. Key id in this example has a dual role: key identification and user identification. (It had better to divide this table into key table and user table). The privilege is to specify
- -|----Field-----|-----Type----------|
- | key_id | VARCHAR(20) |
- | privilege | INTEGER |
- History table: to keep history of opening door.
- -|----Field-----|-----Type----------|
- | index_ | INTEGER |
- | key_id | VARCHAR(20) |
- | door_id | VARCHAR(20)|
- | date_time |DATETIME |
Mysql script for creating database and tables.
Code:
CREATE DATABASE iot_lock; USE iot_lock; CREATE TABLE tbl_key (key_id VARCHAR(20) NOT NULL PRIMARY KEY, privilege INTEGER NOT NULL); CREATE TABLE tbl_history (index_ INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, key_id VARCHAR(20) NOT NULL, door_id VARCHAR(20) NOT NULL, date_time DATETIME(0) NOT NULL);
Mysql script for adding the key. In my case, I have two keys:
- a RFID tag with UID: FE65B0AB is set as a key of manager (privilege = 2)
- a RFID tag with UID: BD1E1D00 is set as a key of normal employee (privilege = 1)
Code:SET @key_id='FE65B0AB', @privilege=2; /*This is a key of manager. change it according to UID of your card */ INSERT INTO tbl_key (key_id, privilege) VALUES (@key_id, @privilege); SET @key_id='BD1E1D00', @privilege=1; /*This is a key of normal employee. change it according to UID of your card */ INSERT INTO tbl_key (key_id, privilege) VALUES (@key_id, @privilege);
Libraries
- Mysql library: Official Library of PHPoC at https://github.com/phpoc/psp
- PN532 library at: https://forum.phpoc.com/blogs/khanh-...-reader-writer
If you have any questions or something to discuss, don’t hesitate to leave a comment!