天刷到了一個(gè)這樣的短視頻,我尋思我是不是也可以寫一個(gè)類似的上課點(diǎn)名程序,想法經(jīng)不起等待,說寫就寫~
私信小編01即可獲取大量Python學(xué)習(xí)資源
Tkinter 是 python 內(nèi)置的 TK GUI 工具集。TK 是 Tcl 語言的原生 GUI 庫。作為 python 的圖形設(shè)計(jì)工具,它所使用的 Tcl 語言環(huán)境已經(jīng)完全嵌入到了 python 解釋器中。
我們使用Tkinter開發(fā)GUI界面。
PIL(Python Image Library)庫是Python語言的第三方庫,需要通過pip工具安裝。安裝PIL庫的方法如下,需要注意,安裝庫的名字是pillow。
PIL庫支持圖像儲(chǔ)存、顯示和處理,他能夠處理幾乎所有圖片格式,可以完成對(duì)圖像的縮放、剪裁、疊加以及向圖像添加線條、圖像和文字等操作。
使用PIL中的Image,ImageTk處理、引入一張圖片,可以使用下面代碼安裝一下。
pip install pillow
雙擊打開后,進(jìn)入軟件主界面,所有功能一目了然。程序會(huì)自動(dòng)識(shí)別軟件目錄下的names.txt,將里面的名字導(dǎo)入。
選擇順序點(diǎn)名后,點(diǎn)擊開始,屏幕上就開始滾動(dòng)出現(xiàn)人名,人名出現(xiàn)的概率是相同的,點(diǎn)擊停止,人名就停止?jié)L動(dòng),點(diǎn)名結(jié)束。
點(diǎn)擊隨機(jī)點(diǎn)名,程序就會(huì)進(jìn)行隨機(jī)點(diǎn)名,人名出現(xiàn)的概率是隨機(jī)的。
可以自己手動(dòng)選擇人名單,前提是人名單格式為txt,且每個(gè)名字占一行。
用Pyqt5也寫了一個(gè)版本,實(shí)現(xiàn)邏輯與TK版本相同,界面可能更好看了一些,但是文件大了許多,大家可以在后面總結(jié)部分自取。
import random
import re
import time
import threading
from tkinter import *
from tkinter import ttk
from base64 import b64decode
from PIL import Image,ImageTk
from tkinter import messagebox
from tkinter.filedialog import askopenfilename
""""
2021-11-10點(diǎn)名/抽獎(jiǎng)程序
主要亮點(diǎn):
1.兩種模式:
①順序點(diǎn)名
②隨機(jī)點(diǎn)名
2.自動(dòng)識(shí)別人名單
3.支持手動(dòng)導(dǎo)入人名單
4.人名單導(dǎo)入校驗(yàn)
5.人名顯示位置自動(dòng)矯正
6.最多顯示五個(gè)大字
"""
imgs=['./point_name.png']
class APP:
def __init__(self):
self.root = Tk()
self.running_flag=False #開始標(biāo)志
self.time_span=0.05 #名字顯示間隔
self.root.title('Point_name-V1.0')
width = 680
height = 350
left = (self.root.winfo_screenwidth() - width) / 2
top = (self.root.winfo_screenheight() - height) / 2
self.root.geometry("%dx%d+%d+%d" % (width, height, left, top))
self.root.resizable(0,0)
self.create_widget()
self.set_widget()
self.place_widget()
self.root.mainloop()
def create_widget(self):
self.label_show_name_var=StringVar()
self.label_show_name=ttk.Label(self.root,textvariable=self.label_show_name_var,font=('Arial', 100,"bold"),foreground = '#1E90FF')
self.btn_start=ttk.Button(self.root,text="開始",)
self.btn_load_names=ttk.Button(self.root,text="手動(dòng)加載人名單",)
self.lf1=ttk.LabelFrame(self.root,text="點(diǎn)名方式")
self.radioBtn_var=IntVar()
self.radioBtn_var.set(1)
self.radioBtn_sequence=ttk.Radiobutton(self.lf1,text="順序點(diǎn)名",variable=self.radioBtn_var, value=1)
self.radioBtn_random=ttk.Radiobutton(self.lf1,text="隨機(jī)點(diǎn)名",variable=self.radioBtn_var, value=2)
self.label_show_name_num=ttk.Label(self.root,font=('Arial', 20),foreground = '#FF7F50')
paned = PanedWindow(self.root)
self.img = imgs
img_=b'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'
the_img = b64decode(img_)#將圖片硬編碼到GUI
paned.image = ImageTk.PhotoImage(data=the_img)
self._img = Label(self.root, image=paned.image,background='black')
def set_widget(self):
default_name_="會(huì)是誰?"
self.label_show_name_var.set(default_name_)
self.label_show_name_adjust(default_name_)
self.btn_start.config(command=lambda :self.thread_it(self.start_point_name))
self.btn_load_names.config(command=self.load_names)
init_names=self.load_names_txt("./names.txt")
self.root.protocol('WM_DELETE_WINDOW',self.quit_window)
self.root.bind('<Escape>',self.quit_window)
if init_names:
self.default_names=init_names #1.文件存在但是無內(nèi)容。2.文件不存在
self.label_show_name_num.config(text=f"一共加載了{(lán)len(self.default_names)}個(gè)姓名")
else:
self.btn_start.config(state=DISABLED)
self.label_show_name_num.config(text=f"請(qǐng)先手動(dòng)導(dǎo)入人名單!")
def place_widget(self):
self.lf1.place(x=300,y=160,width=250,height=50)
self.radioBtn_sequence.place(x=20,y=0)
self.radioBtn_random.place(x=150,y=0)
self.btn_start.place(x=300,y=220,width=100,height=30)
self.btn_load_names.place(x=450,y=220,width=100,height=30)
self._img.place(x=90, y=165, height=120, width=180)
self.label_show_name_num.place(x=300,y=260)
def label_show_name_adjust(self,the_name):
if len (the_name)==1:
self.label_show_name.place(x=280, y=10)
elif len(the_name) == 2:
self.label_show_name.place(x=180, y=10)
elif len(the_name) == 3:
self.label_show_name.place(x=120, y=10)
elif len(the_name) == 4:
self.label_show_name.place(x=80, y=10)
else:
self.label_show_name.place(x=0, y=10)
def start_point_name(self):
"""
啟動(dòng)之前進(jìn)行判斷,獲取點(diǎn)名模式
:return:
"""
if len(self.default_names)==1:
messagebox.showinfo("提示",'人名單就一個(gè)人,不用選了!')
self.label_show_name_var.set(self.default_names[0])
self.label_show_name_adjust(self.default_names[0])
return
if self.btn_start["text"]=="開始":
self.btn_load_names.config(state=DISABLED)
self.running_flag=True
if isinstance(self.default_names,list):
self.btn_start.config(text="就你了")
if self.radioBtn_var.get()==1:
mode="sequence"
elif self.radioBtn_var.get()==2:
mode="random"
else:
pass
self.thread_it(self.point_name_begin(mode))
else:
messagebox.showwarning("警告","請(qǐng)先導(dǎo)入人名單!")
else:
self.running_flag=False
self.btn_load_names.config(state=NORMAL)
self.btn_start.config(text="開始")
def point_name_begin(self,mode):
"""
開始點(diǎn)名,點(diǎn)名主函數(shù)
:param mode:
:return:
"""
if mode == "sequence":
if self.running_flag:
self.always_ergodic()
elif mode=="random":
while True:
if self.running_flag:
random_choice_name=random.choice(self.default_names)
self.label_show_name_var.set(random_choice_name)
self.label_show_name_adjust(random_choice_name)
time.sleep(self.time_span)
else:
break
def always_ergodic(self):
"""
一直遍歷此列表,使用死循環(huán)會(huì)造成線程阻塞
:return:
"""
for i in self.default_names:
if self.running_flag:
self.label_show_name_var.set(i)
self.label_show_name_adjust(i)
time.sleep(self.time_span)
if i==self.default_names[-1]:
self.always_ergodic()
else:
break
def load_names(self):
"""
手動(dòng)加載txt格式人名單
:return:
"""
filename = askopenfilename(
filetypes = [('文本文件', '.TXT'), ],
title = "選擇一個(gè)文本文件",
initialdir="./"
)
if filename:
names=self.load_names_txt(filename)
if names:
self.default_names=names
no_Chinese_name_num=len([n for n in names if not self.load_name_check(n)])
if no_Chinese_name_num==0:
pass
else:
messagebox.showwarning("請(qǐng)注意",f'導(dǎo)入名單有{no_Chinese_name_num}個(gè)不是中文名字')
self.label_show_name_num.config(text=f"一共加載了{(lán)len(self.default_names)}個(gè)姓名")
default_name_ = "會(huì)是誰?"
self.label_show_name_var.set(default_name_)
self.label_show_name_adjust(default_name_)
self.btn_start.config(state=NORMAL)
else:
messagebox.showwarning("警告","導(dǎo)入失敗,請(qǐng)檢查!")
def load_names_txt(self,txt_file):
"""
讀取txt格式的人名單
:param txt_file:
:return:
"""
try:
with open(txt_file,'r',encoding="utf-8")as f:
names=[name.strip() for name in f.readlines()]
if len(names)==0:
return False
else:
return names
except:
return False
def load_name_check(self,name):
"""
對(duì)txt文本中的人名進(jìn)行校驗(yàn)
中文漢字->True
非中文漢字->False
:param name:
:return:
"""
regex = r'[\u4e00-\u9fa5]+'
if re.match(regex,name):
return True
else:
return False
def thread_it(self,func,*args):
t=threading.Thread(target=func,args=args)
t.setDaemon(True)
t.start()
def quit_window(self,*args):
"""
程序退出觸發(fā)此函數(shù)
:param args:
:return:
"""
ret=messagebox.askyesno('退出','確定要退出?')
if ret:
self.root.destroy()
if __name__ == '__main__':
a=APP()
本次使用Tkinter開發(fā)了一款上課點(diǎn)名程序,此程序可以用于點(diǎn)名、抽獎(jiǎng)…代碼不到200行,程序簡(jiǎn)單又實(shí)用,主要有以下六個(gè)亮點(diǎn):
1.兩種模式:
2.自動(dòng)識(shí)別人名單
3.支持手動(dòng)導(dǎo)入人名單
4.人名單導(dǎo)入校驗(yàn)
5.人名顯示位置自動(dòng)矯正
6.最多顯示五個(gè)大字
微信小程序考勤簽到管理系統(tǒng)+后臺(tái)管理系統(tǒng)》該項(xiàng)目含有源碼、論文等資料、配套開發(fā)軟件、軟件安裝教程、項(xiàng)目發(fā)布教程等
本系統(tǒng)包含微信小程序做的考勤前臺(tái)和Java做的后臺(tái)管理系統(tǒng):
微信小程序——考勤前臺(tái)涉及技術(shù):WXML 和 WXSS、JavaScript
Java——考勤后臺(tái)涉及技術(shù):
前端使用技術(shù):JSP,HTML5,CSS3、JavaScript、jQuery、bootstrap等
后臺(tái)使用技術(shù):Spring、SpringMvc、Mybatis(SSM)等
數(shù)據(jù)庫:Mysql數(shù)據(jù)庫
前臺(tái)功能介紹:查看并搜索所有的學(xué)生信息,查看請(qǐng)假信息、簽到打卡、修改個(gè)人信息、登錄、注冊(cè)
后臺(tái)管理:登錄、請(qǐng)假的增刪改查、請(qǐng)假審核、匯報(bào)的增刪改查、簽到的增刪改查、學(xué)生的查詢刪除、 用戶的添加刪除修改、角色的添加刪除修改、菜單的添加刪除修改。
系統(tǒng)功能完整,適合作為畢業(yè)設(shè)計(jì)、課程設(shè)計(jì)、數(shù)據(jù)庫大作業(yè)。
下面是資料信息截圖:
下面是系統(tǒng)運(yùn)行起來后的一些截圖:
這個(gè)Raspberry Pi RFID考勤系統(tǒng)項(xiàng)目中,詳細(xì)記錄了如何利用RC522 RFID閱讀器搭建一個(gè)考勤打卡系統(tǒng)。
首先,展示如何將這些電路連接到Raspberry Pi的GPIO引腳,還將展示如何測(cè)試每個(gè)電路,使其正常工作。
然后,引導(dǎo)您完成建立數(shù)據(jù)庫的所有步驟,還將編寫Python腳本,與數(shù)據(jù)庫通信,為個(gè)人的RFID卡標(biāo)記考勤。
最后,設(shè)置一個(gè)簡(jiǎn)單的PHP腳本,讓你直觀地看到RFID考勤系統(tǒng)產(chǎn)生的數(shù)據(jù)。
在本教程中,有相當(dāng)多的工作要做,但一旦你完成了這個(gè)考勤系統(tǒng),你會(huì)非常有成就感。
要完成這個(gè)項(xiàng)目,你需要以下設(shè)備,點(diǎn)擊鏈接可直達(dá)特別優(yōu)惠購買。
1. 開始時(shí),首先要確保Raspbian安裝的所有東西都是最新的,在Raspberry Pi上運(yùn)行以下兩個(gè)命令。
sudo apt-get update
sudo apt-get upgrade
2. 現(xiàn)在,將安裝接下來幾節(jié)要依賴的所有包。
先運(yùn)行下面的命令安裝build-essential、git、python3-dev、python3-pip和python3-smbus。
sudo apt-get install build-essential git python3-dev python3-pip python3-smbus
1. 首先開始設(shè)置16×2的LCD,將快速運(yùn)行這一切的設(shè)置過程。如果你想了解更多的內(nèi)容,可以查看我的16×2液晶顯示器教程。
開始本教程之前,請(qǐng)確保已經(jīng)準(zhǔn)備好了以下元件。
2. 一旦有了所有所需的零件,就可以觀察下面的圖和步驟開始組裝電路。
如果按照我的指南將LCD連接到Raspberry Pi是一個(gè)非常簡(jiǎn)單的過程,每個(gè)連接的物理引腳號(hào)我都標(biāo)注了出來。
首先,把各種元件與面包板連接起來。
3. 現(xiàn)在開始將液晶顯示器連接到樹莓派上。
RFID考勤系統(tǒng)LCD布線圖
1. 現(xiàn)在電路已經(jīng)設(shè)置好了,讓去測(cè)試一下,以確保一切接線正確。
首先,克隆Adafruit CharLCD庫,將利用這個(gè)項(xiàng)目。如果顯示板使用的是HD44780控制器,那么它的工作就不會(huì)有問題。
要將庫到你的Raspberry Pi上,運(yùn)行以下命令。
git clone https://github.com/pimylifeup/Adafruit_Python_CharLCD.git
2. 現(xiàn)在將庫克隆到Raspberry Pi上,需要運(yùn)行安裝腳本。這個(gè)腳本將安裝這個(gè)庫,這樣任何Python腳本都可以利用它。
運(yùn)行以下兩個(gè)命令移動(dòng)到新克隆的目錄中,并運(yùn)行setup.py腳本。
cd ./Adafruit_Python_CharLCD
sudo python3 setup.py install
3. 在Raspberry Pi上安裝好庫后,需要編輯一個(gè)示例文件。需要這樣做來測(cè)試電路,因?yàn)槭褂玫囊_和例子中的不同。
通過運(yùn)行以下命令開始編輯文件。
nano ~/Adafruit_Python_CharLCD/examples/char_lcd.py
4. 在這個(gè)文件中,找到 "# Raspberry Pi引腳配置: "部分,并修改它,使其與我們下面的值一致。
# Raspberry Pi pin configuration:
lcd_rs = 4
lcd_en = 24
lcd_d4 = 23
lcd_d5 = 17
lcd_d6 = 18
lcd_d7 = 22
一旦做了修改,按CTRL + X,然后按Y,再按ENTER鍵保存文件。
5. 現(xiàn)在,在繼續(xù)運(yùn)行新修改的例子之前,需要安裝Raspberry Pi的GPIO Python庫。
要安裝所需的庫,請(qǐng)運(yùn)行以下命令。
sudo pip3 install RPi.GPIO
6. 為了測(cè)試一切是否正常,現(xiàn)在讓我們運(yùn)行下面的命令來運(yùn)行那個(gè)python腳本。如果一切正常,你現(xiàn)在應(yīng)該可以看到LCD上顯示的文字。
python3 ~/Adafruit_Python_CharLCD/examples/char_lcd.py
1. 現(xiàn)在已經(jīng)設(shè)置好了16×2的LCD顯示屏,現(xiàn)在將把RFID閱讀器添加到這個(gè)電路中。
對(duì)于本節(jié)RFID RC522的電路布線,需要準(zhǔn)備以下設(shè)備。
2. 一旦有了RFID電路所需的一切,就可以繼續(xù)進(jìn)行布線了,由于LCD電路已經(jīng)設(shè)置好了,所以會(huì)稍微復(fù)雜一些。
請(qǐng)注意,這個(gè)電路圖是假設(shè)您已經(jīng)按照上一節(jié)中的步驟來使用LCD顯示器。如果您沒有利用LCD,請(qǐng)確保您將Raspberry Pi上的物理引腳6連接到面包板上的地軌。
按照下面的圖示和步驟將RFID電路連接到樹莓派上。
RC522 RFID考勤系統(tǒng)接線圖譜
1. 現(xiàn)在RFID已經(jīng)連接到Raspberry Pi上,需要進(jìn)入raspi-config工具來啟用SPI接口。這個(gè)接口是必需的,這樣就可以和RC522模塊進(jìn)行通信。
要做到這一點(diǎn),首先運(yùn)行以下命令來啟動(dòng) raspi-config 工具。
sudo raspi-config
2. 運(yùn)行該命令后,會(huì)看到一個(gè)屏幕,顯示了可以配置的各種選項(xiàng)。
目前,我只對(duì)激活SPI接口感興趣。如果你想了解更多,可以查看我們的Raspi-Config工具的終極指南。
在這個(gè)屏幕上使用方向鍵向下選擇 "5個(gè)接口選項(xiàng)",然后按ENTER鍵。
3. 在下一個(gè)屏幕上,你要用方向鍵選擇 "P4 SPI "選項(xiàng),一旦選擇,按ENTER鍵。
4. 現(xiàn)在您需要確認(rèn)是否要啟用SPI接口。為此,您需要使用方向鍵選擇 "Yes",然后在選擇后按回車鍵。
5. 現(xiàn)在SPI接口應(yīng)該已經(jīng)成功啟用,您現(xiàn)在應(yīng)該看到屏幕上出現(xiàn) "The SPI interface is enabled "的文字。
現(xiàn)在在SPI接口完全啟用之前,我們需要重新啟動(dòng)Raspberry Pi。我們可以通過按ENTER鍵再按ESC鍵回到終端來實(shí)現(xiàn)。
輸入以下命令重新啟動(dòng)Raspberry Pi。
sudo reboot
6. 一旦Raspberry Pi完成重啟,您可以通過運(yùn)行以下命令來驗(yàn)證SPI接口是否已經(jīng)啟用。
該命令將檢索已啟用的內(nèi)核模塊列表,并從該列表中抓取任何包含 "spi "文字的模塊。
lsmod | grep spi
如果你看到命令行中出現(xiàn)了 "spi_bcm2835 "的文字,那么你現(xiàn)在就可以繼續(xù)測(cè)試電路是否正常工作了。完成后,我們就可以設(shè)置我們的RFID供電考勤系統(tǒng)了。
如果沒有出現(xiàn),那么我們建議您查看我們的RFID RC522設(shè)置指南,了解其他啟用正確內(nèi)核模塊的方法。
1. 現(xiàn)在使用下面的 "pip "命令將spidev庫安裝到Raspberry Pi上。
依靠spidev庫與RFID閱讀器接口進(jìn)行交互。
sudo pip3 install spidev
2. 現(xiàn)在已經(jīng)將spidev庫安裝到Raspberry Pi上,需要使用 "pip "命令來下載MFRC522庫。
這個(gè)庫將處理我們的RFID考勤系統(tǒng)的繁瑣工作。
sudo pip3 install mfrc522
3. 現(xiàn)在我們已經(jīng)將MFRC522庫和spidev庫安裝到了Raspberry Pi上,讓我們繼續(xù)制作一個(gè)目錄來保存我們的測(cè)試腳本。
mkdir ~/pi-rfid
4. 現(xiàn)在我們需要寫一個(gè)簡(jiǎn)短的腳本來測(cè)試我們的RC522是否真的能夠讀取RFID卡,以及所有的東西是否都正確地連接。
首先,讓我們通過運(yùn)行下面的命令來打開我們的新腳本,這將在我們最近創(chuàng)建的目錄中創(chuàng)建一個(gè)名為 "read.py "的文件。
nano ~/pi-rfid/read.py
5. 在這個(gè)文件中輸入以下幾行代碼。如果你想了解這里的所有內(nèi)容,那么我們建議查看我們關(guān)于RFID RC522的完整指南。
#!/usr/bin/env python
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
reader = SimpleMFRC522()
try:
id, text = reader.read()
print(id)
print(text)
finally:
GPIO.cleanup()
完成后,按CTRL + X然后按Y和ENTER鍵保存文件。
6. 現(xiàn)在,通過運(yùn)行以下腳本,并在閱讀器上點(diǎn)擊您的RFID芯片來測(cè)試RFID RC522。
python3 ~/pi-rfid/read.py
1. 現(xiàn)在設(shè)置了兩個(gè)電路,仔細(xì)檢查一切都在正常工作。通過運(yùn)行我們?cè)谇懊鎺坠?jié)中快速整理的測(cè)試腳本進(jìn)行測(cè)試。
如果您有問題,您可以將您的最終電路與下面的圖表進(jìn)行比較。這些圖是為了讓您了解最終的電路應(yīng)該是怎樣的。
RFID考勤系統(tǒng)電路原理圖
RFID考勤系統(tǒng)GPIO引腳的使用情況
1. 現(xiàn)在,在對(duì)RFID考勤系統(tǒng)進(jìn)行編程之前,必須首先準(zhǔn)備和建立MYSQL數(shù)據(jù)庫。這個(gè)數(shù)據(jù)庫是我們記錄每張RFID卡考勤情況以及誰擁有該RFID卡的地方。
您可以通過我們的MySQL教程和PHPMyAdmin指南來深入了解MYSQL的設(shè)置。我們的RFID考勤系統(tǒng)將引導(dǎo)您完成大部分的基礎(chǔ)知識(shí),但額外的指南將教您如何設(shè)置有用的工具,如PHPMyAdmin。
首先,通過在Pi上運(yùn)行以下命令將MYSQL安裝到Raspberry Pi上。
sudo apt-get install mysql-server -y
2. 接下來,我們需要運(yùn)行MYSQL自帶的 "安全安裝 "腳本。這個(gè)腳本將通過一些程序運(yùn)行,讓你的MYSQL服務(wù)器更加安全。
在Raspberry Pi的終端中運(yùn)行以下命令來運(yùn)行這個(gè)腳本。
sudo mysql_secure_installation
當(dāng)出現(xiàn)提示時(shí),請(qǐng)確保你為MYSQL服務(wù)器根目錄設(shè)置了一個(gè)新的密碼。此外,你應(yīng)該對(duì)大多數(shù)提示回答 "y",比如禁止root登錄訪問你的MYSQL服務(wù)器。
3. 現(xiàn)在讓我們通過運(yùn)行下面的命令加載到MYSQL命令行工具中。系統(tǒng)會(huì)提示你輸入上一步設(shè)置的密碼。
由于MariaDB在安裝時(shí)默認(rèn)使用UNIX_SOCKET作為認(rèn)證方式,所以我們需要使用超級(jí)用戶登錄,使用sudo來完成。
sudo mysql -u root -p
4. 讓我們先建立一個(gè)數(shù)據(jù)庫,我們將在這里存儲(chǔ)所有數(shù)據(jù),我們的RFID考勤系統(tǒng)將利用這些數(shù)據(jù)。
我們將把這個(gè)數(shù)據(jù)庫命名為" attendancesystem"。要?jiǎng)?chuàng)建這個(gè)數(shù)據(jù)庫,請(qǐng)運(yùn)行以下命令。
CREATE DATABASE attendancesystem;
5. 我們創(chuàng)建了數(shù)據(jù)庫,現(xiàn)在讓我們創(chuàng)建一個(gè)名為 "考勤管理員 "的用戶,我們將在Python腳本中利用這個(gè)用戶從我們新創(chuàng)建的數(shù)據(jù)庫中讀取數(shù)據(jù)。
確保你設(shè)置的密碼是獨(dú)特的和難以猜測(cè)的。在我們的例子中,我們將使用 "pimylifeup "作為密碼。
CREATE USER 'attendanceadmin'@'localhost' IDENTIFIED BY 'pimylifeup';
6. 現(xiàn)在我們已經(jīng)創(chuàng)建了我們的用戶,我們需要給它訪問 "考勤系統(tǒng) "數(shù)據(jù)庫的權(quán)限。
我們可以通過運(yùn)行以下命令來實(shí)現(xiàn)。這條命令將賦予我們的 "考勤管理員 "用戶在數(shù)據(jù)庫中任何表上的全部權(quán)限。
GRANT ALL PRIVILEGES ON attendancesystem.* TO 'attendanceadmin'@'localhost';
7. 在創(chuàng)建表之前,我們需要利用 "使用 "命令,這樣我們就可以直接與 "endanceystem "數(shù)據(jù)庫進(jìn)行交互。
通過運(yùn)行以下命令開始與數(shù)據(jù)庫進(jìn)行交互。
use attendancesystem;
8. 現(xiàn)在我們直接與我們想要利用的數(shù)據(jù)庫打交道,我們現(xiàn)在可以開始創(chuàng)建存儲(chǔ)所有數(shù)據(jù)的表。
運(yùn)行下面的兩個(gè)命令將創(chuàng)建我們將依賴的表來存儲(chǔ)數(shù)據(jù)。我們將在創(chuàng)建完這些表后解釋這些表的字段。
create table attendance(
id INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
user_id INT UNSIGNED NOT NULL,
clock_in TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ( id )
);
create table users(
id INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
rfid_uid VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ( id )
);
可以輸入exit離開MYSQL工具
現(xiàn)在已經(jīng)創(chuàng)建了表,來看看將存儲(chǔ)的數(shù)據(jù),以及如何在我們的腳本中使用它們。
對(duì)于考勤表,我們對(duì)每一個(gè)記錄的RFID tap都持有三條數(shù)據(jù)。
對(duì)于用戶表,我們?yōu)槊恳粋€(gè)添加的用戶保留四條數(shù)據(jù)。
1. 在開始編寫考勤系統(tǒng)腳本之前,我們首先需要用pip安裝Python "MYSQL連接器"。
在您的Pi上運(yùn)行以下命令來安裝連接器庫。
sudo pip3 install mysql-connector-python
2. 現(xiàn)在讓我們創(chuàng)建一個(gè)文件夾來保存這個(gè)項(xiàng)目的所有內(nèi)容。
mkdir ~/attendancesystem
3. 是時(shí)候開始為我們的考勤系統(tǒng)編寫第一個(gè)Python腳本了。這第一個(gè)腳本將允許你基于一個(gè)拍打的RFID卡來創(chuàng)建一個(gè)用戶。
點(diǎn)開RFID卡后,Python腳本會(huì)要求你輸入一個(gè)用戶名,將此卡注冊(cè)給一個(gè)人。
運(yùn)行以下命令,開始編寫我們考勤系統(tǒng)的第一部分。
nano ~/attendancesystem/save_user.py
4. 在這個(gè)新文件中寫下以下幾行代碼。我們將解釋每段代碼的作用,以及為什么我們要利用這些代碼。
#!/usr/bin/env python
我們添加這一行是為了讓操作系統(tǒng)知道這個(gè)文件應(yīng)該使用Python來執(zhí)行。
import time
我們導(dǎo)入時(shí)間庫,這樣就可以讓腳本進(jìn)入睡眠狀態(tài),所以事情不會(huì)瞬間發(fā)生。
import RPi.GPIO as GPIO
我們需要GPIO庫,這樣我們就可以在腳本結(jié)束時(shí)運(yùn)行清理功能。
from mfrc522 import SimpleMFRC522
SimpleMFRC522庫用于使其與我們的RFID閱讀器輕松對(duì)話。
import mysql.connector
我們利用MySQL連接器,這樣我們就可以和前面設(shè)置的數(shù)據(jù)庫對(duì)話。
import Adafruit_CharLCD as LCD
最后,我們載入Adafruit與LCD對(duì)話的庫。這個(gè)庫大大簡(jiǎn)化了我們與16×2顯示器的通信過程。
db = mysql.connector.connect(
host="localhost",
user="attendanceadmin",
passwd="pimylifeup",
database="attendancesystem"
)
在這部分代碼中,我們創(chuàng)建了與MYSQL服務(wù)器的連接。在這個(gè)函數(shù)中,我們傳遞了建立連接所需的所有信息,如主機(jī)、用戶、數(shù)據(jù)庫名稱和密碼。
連接器創(chuàng)建的對(duì)象存儲(chǔ)在db變量中,這樣我們就可以方便地與數(shù)據(jù)庫進(jìn)行交互。
在輸入該代碼時(shí),請(qǐng)確保將密碼替換為本指南前面為 "考勤管理員 "SQL用戶設(shè)置的密碼。
cursor = db.cursor()
在這里,我們從數(shù)據(jù)庫連接中實(shí)例化一個(gè)游標(biāo)對(duì)象的副本。我們利用這個(gè)對(duì)象與數(shù)據(jù)庫進(jìn)行交互,并執(zhí)行SQL查詢。
reader = SimpleMFRC522()
現(xiàn)在我們準(zhǔn)備SimpleMFRC522庫,將它實(shí)例化到我們的閱讀器對(duì)象中。這個(gè)庫將允許我們?cè)谏院蟮哪_本中輕松地與RC522對(duì)話,以讀取來自閱讀器的輸入。
lcd = LCD.Adafruit_CharLCD(4, 24, 23, 17, 18, 22, 16, 2, 4);
我們最后的設(shè)置行,這一行為CharLCD庫準(zhǔn)備處理16×2的顯示器。在這個(gè)函數(shù)中,我們輸入了所有需要的引腳數(shù),行數(shù)等。
try:
while True:
lcd.clear()
lcd.message('Place Card to\nregister')
id, text = reader.read()
這塊代碼是我們用戶創(chuàng)建邏輯的開始。我們將先用try:語句將整個(gè)邏輯包裝起來,我們將在后面的指南中解釋為什么。
我們還將我們的邏輯包裹在一個(gè)while True循環(huán)中。這個(gè)循環(huán)將確保下面的代碼會(huì)無限期地運(yùn)行,這樣最終用戶就可以連續(xù)注冊(cè)多個(gè)用戶。
接下來,在屏幕上寫下 "Place card to register"(放卡注冊(cè))之前,我們要清除每一個(gè)循環(huán)的LCD,以確保我們處理的是一個(gè)干凈的顯示器。這段文字提示用戶將他們的RFID卡放在閱讀器上。
最后,我們利用SimpleMFRC522庫來讀取閱讀器的輸入。這個(gè)函數(shù)會(huì)等到用戶將他們的RFID讀寫器放置好后才返回卡的id和存儲(chǔ)在卡上的文本。
cursor.execute("SELECT id FROM users WHERE rfid_uid="+str(id))
cursor.fetchone()
在本節(jié)中,我們使用游標(biāo)來執(zhí)行第一條SQL語句。在這條SQL語句中,我們只是簡(jiǎn)單的搜索 "用戶 "表,看看是否有任何行的RFID UID與我們讀取RFID卡時(shí)的ID相匹配。
為了抓取我們檢索到的數(shù)據(jù),我們利用游標(biāo)對(duì)象的另一個(gè)函數(shù),特別是fetchone()函數(shù)。這個(gè)函數(shù)將從返回的結(jié)果中抓取一條記錄。
if cursor.rowcount >= 1:
lcd.clear()
lcd.message("Overwrite\nexisting user?")
overwrite = input("Overwite (Y/N)? ")
if overwrite[0] == 'Y' or overwrite[0] == 'y':
lcd.clear()
lcd.message("Overwriting user.")
time.sleep(1)
sql_insert = "UPDATE users SET name = %s WHERE rfid_uid=%s"
else:
continue;
else:
sql_insert = "INSERT INTO users (name, rfid_uid) VALUES (%s, %s)"
在本節(jié)中,我們首先檢查上次SQL調(diào)用返回了多少條記錄。
如果SQL調(diào)用返回任何行,我們需要提示用戶是否要覆蓋已經(jīng)存在的用戶。
在if語句里面,我們繼續(xù)清除LCD屏幕,并顯示 "覆蓋現(xiàn)有用戶?"的信息,并在命令行中提供一個(gè)提示,讓用戶回復(fù)Y來覆蓋或其他任何東西來取消。
當(dāng)輸入函數(shù)收到輸入后,我們?cè)贆z查返回?cái)?shù)據(jù)的第一個(gè)字符是否等于'Y'或'y'。
如果第一個(gè)字符與我們預(yù)期的相同,我們就再次清除LCD。接下來,我們會(huì)顯示 "覆蓋用戶 "的信息一秒鐘。
最后,我們建立SQL查詢,用我們?cè)谙乱徊街付ǖ男旅Q更新現(xiàn)有條目。我們做這個(gè)過程,而不是刪除舊條目并重新添加。
如果用戶除了 "Y "和 "y "之外,對(duì)輸入函數(shù)沒有任何反應(yīng),我們就使用 "continue "跳回循環(huán)的開始。
如果這不是一個(gè)重復(fù)的條目,我們建立一個(gè)不同的SQL查詢,在 "用戶 "表中創(chuàng)建一個(gè)新條目。這個(gè)新條目將包含我們?cè)谙乱粋€(gè)代碼塊中指定的新名稱和用戶拍卡時(shí)獲得的RFID ID。
lcd.clear()
lcd.message('Enter new name')
new_name = input("Name: ")
cursor.execute(sql_insert, (new_name, id))
db.commit()
lcd.clear()
lcd.message("User " + new_name + "\nSaved")
time.sleep(2)
finally:
GPIO.cleanup()
我們的最后一段代碼很簡(jiǎn)單,把所有的事情都包了下來。我們首先再次清除LCD,并在LCD上提示用戶需要輸入一個(gè)新的名字。
同時(shí)在控制臺(tái)上,應(yīng)出現(xiàn)文字 "Name: "應(yīng)該會(huì)出現(xiàn),因?yàn)槲覀兝幂斎雭淼却脩舻妮斎搿?/p>
當(dāng)用戶在控制臺(tái)中輸入一個(gè)名字并按下回車鍵后,我們就開始利用游標(biāo)對(duì)象來執(zhí)行我們?cè)谏弦还?jié)代碼中形成的查詢。
我們還創(chuàng)建了一個(gè)元組,傳遞給執(zhí)行函數(shù)。這個(gè)元組包含新的名稱和RFID卡的id。這兩個(gè)值將在執(zhí)行時(shí)自動(dòng)傳遞到我們的查詢字符串中。
最后,我們通過調(diào)用db對(duì)象的.commit()函數(shù)將更改提交到數(shù)據(jù)庫中。如果我們不調(diào)用這個(gè)函數(shù),我們的INSERT和UPDATE查詢將不會(huì)發(fā)生。
我們通過再次清除LCD并顯示新用戶已保存的消息來結(jié)束我們的主代碼邏輯。在重啟循環(huán)之前,我們快速運(yùn)行2秒的睡眠,讓用戶有足夠的時(shí)間看到信息。
最后,我們有我們的 finally:語句,這是我們 try:語句的另一部分。這段代碼確保無論發(fā)生什么事情,我們都會(huì)運(yùn)行GPIO.cleanup函數(shù)。例如,如果我們?cè)谀_本運(yùn)行時(shí)按CTRL + C,它應(yīng)該仍然會(huì)清理GPIO狀態(tài)。
6. 希望此時(shí),你已經(jīng)完成了將腳本寫進(jìn)文件的工作。
然而,如果你想檢查并確保一切正確,那么你可以在下面找到完整版本的代碼。
一旦你對(duì)一切都滿意,按CTRL + X然后Y,最后按ENTER鍵保存文件。
#!/usr/bin/env python
import time
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
import mysql.connector
import Adafruit_CharLCD as LCD
db = mysql.connector.connect(
host="localhost",
user="attendanceadmin",
passwd="pimylifeup",
database="attendancesystem"
)
cursor = db.cursor()
reader = SimpleMFRC522()
lcd = LCD.Adafruit_CharLCD(4, 24, 23, 17, 18, 22, 16, 2, 4);
try:
while True:
lcd.clear()
lcd.message('Place Card to\nregister')
id, text = reader.read()
cursor.execute("SELECT id FROM users WHERE rfid_uid="+str(id))
cursor.fetchone()
if cursor.rowcount >= 1:
lcd.clear()
lcd.message("Overwrite\nexisting user?")
overwrite = input("Overwite (Y/N)? ")
if overwrite[0] == 'Y' or overwrite[0] == 'y':
lcd.clear()
lcd.message("Overwriting user.")
time.sleep(1)
sql_insert = "UPDATE users SET name = %s WHERE rfid_uid=%s"
else:
continue;
else:
sql_insert = "INSERT INTO users (name, rfid_uid) VALUES (%s, %s)"
lcd.clear()
lcd.message('Enter new name')
new_name = input("Name: ")
cursor.execute(sql_insert, (new_name, id))
db.commit()
lcd.clear()
lcd.message("User " + new_name + "\nSaved")
time.sleep(2)
finally:
GPIO.cleanup()
7. 保存了save_user腳本后,讓我們先來轉(zhuǎn)一轉(zhuǎn),以確保一切操作正常,不會(huì)因?yàn)閺?fù)制代碼而出現(xiàn)錯(cuò)誤。
運(yùn)行以下命令來運(yùn)行該腳本。
python3 ~/attendancesystem/save_user.py
8. 輕點(diǎn)你的RFID卡,看看一切是否正常工作,如果不是,請(qǐng)仔細(xì)檢查你的代碼和布線。如果你看到 "User Saved",那么一切都應(yīng)該正常工作。
1. 現(xiàn)在已經(jīng)寫好了save_user腳本,并確保它能正常工作,來看看的check_attendance腳本。
這個(gè)腳本將無限循環(huán)運(yùn)行,檢查是否有RFID芯片被點(diǎn)擊。當(dāng)有人敲擊他們的RFID芯片時(shí),我們將在數(shù)據(jù)庫中檢查該芯片的ID。
如果它找到了一個(gè)用戶,我們就設(shè)置一個(gè)歡迎信息,并在考勤表中插入一個(gè)有當(dāng)前日期和時(shí)間的條目。
讓我們使用下面的命令開始編寫腳本的過程。
nano ~/attendancesystem/check_attendance.py
2. 輸入以下幾行代碼。我們將對(duì)每一段新的代碼進(jìn)行解釋,你會(huì)熟悉其中的一些代碼,因?yàn)槲覀冊(cè)谏弦还?jié)的保存用戶腳本中使用了它。
#!/usr/bin/env python
import time
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
import mysql.connector
import Adafruit_CharLCD as LCD
db = mysql.connector.connect(
host="localhost",
user="attendanceadmin",
passwd="pimylifeup",
database="attendancesystem"
)
cursor = db.cursor()
reader = SimpleMFRC522()
lcd = LCD.Adafruit_CharLCD(4, 24, 23, 17, 18, 22, 16, 2, 4);
try:
while True:
我們就不多說這段代碼了,因?yàn)檫@段代碼都是重用了我們?cè)谶@個(gè)Raspberry Pi RFID考勤系統(tǒng)教程上一節(jié)寫的第一個(gè)save_user.py腳本。
最主要的是,你需要記住的是替換 "passwd "旁邊指定的數(shù)據(jù)庫密碼,因?yàn)槟J(rèn)是我們的例子密碼 "pimylifeup"。
lcd.clear()
lcd.message('Place Card to\nrecord attendance')
id, text = reader.read()
在這段代碼中,我們清除LCD屏幕,并顯示一條信息,提示用戶放卡記錄考勤。然后我們等待RFID閱讀器的響應(yīng)。
cursor.execute("SELECT id, name FROM users WHERE rfid_uid="+str(id))
result = cursor.fetchone()
lcd.clear()
在這里,我們執(zhí)行第一條SQL語句。這條SQL語句從 "用戶 "表中抓取 "id "和 "name",其中用戶的RFID ID與讀卡器上的卡相同。
然后我們抓取SQL查詢返回的記錄,并將其結(jié)果存儲(chǔ)到我們的 "結(jié)果 "變量中供以后使用。
最后,我們清除LCD屏幕,這樣就可以在下一節(jié)代碼中打印新的信息了。
cursor.execute("SELECT id, name FROM users WHERE rfid_uid="+str(id))
result = cursor.fetchone()
lcd.clear()
在本節(jié)中,我們首先檢查上次的SQL請(qǐng)求是否返回了任何行。如果返回0,那么我們就在16×2的顯示屏上顯示一條 "用戶不存在 "的消息。
如果我們確實(shí)有一條記錄,我們就會(huì)顯示一條歡迎用戶的消息。我們使用從數(shù)據(jù)庫中檢索到的用戶名稱作為結(jié)果[1]。
之后,我們做一條SQL語句,在考勤表中插入一條記錄。我們需要傳入我們從之前的SQL調(diào)用中獲取的用戶ID,并存儲(chǔ)在result[0]中。
最后,我們提交對(duì)數(shù)據(jù)庫的修改。
time.sleep(2)
finally:
GPIO.cleanup()
我們的最后一段代碼很簡(jiǎn)單。我們讓腳本休眠兩秒,讓用戶有時(shí)間閱讀我們?cè)?6×2顯示屏上顯示的信息,并取出RFID卡。
"finally: "語句確保我們?cè)谀_本完成后清理GPIO。
3. 輸入完所有代碼后,你可以對(duì)照下面的完整版進(jìn)行檢查。
在輸入所有代碼的時(shí)候,主要是要注意保證所有的縮進(jìn)都是一樣的。每層之間要有兩個(gè)空格隔開。
一旦設(shè)置完成后,按CTRL + X,然后按Y,最后按ENTER鍵保存文件。
#!/usr/bin/env python
import time
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
import mysql.connector
import Adafruit_CharLCD as LCD
db = mysql.connector.connect(
host="localhost",
user="attendanceadmin",
passwd="pimylifeup",
database="attendancesystem"
)
cursor = db.cursor()
reader = SimpleMFRC522()
lcd = LCD.Adafruit_CharLCD(4, 24, 23, 17, 18, 22, 16, 2, 4);
try:
while True:
lcd.clear()
lcd.message('Place Card to\nrecord attendance')
id, text = reader.read()
cursor.execute("Select id, name FROM users WHERE rfid_uid="+str(id))
result = cursor.fetchone()
lcd.clear()
if cursor.rowcount >= 1:
lcd.message("Welcome " + result[1])
cursor.execute("INSERT INTO attendance (user_id) VALUES (%s)", (result[0],) )
db.commit()
else:
lcd.message("User does not exist.")
time.sleep(2)
finally:
GPIO.cleanup()
4. 保存好腳本后,繼續(xù)運(yùn)行它,檢查一切是否正常。
輸入以下命令運(yùn)行腳本,并按照16×2顯示屏上顯示的提示操作。
python3 ~/attendancesystem/check_attendance.py
如果你遇到任何錯(cuò)誤,請(qǐng)確保你仔細(xì)檢查所有的代碼已經(jīng)正確輸入。
1. 現(xiàn)在已經(jīng)寫好并測(cè)試了保存用戶腳本和檢查考勤腳本,來看看數(shù)據(jù)庫,看看新的條目。
通過運(yùn)行以下命令啟動(dòng)MYSQL命令行工具。在繼續(xù)之前,你會(huì)被提示輸入你為root用戶輸入的密碼。
由于MariaDB默認(rèn)使用UNIX_SOCKET進(jìn)行身份驗(yàn)證,所以我們利用sudo來執(zhí)行這個(gè)命令。
sudo mysql -u root -p
2. 一旦你連接到MYSQL命令行,我們需要利用 "使用 "命令。我們需要使用這個(gè)命令,這樣我們就可以和我們的 "考勤系統(tǒng) "數(shù)據(jù)庫進(jìn)行交互。
運(yùn)行以下命令與 "endanceystem "數(shù)據(jù)庫進(jìn)行交互。
use attendancesystem;
3. 現(xiàn)在我們直接與我們的 "考勤系統(tǒng) "數(shù)據(jù)庫進(jìn)行交互,讓我們開始檢查我們的腳本所創(chuàng)建的所有用戶。
我們可以通過運(yùn)行一個(gè)簡(jiǎn)單的SELECT SQL調(diào)用,指定我們的 "用戶 "表來實(shí)現(xiàn)。下面的查詢中使用的星號(hào)(*)表示我們要抓取所有的列。
鍵入以下命令來抓取 "用戶 "表中的所有可用用戶。
SELECT * FROM users;
從這個(gè)命令中,你應(yīng)該看到類似于我們下面的東西。
+--+------------------+---------+------------------------+
| id | rfid_uid | name | created |
+--+------------------+---------+------------------------+
| 1 | 160747764001 | Emmet | 2019-01-31 11:28:04 |
+--+------------------+---------+------------------------+
4. 現(xiàn)在我們已經(jīng)檢查了 "用戶 "表,讓我們繼續(xù)看看 "考勤 "表。就像之前的查詢一樣,我們只是選擇 "考勤 "表中的所有列。
輸入以下命令來抓取所有數(shù)據(jù)。
SELECT * FROM attendance;
從這個(gè)命令中,你應(yīng)該可以看到類似下面的命令行。你可以將 "user_id "引用到 "user "表 "id "中,查看哪個(gè)用戶打卡了。
+----+---------+---------------------+
| id | user_id | clock_in |
+----+---------+---------------------+
| 6 | 1 | 2019-02-01 03:23:30 |
| 7 | 1 | 2019-02-01 03:35:36 |
| 8 | 1 | 2019-02-01 03:36:51 |
+----+---------+---------------------+
你可以通過輸入exit離開MYSQL工具。
1. 在開始本節(jié)之前,我們要求你已經(jīng)設(shè)置好了NGINX與PHP一起使用。你可以按照我們的Raspberry Pi NGINX指南來了解如何做到這一點(diǎn)。
當(dāng)你把NGINX和PHP運(yùn)行起來之后,我們現(xiàn)在就可以開始給我們的考勤系統(tǒng)寫一點(diǎn)前端了。這個(gè)前端是為了讓你可以直觀的看到當(dāng)前用戶的情況,以及他們什么時(shí)候點(diǎn)了閱讀器。
首先在默認(rèn)的NGINX文件夾中建立一個(gè)目錄來保存我們的腳本。
sudo mkdir /var/www/html/attendance
2. 你應(yīng)該已經(jīng)在Raspberry Pi上安裝了GIT,所以現(xiàn)在是時(shí)候?qū)⑽覀兊那岸四_本克隆到第一步創(chuàng)建的文件夾中了。
通過運(yùn)行以下命令從我們的GitHub倉庫中克隆代碼。該命令將使用git將代碼克隆到考勤文件夾中。
sudo git clone https://github.com/pimylifeup/attendance-system-frontend.git /var/www/html/attendance
3. 現(xiàn)在腳本已經(jīng)克隆好了,我們需要對(duì) "common.php "文件做一個(gè)修改,這樣我們就可以利用你在本指南中設(shè)置的數(shù)據(jù)庫登錄。
通過運(yùn)行以下一行開始修改腳本。
sudo nano /var/www/html/attendance/common.php
4. 在這個(gè)腳本中,找到下面的部分,并確保用你自己的密碼代替。
找。
'password' => 'pimylifeup'
一旦你改變了這一行,按CTRL + X然后按Y和ENTER鍵保存文件。
5. 對(duì)于我們的前端腳本,我們利用 "Medoo "和 "bootstrap"。Medoo是一個(gè)處理數(shù)據(jù)庫的輕量級(jí)框架,比如我們?yōu)榭记谙到y(tǒng)建立的數(shù)據(jù)庫。
另一方面,Bootstrap是一個(gè)前端框架,它可以讓你更容易地開發(fā)出外觀簡(jiǎn)潔的前端,而不用擔(dān)心編寫大量的CSS。
現(xiàn)在腳本已經(jīng)被克隆到了目錄中,你現(xiàn)在應(yīng)該可以通過訪問你的樹莓派的IP地址并在URL的結(jié)尾添加/attendance來檢查前端,如下所示。
http://192.168.160/attendance
6. 進(jìn)入網(wǎng)站后,你會(huì)看到下面的網(wǎng)頁,從這里你可以通過點(diǎn)擊 "用戶 "查看當(dāng)前的用戶,也可以通過點(diǎn)擊 "考勤 "按鈕查看用戶的考勤情況。
如果你已經(jīng)走到了這一步,那么所有的工作都是應(yīng)該的,你現(xiàn)在應(yīng)該有一個(gè)基本的RFID和樹莓皮驅(qū)動(dòng)的考勤系統(tǒng)了。
歡迎頁
考勤系統(tǒng)用戶頁
考勤頁
整體系統(tǒng)比較基本,但涵蓋了一個(gè)好的考勤系統(tǒng)所需要的一切。您可以進(jìn)一步擴(kuò)展后端和前端,實(shí)現(xiàn)新的功能,更好的用戶界面等等。
我希望到現(xiàn)在,你已經(jīng)擁有一個(gè)完整的工作的Raspberry Pi RFID考勤系統(tǒng)。
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。