Рассматривали ли вы входить / выходить из системы как переключатель? Состояние по умолчанию 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
до In
![enter image description here](https://i.stack.imgur.com/G2y3H.png)
Помогает ли это указать правильное направление?
Отметка времени Вопрос
Итак, похоже, вы инициализировали временную метку один раз, прежде чем ввести 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.
Затем в вашей ожидаемой базе данных будет строка для каждого прикосновения карты к считывателю со временем события, и вам не придется обновлять уже существующую запись.