הקדמה קצרה
בית חכם הופך נפוץ יותר ויותר עם התפתחות הטכנולוגיה, מאמר זה יתמקד בהיבטי האבטחה של פרויקט בקרת הגישה החכמה.
מאמר זה משתמש מסך המגע של STONE לשלוח פקודות ל-MCU כדי לשלוט בממסר ובמודול MFRC522.
העיקרון של קריאת כרטיסים: על ידי הפעלת מודול RFID-RC522, זהה את מזהה תעודת הזהות קרוב לתעודת הזהות, ולאחר מכן קבע אם המזהה קיים במסד הנתונים של המילה טיפוסית, ID הוא הערך הטיפוסי של המילה, אם קיומו של האימות באמצעות , ולאחר מכן הדפס את השם המתאים, ולאחר מכן הניע את המנעול האלקטרומגנטי באותו אופן.
חומרים נדרשים
- ESP32
- מנעול אלקטרוני KOB
- ממסר
- תצוגת לוח מגע STONE STWI070WT-01
- מודול MFRC522
מימוש פונקציה
- רישום כרטיס.
- רישום שם משתמש וסיסמה.
- החלק את הכרטיס כדי לפתוח את הנעילה האלקטרונית.
- שם משתמש וסיסמה לפתיחת המנעול האלקטרוני.
תיאור החומרה העיקרי
מודול RFID
ניתן לטעון מודול זה ישירות לתוך מודולי קורא שונים. הוא משתמש במתח של 3.3V, דרך ממשק SPI עם רק כמה חוטים. מחובר ישירות ללוח אם של מעבד, המודול יכול לעבוד בצורה יציבה ואמינה כקורא כרטיסי מרחק.
ה-STWI070WT-01 הוגה כצג TFT ובקר מגע. הוא כולל מעבד, תוכנית בקרה, דרייבר, זיכרון פלאש, יציאת RS232/RS422/RS485/TTL/LAN, Wi-Fi/Bluetooth, מסך מגע, ספק כוח וכו', כך שזו מערכת תצוגה שלמה המבוססת על העוצמה והקלה. מערכת הפעלה, הניתנת לשליטה על ידי כל MCU.
עיצוב GUI
שיתוף קוד
ייבוא mfrc522
זמן יבוא
ייבוא _thread
מ-os import uname
מ-PIN של ייבוא מכונה, UART
#from pyb ייבוא UART
#מכונת יבוא
suos = Pin(32,Pin.OUT)
uart2 = UART(2, baudrate=115200, rx=16,tx=17, timeout=10)
ESP32_HSPI_CLOCK = 14
ESP32_HSPI_SLAVE_SELECT = 15
ESP32_HSPI_MISO = 12
ESP32_HSPI_MOSI = 13
ESP32_MFRC522_RST = 5
rx3 = []
rx_name = []
user_id_flag = False
password_flag = False
temp_id = ”
temp_mima = ”
personnel_id = {'zbw':[236,230,169,47],'lbw':[19,165,93,4]}
personnel_ps = {'zbw':'zbw3366′,'lbw':'lbwnb'}
admin_password = ('yyds')
button_cmd = [16,1]
edit1_cmd = [16,112]
edit2_cmd = [16,113]
edit3_cmd = [16,114]
if uname()[0] == 'esp32':
rdr = mfrc522.MFRC522(ESP32_HSPI_CLOCK, ESP32_HSPI_MOSI, ESP32_HSPI_MISO, ESP32_MFRC522_RST, ESP32_HSPI_SLAVE_SELECT)
def do_write():
נסה:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
print ("כרטיס חדש זוהה")
print(" – סוג תג: 0x%02x" % tag_type)
print(" – uid : 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
הדפס("")
if rdr.select_tag(raw_uid) == rdr.OK:
key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK:
stat = rdr.write(8, b”\x00\x53\x00\x54\x00\x4F\x00\x4E\x00\x45\x0a\x0b\x0c\x0d\x0e\x0f”)
rdr.stop_crypto1()
if stat == rdr.OK:
print ("הנתונים נכתבו לכרטיס")
else
print ("נכשל לכתוב נתונים לכרטיס")
else
print ("שגיאת אימות")
else
print("בחירת התג נכשלה")
למעט KeyboardInterrupt:
print ("שגיאת כתיבה")
def do_read():
בעוד נכון:
נסה:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
print ("כרטיס חדש זוהה")
print(" – סוג תג: 0x%02x" % tag_type)
print(" – uid : 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
הדפסה (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])
הדפס("")
if rdr.select_tag(raw_uid) == rdr.OK:
key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK:
print("נתוני כתובת 8: %s" % rdr.read(8))
עבור ps ב-personnel_id:
if raw_uid[0:4:1] == personnel_id.get(ps):
suos.value(1)
print(ps)
uart_write(ps, *raw_uid[0:4:1])
זמן. שינה (3)
uart2.sendbreak()
לשבור
rdr.stop_crypto1()
זמן. שינה (3)
suos.value(0)
else
print ("שגיאת אימות")
else
print("בחירת התג נכשלה")
if uart2.any()>1:
rx2 = []
data_name2 = ”
bin_data = uart2.read(40)
uart2.sendbreak()
rx1 = list(bin_data)
עבור פריט ב-rx1:
rx2.append(chr(item))
print(rx2)
if rx1[3:5:1] == button_cmd:
data_name_len = rx1[6] – 1
data_name = rx2[7:data_name_len+7:1]
data_name2 = ”.join(data_name)
print(data_name2)
if data_name2 == 'back3':
לַחֲזוֹר
למעט KeyboardInterrupt:
print ("שגיאת קריאה")
def do_read2 (idd):
print(idd)
בעוד נכון:
נסה:
(stat, tag_type) = rdr.request(rdr.REQIDL)
if stat == rdr.OK:
(stat, raw_uid) = rdr.anticoll()
if stat == rdr.OK:
print ("כרטיס חדש זוהה")
print(" – סוג תג: 0x%02x" % tag_type)
print(" – uid : 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
הדפסה (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])
הדפס("")
if rdr.select_tag(raw_uid) == rdr.OK:
key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK:
print("נתוני כתובת 8: %s" % rdr.read(8))
personnel_id[idd] = raw_uid[0:4:1]
uart_write3(*raw_uid[0:4:1])
rdr.stop_crypto1()
else
print ("שגיאת אימות")
else
print("בחירת התג נכשלה")
if uart2.any()>1:
rx2 = []
data_name2 = ”
bin_data = uart2.read(40)
uart2.sendbreak()
rx1 = list(bin_data)
עבור פריט ב-rx1:
rx2.append(chr(item))
if rx1[3:5:1] == button_cmd:
data_name_len = rx1[6] – 1
data_name = rx2[7:data_name_len+7:1]
data_name2 = ”.join(data_name)
print(data_name2)
if data_name2 == 'back1':
לַחֲזוֹר
למעט KeyboardInterrupt:
print ("שגיאת קריאה")
def uart_write(טקסט, *ids):
# print(טקסט, *ID)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardname1″,”text”:”'+str(text)+'”}>ET' )
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid1″,”text”:”'+str(ids)+'”}>ET' )
uart2.write('ST<{“cmd_code”:”set_visible”,”type”:”widget”,,”widget”:”lock1″,”visible”:true}>ET')
זמן. שינה (3)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardname1″,”text”:”””}>ET')
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid1″,”text”:”””}>ET')
uart2.write('ST<{“cmd_code”:”set_visible”,,”type”:”widget”,,”widget”:”lock1″,”visible”:false}>ET')
def uart_write2(text,text2):
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid”,,”text”:”'+text+'”}>ET')
זמן. שינה (3)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid”,,”text”:”'+text2+'”}>ET')
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”edit2″,”text”:”””}>ET')
def uart_write3(*id2):
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid”,,”text”:”'+str(id2)+'”}>ET' )
זמן. שינה (3)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid”,,”text”:”””}>ET')
def uart_write4(text,text2):
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”login”,,”text”:”'+text+'”}>ET')
זמן. שינה (1)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”login”,,”text”:”'+text2+'”}>ET')
זמן. שינה (1)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”edit3″,”text”:”””}>ET')
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”edit4″,”text”:”””}>ET')
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”edit7″,”text”:”””}>ET')
def uart_write5():
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid”,,”text”:”'+str(id2)+'”}>ET' )
זמן. שינה (3)
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”cardid”,,”text”:”””}>ET')
def card_zhuce():
בעוד נכון:
if uart2.any():
user_id = ”
סיסמה = ”
rx2 = []
rx_num = 0
bin_data = uart2.read(40)
uart2.sendbreak()
rx1 = list(bin_data)
עבור פריט ב-rx1:
rx2.append(chr(item))
rx_num += 1
data_end = rx_num-5
data_id_st = rx2[8:13:1]
data_id_st2 = ”.join(data_id_st)
print(data_id_st2)
if data_id_st2 == 'edit1':
data_id_st3 = rx2[15:data_end:1]
data_id_st4 = ”.join(data_id_st3)
print(data_id_st4)
if data_id_st4 != ”:
שם = נכון
elif data_id_st2 == 'edit2':
data_id_st5 = rx2[15:data_end:1]
data_id_st6 = ”.join(data_id_st5)
if data_id_st6 == admin_password:
admin = נכון
uart_write2('האימות עבר!','אנא הנח את הכרטיס!')
do_read2(data_id_st4)
לַחֲזוֹר
def mima_zuce():
temp_id3 = ”
temp_mima3 = ”
בעוד נכון:
if uart2.any():
user_id = ”
סיסמה = ”
rx2 = []
rx_num = 0
# data_end = 0
bin_data = uart2.read(40)
uart2.sendbreak()
rx1 = list(bin_data)
עבור פריט ב-rx1:
rx2.append(chr(item))
rx_num += 1
# if (rx2[rx_num] == 'T') ו-(rx2[rx_num-1] == 'E') ו-(rx2[rx_num-2] == '>'):
# לשבור
data_end = rx_num-5
data_id_st = rx2[8:13:1]
data_id_st2 = ”.join(data_id_st)
print(data_id_st2)
if rx1[3:5:1] == button_cmd:
data_name_len = rx1[6] – 1
data_name = rx2[7:data_name_len+7:1]
data_name2 = ”.join(data_name)
print(data_name2)
if data_name2 == 'back2':
לַחֲזוֹר
if data_id_st2 == 'edit3':
data_id_st3 = rx2[15:data_end:1]
data_id_st4 = ”.join(data_id_st3)
print(data_id_st4)
user_id_flag = נכון
temp_id3 = data_id_st4
# personnel_ps[temp_id] = raw_uid[0:4:1]
elif data_id_st2 == 'edit4':
data_id_st5 = rx2[15:data_end:1]
data_id_st6 = ”.join(data_id_st5)
print(data_id_st6)
# if personnel_ps.get(temp_id) == data_id_st6:
password_flag = נכון
temp_mima3 = data_id_st6
# personnel_ps[temp_id] = password_flag
# print(rx2,user_id_flag,password_flag)
elif data_id_st2 == 'edit7':
data_id_st5 = rx2[15:data_end:1]
data_id_st6 = ”.join(data_id_st5)
if (data_id_st6 == admin_password) ו-(password_flag == True) ו- (user_id_flag == True):
admin = נכון
personnel_ps[temp_id3] = temp_mima3
password_flag = False
user_id_flag = False
uart_write4('האימות עבר!','הכניסה הצליחה!')
def password_loin():
temp_id2 = ”
temp_mima = ”
בעוד נכון:
if uart2.any():
user_id = ”
סיסמה = ”
rx2 = []
rx_num = 0
# data_end = 0
bin_data = uart2.read(40)
uart2.sendbreak()
rx1 = list(bin_data)
עבור פריט ב-rx1:
rx2.append(chr(item))
rx_num += 1
# if (rx2[rx_num] == 'T') ו-(rx2[rx_num-1] == 'E') ו-(rx2[rx_num-2] == '>'):
# לשבור
data_end = rx_num-5
data_id_st = rx2[8:13:1]
data_id_st2 = ”.join(data_id_st)
print(data_id_st2)
if rx1[3:5:1] == button_cmd:
data_name_len = rx1[6] – 1
data_name = rx2[7:data_name_len+7:1]
data_name2 = ”.join(data_name)
print(data_name2)
if data_name2 == 'back4':
לַחֲזוֹר
if data_id_st2 == 'edit5':
data_id_st3 = rx2[15:data_end:1]
data_id_st4 = ”.join(data_id_st3)
print(data_id_st4)
if data_id_st4 ב-personnel_ps:
user_id_flag = נכון
temp_id2 = data_id_st4
elif data_id_st2 == 'edit6':
data_id_st5 = rx2[15:data_end:1]
data_id_st6 = ”.join(data_id_st5)
print(data_id_st6)
print(temp_id2)
print(personnel_ps)
if personnel_ps.get(temp_id2) == data_id_st6:
password_flag = נכון
# print(rx2,user_id_flag,password_flag)
print(user_id_flag,password_flag)
if (password_flag == True) ו- (user_id_flag == True):
uart_write(temp_id2,temp_id2)
password_flag = False
user_id_flag = False
suos.value(1)
uart2.write('ST<{“cmd_code”:”set_visible”,”type”:”widget”,,”widget”:”lock2″,”visible”:true}>ET')
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”edit5″,”text”:”””}>ET')
uart2.write('ST<{“cmd_code”:”set_text”,,”type”:”label”,,”widget”:”edit6″,”text”:”””}>ET')
זמן. שינה (3)
# uart_write('סטודנט',")
suos.value(0)
uart2.write('ST<{“cmd_code”:”set_visible”,,”type”:”widget”,,”widget”:”lock2″,”visible”:false}>ET')
uart2.sendbreak()
בעוד נכון:
if uart2.any()>1:
rx2 = []
data_name2 = ”
bin_data = uart2.read(40)
# time.sleep(1)
uart2.sendbreak()
# time.sleep(1)
rx1 = list(bin_data)
עבור פריט ב-rx1:
rx2.append(chr(item))
print(rx2)
if rx1[3:5:1] == button_cmd:
data_name_len = rx1[6] – 1
data_name = rx2[7:data_name_len+7:1]
data_name2 = ”.join(data_name)
print(data_name2)
if data_name2 == 'כרטיס1':
card_zhuce()
elif data_name2 == 'סיסמה1':
mima_zuce()
elif data_name2 == 'כרטיס2':
do_read()
elif data_name2 == 'סיסמה2':
password_loin()
MFRC522.py
מייבוא מכונה Pin, SPI
מ-os import uname
מחלקה MFRC522:
בסדר = 0
NOTAGERR = 1
ERR = 2
REQIDL = 0x26
REQALL = 0x52
AUTHENT1A = 0x60
AUTHENT1B = 0x61
def __init__(self, sck, mosi, miso, rst, cs):
self.sck = Pin(sck, Pin.OUT)
self.mosi = Pin(mosi, Pin.OUT)
self.miso = Pin(miso)
self.rst = Pin(rst, Pin.OUT)
self.cs = Pin(cs, Pin.OUT)
self.rst.value(0)
self.cs.value(1)
board = uname()[0]
אם לוח == 'WiPy' או לוח == 'LoPy' או לוח == 'FiPy':
self.spi = SPI(0)
self.spi.init(SPI.MASTER, baudrate=1000000, pins=(self.sck, self.mosi, self.miso))
elif board == ‘esp32’:
self.spi = SPI(baudrate=100000, polarity=0, phase=0, sck=self.sck, mosi=self.mosi, miso=self.miso)
self.spi.init()
else
raise RuntimeError ("פלטפורמה לא נתמכת")
self.rst.value(1)
self.init()
def _wreg(self, reg, val):
self.cs.value(0)
self.spi.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))))
self.spi.write(b'%c' % int(0xff & val))
self.cs.value(1)
def _rreg(self, reg):
self.cs.value(0)
self.spi.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80)))
val = self.spi.read(1)
self.cs.value(1)
ערך החזרה[0]
def _sflags(self, reg, mask):
self._wreg(reg, self._rreg(reg) | mask)
def _cflags(self, reg, mask):
self._wreg(reg, self._rreg(reg) & (~mask))
def _tocard(self, cmd, send):
recv = []
סיביות = irq_en = wait_irq = n = 0
stat = self.ERR
אם cmd == 0x0E:
irq_en = 0x12
wait_irq = 0x10
elif cmd == 0x0C:
irq_en = 0x77
wait_irq = 0x30
self._wreg(0x02, irq_en | 0x80)
self._cflags(0x04, 0x80)
self._sflags(0x0A, 0x80)
self._wreg(0x01, 0x00)
עבור c בשלח:
self._wreg(0x09, c)
self._wreg(0x01, cmd)
אם cmd == 0x0C:
self._sflags(0x0D, 0x80)
i = 2000
בעוד נכון:
n = self._rreg(0x04)
אני -= 1
אם ~((i != 0) ו-~(n & 0x01) ו-~(n & wait_irq)):
לשבור
self._cflags(0x0D, 0x80)
אם אני:
if (self._rreg(0x06) & 0x1B) == 0x00:
stat = עצמי.בסדר
if n & irq_en & 0x01:
stat = עצמי.NOTAGERR
elif cmd == 0x0C:
n = self._rreg(0x0A)
lbits = self._rreg(0x0C) & 0x07
אם לביט != 0:
סיביות = (n – 1) * 8 + לביט
else
סיביות = n * 8
אם n == 0:
n = 1
elif n > 16:
n = 16
עבור _ בטווח(n):
recv.append(self._rreg(0x09))
else
stat = self.ERR
החזר נתונים, recv, ביטים
def _crc(עצמי, נתונים):
self._cflags(0x05, 0x04)
self._sflags(0x0A, 0x80)
עבור c בנתונים:
self._wreg(0x09, c)
self._wreg(0x01, 0x03)
i = 0xFF
בעוד נכון:
n = self._rreg(0x05)
אני -= 1
אם לא ((i != 0) ולא (n & 0x04)):
לשבור
החזר [self._rreg(0x22), self._rreg(0x21)]
def init(עצמי):
self.reset()
self._wreg(0x2A, 0x8D)
self._wreg(0x2B, 0x3E)
self._wreg(0x2D, 30)
self._wreg(0x2C, 0)
self._wreg(0x15, 0x40)
self._wreg(0x11, 0x3D)
self.antenna_on()
def reset (עצמי):
self._wreg(0x01, 0x0F)
def antenna_on(self, on=True):
אם פועל ו-~(self._rreg(0x14) ו-0x03):
self._sflags(0x14, 0x03)
else
self._cflags(0x14, 0x03)
def request (עצמי, מצב):
self._wreg(0x0D, 0x07)
(stat, recv, bits) = self._tocard(0x0C, [mode])
if (stat != self.OK) | (סיביות != 0x10):
stat = self.ERR
נתון החזרה, ביטים
def anticoll (עצמי):
ser_chk = 0
ser = [0x93, 0x20]
self._wreg(0x0D, 0x00)
(stat, recv, bits) = self._tocard(0x0C, ser)
if stat == self.OK:
if len(recv) == 5:
עבור i בטווח (4):
ser_chk = ser_chk ^ recv[i]
if ser_chk != recv[4]:
stat = self.ERR
else
stat = self.ERR
החזר נתונים, recv
def select_tag(self, ser):
buf = [0x93, 0x70] + ser[:5]
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
החזר self.OK if (stat == self.OK) ו-(bits == 0x18) else self.ERR
def auth(self, mode, addr, sect, ser):
return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0]
def stop_crypto1(self):
self._cflags(0x08, 0x08)
def read(self, addr):
נתונים = [0x30, addr]
data += self._crc(data)
(stat, recv, _) = self._tocard(0x0C, data)
return recv if stat == self.OK else None
def write(self, addr, data):
buf = [0xA0, addr]
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
אם לא (stat == self.OK) או לא (סיביות == 4) או לא ((recv[0] & 0x0F) == 0x0A):
stat = self.ERR
else
buf = []
עבור i בטווח (16):
buf.append(data[i])
buf += self._crc(buf)
(stat, recv, bits) = self._tocard(0x0C, buf)
אם לא (stat == self.OK) או לא (סיביות == 4) או לא ((recv[0] & 0x0F) == 0x0A):
stat = self.ERR
נתון החזרה
מקור: מודיעין נתונים אפלטון