Как заставить систему понять, что RFID-карта читается 2 раза для выхода? - PullRequest
3 голосов
/ 25 апреля 2020

Я новичок, и мне нужна помощь / руководство! В общем, я пытаюсь создать систему посещаемости, используя Raspberry Pi 4 и RFID-ридер и писатель. Пока все работает хорошо, но я борюсь с отправкой данных для sign_out. На данный момент та же временная метка, которая есть в sign_in, также помечена в sign_out в базе данных, но здесь я бы хотел сделать так, чтобы при считывании карты RFID во второй раз данные заполнялись в столбце sign_out. Если у вас есть какие-либо другие предложения, я буду рад услышать / узнать, спасибо. РЕДАКТИРОВАТЬ: "весь код был удален из этого вопроса"

1 Ответ

1 голос
/ 25 апреля 2020

Рассматривали ли вы входить / выходить из системы как переключатель? Состояние по умолчанию sign-in установлено на 0 или false, sign-out установлено на 1 или true. Затем, когда карта прочитана, она проверяет значение входа. Если он равен 0 / false, он переворачивается на 1 / true и выполняет обратное переключение для выхода. Когда карта читается во второй раз, она считывает выход из системы, а если 0 / ложь, она устанавливает ее в 1 / true и делает обратное входу.

Для ясности:

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

Это можно еще больше упростить, сократив 2 состояния до одного, signed-in.

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

Проще говоря, вы хотите рассматривать это как простой конечный автомат с двумя переходами : от In до Out и от Out до Inenter image description here

Помогает ли это указать правильное направление?

Отметка времени Вопрос

Итак, похоже, вы инициализировали временную метку один раз, прежде чем ввести l oop. Попробуйте переместить

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

после следующей строки:

id, text = reader.read()

Решает ли это вашу проблему?

Комментарии общего стиля

Вы можете упростить следующее:

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])

на что-то более похожее на

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])

Как мне упростить логи c далее

#!/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_id и read_at времени считывания карты. Измените sign_in / sign_out logi c, чтобы оно имело только поле signed_in, которое выражает оба состояния, 1 - когда пользователь вошел в систему, 0 - когда нет.

Другое изменение в коде вводится метка времени c в while l oop.

Затем в вашей ожидаемой базе данных будет строка для каждого прикосновения карты к считывателю со временем события, и вам не придется обновлять уже существующую запись.

...