首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使系统实现对RFID卡的二次读卡注销?

如何使系统实现对RFID卡的二次读卡注销?
EN

Stack Overflow用户
提问于 2020-04-26 00:11:42
回答 1查看 225关注 0票数 3

我是一个初学者,我需要一些帮助/指导!因此,基本上我正在尝试使用树莓派4和RFID读写器来制作一个考勤系统。到目前为止,一切都运行得很好,但我正在为sign_out发送数据而苦苦挣扎。现在,在sign_in中的相同时间戳也在数据库中的signed_out中标记,但在这里,我想在第二次读取RFID卡时将数据填充到sign_out列中。如果你有任何其他建议,我很乐意倾听/学习,谢谢。编辑:“从这个问题中删除了整个代码”

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-26 00:26:27

您是否考虑过将登录/注销视为切换?默认状态是sign-in设置为0或false,sign-out设置为1或true。然后,当读取卡时,它检查登录的值。如果它是0/false,它将被反转为1/true,并执行相反的反转以注销。当第二次读取卡时,它读取注销,如果为0/false,则将其设置为1/true,并执行与登录相反的操作。

为了清楚起见:

代码语言:javascript
复制
current state: 
    sign-in = 0
    sign-out = 1

---> card is read for the first time
sign-in = (sign-in + 1) % 2 
sign-out = (sign-out + 1) %2

state now:
    sign-in = 1
    sign-out = 0

---> card is read for the second time, consider previous state
sign-in = (sign-i + 1) % 2
sign-out = (sign-out + 1) % 2

state:
    sign-in = 0
    sign-out = 1

这可以通过将两个状态减少到一个单独的状态signed-in来进一步简化。

代码语言:javascript
复制
initial state:
    signed-in = 0

---> card is read for entry
signed-in = (signed-in + 1) % 2

state:
    signed-in = 1

---> card is read for exit
signed-out = (signed-in + 1) % 2

state:
    signed-in = 0

简单地说,您希望将其视为具有两个转换的简单状态机:从InOut和从OutIn

这能帮助你找到正确的方向吗?

时间戳问题

因此,在进入循环之前,您似乎只初始化了一次时间戳。试着移动

代码语言:javascript
复制
ts = time.time()
timestamp = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d     %H:%M:%S'

在以下行之后:

代码语言:javascript
复制
id, text = reader.read()

这解决了你的问题吗?

常规样式注释

您可以简化以下操作:

代码语言:javascript
复制
if sign_in == 0:
    sign_in = (sign_in + 1) % 2
    sign_out = (sign_out + 1) % 2
    #id, text = reader.read()
    cursor.execute("INSERT INTO attendance (user_id, clock_in) VALUES (%s, %s)", (result[0], timestamp,) )
    lcd.lcd_display_string("Sign in " + result[1])

  elif sign_in == 1:
    sign_out = (sign_out + 1) % 2
    sign_in = (sign_in + 1) % 2
    #id, text = reader.read()
    cursor.execute("INSERT INTO attendance (user_id, clock_out) VALUES (%s, %s)", (result[0], timestamp,) )

    lcd.lcd_display_string("Sign out " + result[1])

更像是

代码语言:javascript
复制
sign_in = (sign_in + 1) % 2
sign_out = (sign_out + 1) % 2
#id, text = reader.read()
field_in_or_out = 'in' if sign_in == 1 else 'out'
cursor.execute(f"INSERT INTO attendance (user_id, clock_{field_in_or_out}) VALUES (%s, %s)", (result[0], timestamp,) )
lcd.lcd_display_string(f"Sign {field_in_or_out} " + result[1])

我将如何进一步简化逻辑

代码语言:javascript
复制
#!/usr/bin/env python
import time
import datetime
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
import mysql.connector
import I2C_LCD_driver

db = mysql.connector.connect(
    host="localhost",
    user="admin",
    passwd="*******",
    database="attendancesystem"
)

cursor = db.cursor()
reader = SimpleMFRC522()
lcd = I2C_LCD_driver.lcd()
#redLED = 4
#yellowLED = 17
#greenLED = 27
#GPIO.setmode(GPIO.BCM)
signed_in = 0
try:
    while True:
        lcd.lcd_clear()
        lcd.lcd_display_string('Place Card to')
        lcd.lcd_display_string('record attendance', 2)
        id, text = reader.read()

        ts = time.time()
        timestamp = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d     %H:%M:%S')

        cursor.execute("Select id, name FROM users WHERE rfid_uid="+str(id))
        result = cursor.fetchone()

        lcd.lcd_clear()

        if cursor.rowcount >= 1:
            lcd.lcd_display_string("Welcome")
            lcd.lcd_display_string(""+ result[1], 2)
            #GPIO.output(greenLED,GPIO.HIGH)
            #time.sleep(3)
            #GPIO.output(greenLED,GPIO.LOW)
            cursor.execute("INSERT INTO attendance (user_id) VALUES (%s)", (result[0],) )

            signed_in = (signed_in + 1) % 2
            #id, text = reader.read()
            cursor.execute(f"INSERT INTO attendance (user_id, read_at) VALUES (%s, %s)", (result[0], timestamp,) )
            lcd.lcd_display_string(f"Card read " + result[1])
            db.commit()

        else:
            lcd.lcd_display_string("User does not")
            lcd.lcd_display_string("exist !!", 2)
            #GPIO.output(yellowLED,GPIO.HIGH)
            #time.sleep(3)
            #GPIO.output(yellowLED,GPIO.LOW)
        time.sleep(2)
finally:
    GPIO.cleanup()

并将数据库模式更新为仅具有读取卡时的user_idread_at时间列。更改您的sign_in/sign_out逻辑,使其只有一个表示这两种状态的signed_in字段,当用户登录时为1,当用户未登录时为0。

代码中的另一个变化是将时间戳逻辑拉入while循环。

然后,您期望的数据库将在每次卡被触摸到读卡器时都有一行记录事件发生的时间,这样您就不必更新已经存在的条目。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61428664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档