طراحی وپیاده سازی سیستم احراز هویت مبتنی بر rfid

به نام خدا

موضوع پروژه:طراحی وپیاده سازی سیستم احراز هویت

علی فرجی

فرشیدحبیبی

ابزار مورد استفاده در پروژه

· breadboard

· NodeMcu

OLED

· buzzer

. LED

. RFID

: NodeMcu

یک پلت فرم اوپن سورس در زمینه‌ی IOT ( اینترنت اشیا یا به عبارت درست‌تر اینترنت چیزها) می‌باشد. هسته‌ی NodeMCU ، چیپ ESP8266 ورژن ESP12 می‌باشد که از WiFi پشتیبانی می‌کند و به وسیله‌ی آن می‌توان به شبکه‌ی وای فای متصل شد و اطلاعات را میان اینترنت یا سایر دستگاه‌ها جابه‌جا نمود. زبان برنامه‌نویسی این ماژول ، Lua می‌باشد. ولی از امکانات بسیار عالی این ماژول این است که می‌توان یا استفاده از IDE آردوینو و با استفاده از دستوارات آردوینو بر روی آن به سادگی برنامه نویسی کرد. NodeMCU یک پلت فرم اوپن سورس در زمینه‌ی IoT ( اینترنت اشیا یا به عبارت درست‌تر اینترنت چیزها) می‌باشد. هسته‌ی NodeMCU ، چیپ ESP8266 ورژن ESP12 می‌باشد که از WiFi پشتیبانی می‌کند و به وسیله‌ی آن می‌توان به شبکه‌ی وای فای متصل شد و اطلاعات را میان اینترنت یا سایر دستگاه‌ها جابه‌جا نمود. زبان برنامه‌نویسی این ماژول ، Lua می‌باشد. ولی از امکانات بسیار عالی این ماژول این است که می‌توان یا استفاده از IDE آردوینو و با استفاده از دستوارات آردوینو بر روی آن به سادگی برنامه نویسی کرد.



تنظیمات اولیه در Arduino IDE



صفحه setup و config

این صفحه دارای چند قسمت مجزا می باشد قسمت اول برای connect به wifi می باشد همانطور که در شکل زیر میبینیم میکروکنترولر ما می تواند چند حالت مختلف داشته باشد 1:station mode 2:AP_Mode 3: Multi_Mode که در حالت اول ما به عنوان کلاینت به منبع وصل می شویم در حالت دوم از میکروکنترولر به عنوان accesspoint استفاده می نماییم و در حالت سوم که حالت multi میباشد ما میکروکنترولر هم می تواند به صورت کلایت و هم accesspointعمل کند.

میکروکنترولر درون خود یک حافظه اسپیفس دارد که حجم ان 4مگابایت می باشد ما فایل های text را که در ادامه توضیح داده خواهد شد را با استفاده از نرم افزار winScp به حافظه ان با استفاده از FTP انتقال می دهیم حال با توجه به حالت های مختلف که میتواندقرار بگیرد به ان ip اختصاص می دهیم هنگام لود شدن صفحه برخی توابع همزمان با ان اجرا می شوند.

=loading_scripts;

function loading_scripts(){

processwificonfig();

processnetworkconfig();

processauthconfig();

}

ابتدا تابع processwificonfig(); اجرا می شود که به صورت زیر می باشد.

function processwificonfig(){

reqwifi.open("POST", "/WIFI.TXT", true);

reqwifi. = responsewifi;

reqwifi.send();

در این تابع یک تابع دیگر به نام responsewifi فراخوانده می شودکه این تابع یک شی ایجاد کرده و از طریق JSON اطلاعات موجود در فایل WIFI.TEX که درون حافظه اسپیفس ما موجود است را پارس کرده و ان ها را داخل textbox ها قرار می دهد.

function responsewifi(){

if (this.readyState == 4 && this.status ==200){

myObj = JSON.parse(this.responseText);

document.getElementById("SSID").value = myObj.SSID;

document.getElementById("presharedkey").value = myObj.presharedkey;

document.getElementById("APname").value = myObj.APname;

document.getElementById("APsharedkey").value = myObj.APsharedkey;

var wifimodes = myObj.wifimode;

if(wifimodes == "WIFI_STA"){document.getElementById("stationbt").checked = true;}

if(wifimodes == "WIFI_AP"){document.getElementById("APbt").checked = true;}

if(wifimodes == "WIFI_AP_STA"){document.getElementById("multibt").checked = true;}

}

}

دکمه SCAN NETWORK برای پیدا کردن AP ها موجود می باشد هنگامی که دکمه زده می شود باید تمام AP های که از قبل موجود بودند باید حذف شوند بر ای این کار از تابع removeOptions() استفاده میکنیم که به صورت زیر می باشد

function removeOptions()

{

var i;

for(i = combo.options.length - 1 ; i >= 0 ; i--)

{

combo.remove(i);

}

processscan();}

در انتهای این تابع, تابع processscan()فراخوانده می شود که درون ان تابع Responsscan فراخوانی میشود از ap های که در دسترس هستند را در combobox نمایش می دهند

function processscan(){

reqscan.open("POST", "/scan", true);

reqscan. = responsescan;

reqscan.send();

}

function responsescan(){

if (this.readyState == 4 && this.status ==200){

myObj = JSON.parse(this.responseText);

for ( i=0; i < myObj.stations.length; i++){

var option = document.createElement("option");

option.value = myObj.stations[i];

option = myObj.stations[i];

combo(option);

}

document.getElementById("SSID").value = myObj.stations[0];

document.getElementById("presharedkey").value = myObj.presharedkey;

}

}

حال به قسمت دوم save network setup می پردازیم در این قسمت می خواهیم انتخاب کنبم که ایا میخواهیم ip اتوماتیک بدیم که این از طریق dhcp سروری که داخل میکروکنترولر وجود دارد انجام می شود یا اینکه به صورت استاتیک ip تخصیص دهیم.

که برای این قسمت تابع processnetworkconfig();هنگام لود شدن صفحه فراخوانی می شودکه اطلاعات را از فایل NET.TXT خوانده و توسط یک تابع دیگر ان را پارس می کند و مقدار هایی را که پارسر کرده را درون المنت هاقرار می دهد.

function responsenetwork(){

if (this.readyState == 4 && this.status ==200){

myObj = JSON.parse(this.responseText);

document.getElementById("IP").value = myObj.IP

document.getElementById("SUBNET").value = myObj.SUBNET;

document.getElementById("GATEWAY").value = myObj.GATEWAY;

document.getElementById("DNS").value = myObj.DNS;

var dhcp=myObj.DHCP;

if (dhcp == "on"){

document.getElementById("DHCP").checked = true;

}

}

}

function processnetworkconfig(){

reqnet.open("POST", "/NET.TXT", true);

reqnet. = responsenetwork;

reqnet.send();

}

قسمت سوم و چهارم در این قسمت ها ما می توانیم برای امنیت بیشتر یک صفحه لاگین مانند درست کنیم که وقتی برای اولین بار می خواهیم ورود کنیم باید user و password را وارد کنیم قسمت چهارم برای ریستارت کردن برنامه به کار می رود که برایما دو انتخاب وجود 1.بازگشت به حالت اولیه 2.شروع مجدد

حال به قسمت ARDUINO ان می رسیم کتاب خانه هایی که میخواهیم از انها استفاده کنیم

#include <FS.h> حافظه اسپیفس

#include <ESP8266WiFi.h>

#include <ArduinoJson.h>

#include <ESP8266WebServer.h>

#include <ESP8266mDNS.h>

#include <DNSServer.h>

#include <Wire.h> ارتباط I2C

#include "SSD1306.h" راه اندازی OLED

#include <ESP8266FtpServer.h>

در ابتدای کار باید وب سرور DNSسرور FTP سرور خود را راه اندازی کنیم که برای انها پورت هابی را تخصیص می دهیم

ESP8266WebServer server(80);

const byte DNS_PORT = 53;

DNSServer dnsServer;

File myFile ;

FtpServer ftpSrv;

کدهایی که در اردوینو قرار می گیرند در یکی از دو قسمت setup و loop قرار میگیرند در قسمت setup حافظه اسپیفس راه اندازی می شود و تابع read_wifi_config() فراخوانده می شود اگر راه اندازی حافظه با مشکل روبه رو شود یک پیغام خطا دریافت می کنیم و پس از ان esp ما ریستارت می شود

display.display();

if (!SPIFFS.begin()) {

display.drawString(0, 26, "Faild!!check SPIFFS");

display.display();

delay(60000);

ESP.restart();

}

display.drawString(0, 26, "SPIFFS OK");

display.display();

delay(1000);

read_wifi_config();

در قسمت وب قسمت های داشتیم که هرکدام از انها دکمه مخصوص خود را داشتند هنگامی این دکمه ها زده شوند اطلاعاتی که داخل textboxها قرار گرفته در هر یک از فایل های مربوطه دخیره می شوند به کمک دستورات زیر این کار انجام می شود.

server.on("/wificonfig",wifi_config);

server.on("/networkconfig",network_config);

server.on("/authconfig",auth_config);

server.on("/scan",scan_wifi);

server.on("/command",Command);

server.on("/format",SPIFFS_format);

حال سراغ تابع read_wifi_config() می رویم این تابع مسول پارس کردن اطلاعاتی است که درون فایل های ما قرار گرفته اند پس به این ترتیب هنگامی که صفحه لود می شود توابعی که در قسمت وب تعریف شده اند از این مقدار ها استفاده می کنندین تابع اول سراغ فایل wifi.txt میرود اطلاعاتی که درون این فایل ذخیره شده اند درون یک متغییر ریخته می شود سپس یک شی از جنس json ساخته شده و اطلاعاتی که درون متغییر بود را به وسیله این شی پارس میشود

void read_wifi_config(){

myFile = SPIFFS.open("/WIFI.TXT","r");

config_str = myFile.readString();

DynamicJsonBuffer jsonBuffer1;

JsonObject& json1 = jsonBuffer1.parseObject(config_str);

format from string_str

wifi_Mode=json1["wifimode"].as<String>();

ssid=json1["SSID"] ;

presharedkey=json1["presharedkey"];

apname=json1["APname"];

apsharedkey=json1["APsharedkey"];

myFile.close();

بعد از اجرای این قسمت نوبت قسمت دوم میرسد که در این قسمت فایل net.txt خوانده شده و مانند بالا برای ان یک متغییر تعریف شده اطلاعات درون ان ریخته شده و به وسیله یک شی json پارس می شوند لازم به ذکر است که ip ها باید به صورت رشته ذخیره شود

myFile = SPIFFS.open("/NET.TXT","r");

config_str = myFile.readString();

DynamicJsonBuffer jsonBuffer2;

JsonObject& json2 = jsonBuffer2.parseObject(config_str);

DHCP = json2["DHCP"].as<String>();

IP_str = json2["IP"].as<String>();

SUBNET_str = json2["SUBNET"].as<String>();

GATEWAY_str = json2["GATEWAY"].as<String>();

DNS_str = json2["DNS"].as<String>();

myFile.close();

حال سراغ فایل AUTH.TXT رفته و همانند کارهایی که برای موارد بالا گفته شد براین هم انجام میشود ودر اخر تابع run_wifi() فراخوانی میشود

myFile = SPIFFS.open("/AUTH.TXT","r");

config_str = myFile.readString();

DynamicJsonBuffer jsonBuffer3;

JsonObject& json3 = jsonBuffer3.parseObject(config_str);

USER_str= json3["USER"].as<String>();

PASSWORD_str = json3["PASSWORD"].as<String>();

myFile.close()

run_wifi();

}

تابعrun_wifi() با استفاده از تابع string_to_ip() که در ادامه به می پردازیم ip های موجود را به رشته تبدیل می نمایید

void run_wifi(){

String_to_IP(IP_str,IP);

String_to_IP(SUBNET_str,SUBNET);

String_to_IP(GATEWAY_str,GATEWAY);

String_to_IP(DNS_str,DNS);

}

دلیل استفاده از تابع string_to_ip() به این صورت می باشدکه در اردوینو امکان ذخیره ip به طور مثال صورت 192.168.1.5 نداریم و باید به صورت 192,168,1,5 ذخیره شود که به کمک این تابع انجام می شود که به صورت زیر می باشد

void String_to_IP(String str,IPAddress& IP_addr)

{

int c1 = str.indexOf('.');

int c2 = str.indexOf('.',c1+1);

int c3 = str.indexOf('.',c2+1);

int ln = str.length();//last place to stop

IP_addr[0] = str.substring(0,c1).toInt();

IP_addr[1] = str.substring(c1+1,c2).toInt();

IP_addr[2] = str.substring(c2+1,c3).toInt();

IP_addr[3] = str.substring(c3+1,ln).toInt();

}

در قسمت command گفته شد دو انتخاب داریم یکی بازشگت به حالت اولیه و ریستارت کردن میکروکنترور

اگر (بازگشت به حالت اولیه)default انتخاب شود به جز چند فیلد ,همه فیلد ها مقدار null را به خود میگیرند در غیر این صورت ریستارت می شود.

نحوه اتصال

سناریوکلی

در ابتدا قرار است که ما توسط ماژول rfid و nodemcu کارت های 13.56 مگاهرتز خود را بخوانیم بعد از خواندن nodemcu به فایل (برای مثال rfid.php) که درون اپاچی سرور قرار دارد وصل میشود که درخواست های rfid که شامل اطلاعات کارت (uid)میشودرا بگیرد پس بعد از خواندن کارت uid ان فرستاده میشود سپس چک می شود که وضعیت این uid در سرور به چه صورت است allow یا notallow یا تعریف نشده که این اطلاعات را به صورت json به nodemcu فرستاده می شود nodemcu اطلاعات فرستاده شده توسط سرور را میخواند اگر allow بود مثلا قفل برای ما باز می شود و لی اگر notallow بود باز نمیشود و همچنین اگر تعریف نشده باشدکار خود ادامه می دهد.در قسمت وب دو حالت normalmode و registermode را داریم هنگامی که گزینه registermode زده می شود یک پیغام xhttp به nodemcu فرستاده می شود سپس nodemcu فایل json را که از سرور گرفته به صفحه وب میفرستد اطلاعات فرستاده شده توسط صفحه خوانده می شود انها را درون عناصری که در صفحه می باشد را نمایش می دهد حال ما سه گزینه مختلف داریم ذخیره اطلاعات,حذف و بروز کردن اطلاعات کارت, برای مثال اگر ما گزینه ذخیره کردن را بزنیم اطلاعات به صورت xhttp و اژاکس به nodemcu فرستاده می شود سپس nodemcu به فایل (برای مثال register.php ) وصل شده تا اطلاعاتی که از برازر درریافت کردیم را به سرور بفرستد سپس uid ان چک شود اگر از قبل وجود داشته باشد از طریق nodemcu به برازر پیغام میدهد که این کارت از قبل وجود دارد در غیر ان صورت در سرور ذخیره شده و پیغام ذخیره کارت را به برازر می فرستد برای بروزرسانی و حذف نیز شیوه کار به همین صورت است فایل register.php علاوه بر اطلاعاتی که می فرستد یه جدولی هم همراه ان ارسال میشود که مشخصات کارت های موجود در سرور را نشان می دهد.حال برای ثبت کردن مثلا تاریخ باید روی normalmode قراربدیهم تا در سرور ذخیره شود.


لینکهای مفید:

آموزش مقدماتی جاوا اسکریپت و آموزش مقدماتی کاتلین را با کدایت شروع نمایید.