RF-AD/Client/main.py

225 lines
7.0 KiB
Python

import network
import urequests as requests
import ujson as json
import time
from machine import Pin, SPI, I2C, Timer
import _thread
from mfrc522 import MFRC522
from ssd1306 import SSD1306_I2C
from env import DOOR_ID, WLAN_SSID, WLAN_SSID, WLAN_PASS, SERVER_IP, SERVER_PORT
# Initialize RFID reader
reader = MFRC522(spi_id=0, sck=6, miso=4, mosi=7, cs=5, rst=22)
# Initialize I2C for the OLED display
i2c = I2C(id=0, scl=Pin(1), sda=Pin(0), freq=200000)
oled = None
# Initialize greenLED
greenled = Pin(16, Pin.OUT)
greenled.on()
time.sleep(0.5)
greenled.off()
# Initialize redLED
redled = Pin(21, Pin.OUT)
redled.on()
time.sleep(0.5)
redled.off()
# Global variables
last_activity_time = time.time()
screensaver_active = False
screensaver_thread_running = False
inactivity_timer = Timer(-1)
def init_oled():
global oled
try:
oled = SSD1306_I2C(128, 64, i2c)
oled.fill(0)
oled.text("Initializing...", 0, 0)
oled.show()
except Exception as e:
print("display error:", e)
# init_oled()
def display_message(message, ip_address):
global last_activity_time, screensaver_active, screensaver_thread_running
last_activity_time = time.time()
screensaver_active = False
screensaver_thread_running = False
try:
oled.fill(0)
oled.text(f"Door ID: {DOOR_ID}", 0, 0) # Display Door ID at the top
oled.text("___________________", 0, 3)
lines = message.split("\n")
for i, line in enumerate(lines):
oled.text(line, 0, 20 + i * 10) # Adjust the y position for each line
oled.text("__________________", 0, 47)
oled.text(ip_address, 0, 57) # Display IP address at the bottom
oled.show()
except Exception as e:
greenled.off()
redled.off()
print("display error:", e)
init_oled()
def screensaver():
global screensaver_active, screensaver_thread_running
x, y = 0, 0
direction_x, direction_y = 1, 1
while screensaver_active:
oled.fill(0)
oled.text("RF-AD", x, y)
oled.show()
time.sleep(0.05)
x += direction_x
y += direction_y
if x <= 0 or x >= 128 - 36: # 36 is the length of "RF-AD"
direction_x *= -1
if y <= 0 or y >= 64 - 10: # 10 is the height of text
direction_y *= -1
# Check for activity
if time.time() - last_activity_time <= 60:
screensaver_active = False
screensaver_thread_running = False
break
def start_screensaver_thread():
global screensaver_active, screensaver_thread_running
if not screensaver_thread_running:
screensaver_active = True
screensaver_thread_running = True
_thread.start_new_thread(screensaver, ())
def handle_inactivity(timer):
if time.time() - last_activity_time > 60:
start_screensaver_thread()
def reset_inactivity_timer():
global last_activity_time
last_activity_time = time.time()
def test_server_connection(ip_address):
while True:
try:
response = requests.get(f"http://{SERVER_IP}:{SERVER_PORT}/")
if response.status_code == 200:
print("Server connection successful")
# display_message(f"Server Connected\nIP: {ip_address}", ip_address)
return
else:
print("Server connection failed")
display_message(f"Server Fail\nIP: {ip_address}", ip_address)
except Exception as e:
print("Server connection error:", e)
display_message(f"Server Error\n{e}\nIP: {ip_address}", ip_address)
# Reconnection loop
while True:
try:
response = requests.get(f"http://{SERVER_IP}:{SERVER_PORT}/")
if response.status_code == 200:
print("Reconnected successfully")
display_message(f"Server Reconnected\nIP: {ip_address}", ip_address)
time.sleep(1)
return
display_message(f"Reconnecting...\nIP: {ip_address}", ip_address)
time.sleep(1)
except Exception as e:
display_message(f"Reconnect Error\n{e}\nIP: {ip_address}", ip_address)
time.sleep(5)
# Connect to WiFi
def connect_wifi(ssid, password):
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
while not wlan.isconnected():
time.sleep(0.5)
print("Connecting to WiFi...")
ip_address = wlan.ifconfig()[0]
print("Connected to WiFi:", ip_address)
display_message("WiFi Connected", ip_address)
test_server_connection(ip_address)
display_message(f"Server Connected\nIP: {ip_address}", ip_address)
time.sleep(1)
# Function to send RFID UID to the server
def send_rfid_to_server(rfid_uid):
try:
url = f"http://{SERVER_IP}:{SERVER_PORT}/access"
headers = {"Content-Type": "application/json"}
data = {"rfid_uid": rfid_uid, "door_id": DOOR_ID}
response = requests.post(url, headers=headers, data=json.dumps(data))
# print(response.json())
return response.json()
except Exception as e:
test_server_connection(ip_address=network.WLAN(network.STA_IF).ifconfig()[0])
return {"access_granted": False}
# Main loop to scan RFID tags
def main():
# Retry mechanism for OLED initialization
for _ in range(3):
try:
init_oled()
break
except Exception as e:
print("OLED init error:", e)
time.sleep(1)
connect_wifi(WLAN_SSID, WLAN_PASS)
ip_address = network.WLAN(network.STA_IF).ifconfig()[0]
display_message("Scan your tag", ip_address)
inactivity_timer.init(period=1000, mode=Timer.PERIODIC, callback=handle_inactivity)
while True:
(status, tag_type) = reader.request(reader.REQIDL)
if status == reader.OK:
(status, uid) = reader.SelectTagSN()
if status == reader.OK:
reset_inactivity_timer()
rfid_uid_decimal = "".join([str(i) for i in uid])
print("RFID UID:", rfid_uid_decimal)
display_message("Checking...", ip_address)
response = send_rfid_to_server(rfid_uid_decimal)
if response.get("access_granted"):
user_upn = response.get("upn")
print("Access Granted:", user_upn)
display_message(f"Access Granted\n{user_upn}", ip_address)
# Turn on the LED to indicate door open
greenled.on()
# Add code here to open the door (e.g., trigger a relay)
else:
print("Access Denied")
display_message("Access Denied", ip_address)
redled.on()
time.sleep(2) # Delay to avoid rapid repeated reads
greenled.off()
redled.off() # Turn off the LED
display_message("Scan your tag", ip_address)
if __name__ == "__main__":
main()