from machine import Pin,PWM,I2C
import utime
import time
import network
import BlynkLib
from pico_i2c_lcd import I2cLcd
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)
I2C_ADDR = i2c.scan()[0]
lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)

# Define GPIO pins
SERVO_PIN = 10  
print("Connecting to WiFi", end="")
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect("Wokwi-GUEST", "")
while not wlan.isconnected():
  print(".", end="")
  time.sleep(0.1)
print(" Connected!")
print(wlan.ifconfig())

 
BLYNK_AUTH = "0sfuwKoodOAG54X5Nu020F9iveUe1OuX"
 
# connect the network       
wait = 10
while wait > 0:
    if wlan.status() < 0 or wlan.status() >= 3:
        break
    wait -= 1
    print('waiting for connection...')
    time.sleep(1)
 
# Handle connection error
if wlan.status() != 3:
    raise RuntimeError('network connection failed')
else:
    print('connected')
    ip=wlan.ifconfig()[0]
    print('IP: ', ip)
    
 
"Connection to Blynk"
# Initialize Blynk
'''blynk = BlynkLib.Blynk(BLYNK_AUTH)
 
# Register virtual pin handler
@blynk.on("V0") #virtual pin V0
def v0_write_handler(value): #read the value
    if int(value[0]) == 1:
        print("Access Granted")
        lcd.clear()
        lcd.putstr("Access Granted!")
        utime.sleep(2)
        lcd.clear()
        lcd.putstr("Door Unlocked")
        unlock_door()
        utime.sleep(2)
        lcd.clear()
        lcd.putstr("Door locked")
        utime.sleep(1)
        lcd.clear()
    else:
        pass
   ''' 


# Keypad mapping (assuming a 4x4 keypad)
KEYPAD_MAP = [
    ["1", "2", "3", "A"],
    ["4", "5", "6", "B"],
    ["7", "8", "9", "C"],
    ["*", "0", "#", "D"]
]

ROW_PINS = [2,3,4,5]
COL_PINS = [6,7,8,9]

row_pins = [Pin(x, Pin.OUT) for x in ROW_PINS]
col_pins = [Pin(x, Pin.IN, Pin.PULL_DOWN) for x in COL_PINS]
key_inputed = []

# Initialize servo motor
servo = PWM(Pin(SERVO_PIN))
servo.freq(50)  # Set PWM frequency to 50Hz
switch_pin = Pin(19, Pin.IN)  # GPIO pin 19

def unlock_door():
    for pos in range(1000,5000,50):
        servo.duty_u16(pos)
        utime.sleep(0.1)  
    servo.duty_u16(0)


def get_keypad_input():
    for row in range(4):
        for col in range(4): 
            row_pins[row].high()
            
            if col_pins[col].value() == 1:
                key_press = KEYPAD_MAP[row][col]
                print("You have Entered:", KEYPAD_MAP[row][col])
                lcd.putstr(KEYPAD_MAP[row][col])
                utime.sleep(0.3)
                key_inputed.append(key_press)
                col_pins[col].low()   
                
            if len(key_inputed) == 4:
                return(key_inputed)
                
                for x in range(0,4):
                    key_inputed.pop() 
                    
        row_pins[row].low()

def authenticate_user(key_inputed):
    key_inputed = get_keypad_input()
    if key_inputed == USER_CODE:
        print("Access Granted")
        lcd.clear()
        lcd.putstr("Access Granted!")
        utime.sleep(2)
        lcd.clear()
        lcd.putstr("Door Unlocked")
        unlock_door()
        utime.sleep(2)
        lcd.clear()
        lcd.putstr("Door locked")
        utime.sleep(1)
        lcd.clear()
    else:
        print("Access denied")
        lcd.clear()
        lcd.putstr("Access Denied!")
        utime.sleep(1)
        lcd.clear()
        utime.sleep(1)
        lcd.putstr("Door locked")
        utime.sleep(1)
        lcd.clear()

def reset_pass(key):
    if key == USER_CODE:
        lcd.clear()
        return reset_key()
    else:
        lcd.clear()
        lcd.putstr("Incorrect password")
        utime.sleep(2)
        lcd.clear()

def reset_key():
    lcd.putstr("Enter New key:")
    utime.sleep(2)
    lcd.clear()
    i = 1   
    key_inputed.clear()
    while (i<2):
        b = get_keypad_input()
        if b == None:
            i=i-1
        i=i+1
        if b != None:
            return b

USER_CODE = ['1','2','3','4']   
c = USER_CODE 
flag = 1
while True:
    #switch_state = switch_pin.value()
    '''utime.sleep(0.1)
    if (switch_state == 0):'''
    if flag == 1:
        lcd.putstr("Enter Password:")
        utime.sleep(3)
        lcd.clear()
        flag = 0
    a = get_keypad_input()
    if (a != None):
        authenticate_user(a)
        a.clear()
        flag = 1
    else:
        pass
    '''else:
        a = get_keypad_input()
        if(a != None):
            c = reset_pass(a)
            print(c)
            USER_CODE.clear()
            print(c)
            a.clear()
    print(c)
    if c!= None:
        USER_CODE = c
    print(USER_CODE)'''