import machine
import time
import network
import urequests
WIFI_SSID = "Wokwi-GUEST"
WIFI_PASS = ""
BLYNK_AUTH_TOKEN = "_y9WUOwiCAwzGE780ZmRIxuWax59r4TJ"
def connect_wifi():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected():
print("[WIFI] Connecting to network...")
wlan.connect(WIFI_SSID, WIFI_PASS)
start_time = time.ticks_ms()
while not wlan.isconnected():
if time.ticks_diff(time.ticks_ms(), start_time) > 10000:
print("[WIFI] Connection timeout (Running Offline Mode)")
return False
time.sleep_ms(500)
print("[WIFI] Connected! IP:", wlan.ifconfig()[0])
return True
connect_wifi()
buzzer = machine.Pin(23, machine.Pin.OUT)
buzzer.value(0)
servo_pin = machine.Pin(18)
servo = machine.PWM(servo_pin, freq=50)
def set_door(open_door):
servo.duty(75 if open_door else 25)
set_door(False)
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21))
DS1307_ADDR = 0x68
def bcd2dec(val):
return (val // 16 * 10) + (val % 16)
def get_time():
try:
data = i2c.readfrom_mem(DS1307_ADDR, 0x00, 7)
sec = bcd2dec(data[0] & 0x7F)
minute = bcd2dec(data[1])
hour = bcd2dec(data[2] & 0x3F)
return hour, minute, sec
except:
return 10, 30, 0
LCD_ADDR = 0x27
def lcd_cmd(cmd):
try:
i2c.writeto(LCD_ADDR, bytes([(cmd & 0xF0) | 0x0C, (cmd & 0xF0) | 0x08]))
i2c.writeto(LCD_ADDR, bytes([((cmd << 4) & 0xF0) | 0x0C, ((cmd << 4) & 0xF0) | 0x08]))
except:
pass
def lcd_data(data):
try:
i2c.writeto(LCD_ADDR, bytes([(data & 0xF0) | 0x0D, (data & 0xF0) | 0x09]))
i2c.writeto(LCD_ADDR, bytes([((data << 4) & 0xF0) | 0x0D, ((data << 4) & 0xF0) | 0x09]))
except:
pass
def lcd_init():
time.sleep_ms(50)
for c in [0x33, 0x32, 0x28, 0x0C, 0x06, 0x01]:
lcd_cmd(c)
time.sleep_ms(5)
def lcd_clear():
lcd_cmd(0x01)
time.sleep_ms(2)
def lcd_print(row, text):
addr = 0x80 if row == 0 else 0xC0
lcd_cmd(addr)
padded_text = text + " " * (16 - len(text))
for ch in padded_text[:16]:
lcd_data(ord(ch))
ROW_PINS = [13, 12, 14, 27]
COL_PINS = [26, 25, 33, 32]
KEYS = [
['1', '2', '3', 'A'],
['4', '5', '6', 'B'],
['7', '8', '9', 'C'],
['*', '0', '#', 'D']
]
rows = [machine.Pin(p, machine.Pin.OUT) for p in ROW_PINS]
cols = [machine.Pin(p, machine.Pin.IN, machine.Pin.PULL_DOWN) for p in COL_PINS]
def read_keypad():
for r_idx, r_pin in enumerate(rows):
r_pin.value(1)
for c_idx, c_pin in enumerate(cols):
if c_pin.value() == 1:
while c_pin.value() == 1:
time.sleep_ms(15)
r_pin.value(0)
return KEYS[r_idx][c_idx]
r_pin.value(0)
return None
def buzz(ms):
buzzer.value(1)
time.sleep_ms(ms)
buzzer.value(0)
def send_to_blynk(status_msg):
try:
url = "https://blynk.cloud/external/api/update?token={}&pin=V0&value={}".format(BLYNK_AUTH_TOKEN, status_msg.replace(" ", "%20"))
urequests.get(url)
print("[CLOUDSYNC] Sent to Blynk IoT ->", status_msg)
except:
print("[CLOUDSYNC] Failed to send update.")
CORRECT_PIN = "1234"
WORK_START = 8
WORK_END = 17
state = "LOCKED_IDLE"
code = ""
failed_count = 0
timer_state = 0
timer_key = 0
def show_idle():
global state, code
state = "LOCKED_IDLE"
code = ""
h, m, _ = get_time()
lcd_clear()
lcd_print(0, "DOOR LOCKED")
lcd_print(1, "Time: {:02d}:{:02d}".format(h, m))
lcd_init()
show_idle()
print("[SYSTEM] USROM Smart Access Control Active.")
while True:
now = time.ticks_ms()
key = read_keypad()
if state == "LOCKED_IDLE":
if key and key.isdigit():
code = key
buzz(40)
state = "CODE_ENTRY"
timer_key = now
lcd_clear()
lcd_print(0, "ENTER PIN (#:OK)")
lcd_print(1, code)
print("[EVENT] Key pressed:", key)
elif state == "CODE_ENTRY":
if time.ticks_diff(now, timer_key) >= 10000:
buzz(200)
print("[TIMEOUT] Entry timed out. Resetting.")
show_idle()
elif key:
timer_key = now
if key == '#':
h, m, s = get_time()
is_valid = (code == CORRECT_PIN)
is_time = (WORK_START <= h < WORK_END)
if is_valid and is_time:
failed_count = 0
state = "ACCESS_GRANTED"
timer_state = now
set_door(True)
buzz(100)
lcd_clear()
lcd_print(0, "ACCESS GRANTED")
lcd_print(1, "Door Open (5s)")
audit_str = "GRANTED (PIN:{} Time:{:02d}:{:02d})".format(code, h, m)
print("[AUDIT] " + audit_str)
send_to_blynk(audit_str)
else:
failed_count += 1
reason = "WRONG_PIN" if not is_valid else "OUT_OF_HOURS"
audit_str = "DENIED-{0} (Attempts:{1}/3)".format(reason, failed_count)
print("[AUDIT] " + audit_str)
send_to_blynk(audit_str)
if failed_count >= 3:
state = "SYSTEM_LOCKOUT"
timer_state = now
lcd_clear()
lcd_print(0, "SYSTEM LOCKOUT!")
buzz(600)
print("[ALERT] SYSTEM LOCKOUT ACTIVATED (60s Penalty)")
send_to_blynk("ALERT: SYSTEM LOCKOUT ACTIVATED")
else:
state = "ACCESS_DENIED"
timer_state = now
lcd_clear()
lcd_print(0, "ACCESS DENIED")
lcd_print(1, "Left: {}".format(3 - failed_count))
buzz(300)
elif key == '*':
buzz(50)
print("[EVENT] Canceled by user.")
show_idle()
elif len(code) < 6 and key.isdigit():
code += key
buzz(40)
lcd_print(1, code)
print("[EVENT] Key pressed:", key)
elif state == "ACCESS_GRANTED":
if time.ticks_diff(now, timer_state) >= 5000:
set_door(False)
print("[INFO] Door locked automatically.")
show_idle()
elif state == "ACCESS_DENIED":
if time.ticks_diff(now, timer_state) >= 2000:
show_idle()
elif state == "SYSTEM_LOCKOUT":
diff = time.ticks_diff(now, timer_state)
if diff >= 60000:
failed_count = 0
print("[INFO] Lockout expired. System restored.")
show_idle()
else:
rem = (60000 - diff) // 1000
lcd_print(1, "Wait: {:02d}s".format(rem))
time.sleep_ms(400)
time.sleep_ms(20)