from machine import Pin, I2C, ADC
from time import sleep, sleep_ms
from pico_i2c_lcd import I2cLcd
import math
import random
import ds1307

TECLA_ARRIBA = const(0)
TECLA_ABAJO = const(1)
cancelar = 0
hora_apertura = "0800"
hora_cierre = "2200"
band=0
band2=0



#LCD
i2c = I2C(0, sda=Pin(16), scl=Pin(17), freq=400000)

lcd = I2cLcd(i2c,0x27 , 4, 20)

lcd.move_to(0, 1)
lcd.putstr("hora de cierre: ")
lcd.putstr(str(hora_cierre))
# Menú predeterminado
def menu():
    print("fede")

    
    

#Definiciones ldr
ldr = ADC(27)
MAX_ADC_READING = 65535
ADC_REF_VOLTAGE = 3.3
REF_RESISTANCE = 50
caso_comp = 5
hora = 0



#Motores
# Configurar los pines como salida para los motores
motor1_dir = Pin(2, Pin.OUT)  # Dirección del motor 1 (cortina clara)
motor1_step = Pin(3, Pin.OUT)  # Pasos del motor 1
motor2_dir = Pin(4, Pin.OUT)  # Dirección del motor 2 (cortina oscura)
motor2_step = Pin(5, Pin.OUT)  # Pasos del motor 2
motor3_dir = Pin(6, Pin.OUT)    #Dirección de motor 3 (Persiana)
motor3_step = Pin(7, Pin.OUT)   #Pasos del motor 3

def setup():
    # Inicializar los pines
    motor1_dir.off()
    motor1_step.off()
    motor2_dir.off()
    motor2_step.off()
    motor3_dir.off()
    motor3_step.off()

def move_motor(motor_dir, motor_step, steps, direction, delay=10):
    """
    Controla un motor paso a paso.
    :param motor_dir: Pin de dirección del motor.
    :param motor_step: Pin de pasos del motor.
    :param steps: Número de pasos a mover.
    :param direction: Dirección del motor (True para abrir, False para cerrar).
    :param delay: Tiempo en milisegundos entre pasos.
    """
    motor_dir.value(direction)  # Establecer dirección
    for _ in range(steps):
        motor_step.on()
        sleep_ms(1)  # Pulso de paso
        motor_step.off()
        sleep_ms(delay)


#RTC
i2c_rtc = I2C(0, scl=Pin(1), sda=Pin(0), freq=100000)
# I2C object
# creating an DS1307 RTC object using I2C
ds1307rtc = ds1307.DS1307(i2c_rtc, 0x68)



#Teclado
teclas = [['1', '2', '3', 'A'],
          ['4', '5', '6', 'B'],
          ['7', '8', '9', 'C'],
          ['*', '0', '#', 'D']]

# Pines del GPIO  
filas = [15, 14, 13, 12]
columnas = [11, 10, 9, 8]

# Define los pines de filas como salidas
fila_pines = [Pin(nombre_pin, mode=Pin.OUT) for nombre_pin in filas]

# Define los pines de columnas como entradas
columna_pines = [Pin(nombre_pin, mode=Pin.IN, pull=Pin.PULL_DOWN) for nombre_pin in columnas]

def init():
    for fila in range(4):
        fila_pines[fila].low()

# Define todas las columnas bajo -low-
init()

def scan(fila, columna):
    """ Escanea todo el teclado """

    # Define la columna actual en alto -high-
    fila_pines[fila].high()
    tecla = None

    # Verifica si hay teclas presionadas
    if columna_pines[columna].value() == TECLA_ABAJO:
        tecla = TECLA_ABAJO
    if columna_pines[columna].value() == TECLA_ARRIBA:
        tecla = TECLA_ARRIBA
    fila_pines[fila].low()

    # Devuelve el estado de la tecla
    return tecla

#Minutos dentro del rango
def validar_minutos(horario):
    """ Verifica que los minutos estén en el rango válido (00-59). """
    minutos = int(horario[-2:])
    if 0 <= minutos <= 59:
        return True
    return False

#Cambio de horario
def cambio():
    global cancelar
    cancelar = 0
    entrada = ""  # Limpia la entrada al iniciar
    sleep(0.5)  # Espera breve para evitar capturar entradas previas
    while cancelar == 0:
        for fila in range(4):
            for columna in range(4):
                tecla = scan(fila, columna)
                if tecla == TECLA_ABAJO:
                    ultima_tecla_presionada = teclas[fila][columna]
                    if ultima_tecla_presionada in ["A", "B", "C"]:
                        num = ultima_tecla_presionada
                    else:
                        entrada += ultima_tecla_presionada
                        num = ultima_tecla_presionada

                    if num not in ["A", "B"] and len(entrada) != 4:
                        print("Horario: ", entrada)
                        sleep(0.3)
                    if num == "A" or len(entrada) > 3:
                        if entrada.isdigit() and int(entrada) < 2400 and validar_minutos(entrada) and len(entrada) == 4:
                            print("Horario actualizado.")
                            return entrada
                        else:
                            print("Horario no permitido. Ingrese nuevamente.")
                            entrada = ""
                        sleep(0.3)
                    if num == "B":
                        entrada = ""
                        sleep(0.3)
                    if num == "C":
                        cancelar = 1
                        entrada = ""
                        sleep(0.3)

#Obtener horario
def get_date_string():
    dt = ds1307rtc.datetime
    return str(dt[2]) + "." + str(dt[1]) + "." + str(dt[0])

def get_time_string():
    dt = ds1307rtc.datetime
    return f"{dt[3]:02}:{dt[4]:02}"  # Formatea con ceros iniciales
    #return str(dt[3]) + ":" + str(dt[4])



#Comparar horarios
def comparar_horarios(hora_cierre, hora_apertura):
    # Obtener hora y minutos actuales del RTC
    dt = ds1307rtc.datetime
    hora_actual = dt[3]
    minutos_actuales = dt[4]

    # Convertir el horario guardado en horas y minutos
    hora_ap = int(hora_apertura[:2])
    minutos_ap = int(hora_apertura[2:])
    hora_ci = int(hora_cierre[:2])
    minutos_ci = int(hora_cierre[2:])

    # Comparar horarios de apertura
    if (hora_actual > hora_ap) or (hora_actual == hora_ap and minutos_actuales >= minutos_ap):
        apertura_estado = True  # Horario actual está dentro o después del horario de apertura
    else:
        apertura_estado = False

    # Comparar horarios de cierre
    if (hora_actual < hora_ci) or (hora_actual == hora_ci and minutos_actuales < minutos_ci):
        cierre_estado = False  # Horario actual está antes del horario de cierre
    else:
        cierre_estado = True

    if apertura_estado and not cierre_estado:
        return 0

    else:
        return 1



#Valor ldr
def valor_ldr(ldrResistance, caso_comp, hora):
    if hora == 0:
        # Persiana abierta
        if ldrResistance < 775:
            # No hace nada
            return 0
        elif 775 <= ldrResistance < 2400:
            # Cierra cortina clara
            return 1
        elif ldrResistance >= 2400:
            # Cierra cortina oscura
            return 2
    else:
        # Cierra persiana (((((((((((No se usa)))))))))))
        return 3



def main():
    global hora_cierre, hora_apertura, hora, caso_comp, band, band2
    
    menu()
    while True:
        #print("\n")
        print(get_time_string())
        #hora: indica si es horario de cierre o apertura
        hora = comparar_horarios(hora_cierre, hora_apertura)
        #Lecturas del ldr
        rawData = ldr.read_u16()
        resistorVoltage = rawData / MAX_ADC_READING * ADC_REF_VOLTAGE
        ldrVoltage = ADC_REF_VOLTAGE - resistorVoltage
        ldrResistance = ldrVoltage / resistorVoltage * REF_RESISTANCE
        print(f"LDR resistance: {ldrResistance}")
        #funcion de ldr. De acá sale el valor que controlará que cortina se cierra.
        caso = valor_ldr(ldrResistance, caso_comp, hora)
        caso_comp = caso
        print(caso)
        print(hora)
        #print(hora)
        sleep(1)
        
        '''TECLADO'''
        for fila in range(4):
            for columna in range(4):
                opcion = scan(fila, columna)
                if opcion == TECLA_ABAJO:
                    opcion_presionada = teclas[fila][columna]
                    sleep(0.5)  # Espera para evitar capturar el número del menú en el horario
                    if opcion_presionada == '1':
                        print("Ingrese nuevo horario de cierre:")
                        hora_cierre = cambio()
                        menu()
                        sleep(5)
                    elif opcion_presionada == '2':
                        print("Ingrese nuevo horario de apertura:")
                        hora_apertura = cambio()
                        menu()
                        sleep(5)
        

        #Control motores
        '''PERSIANA'''
        if (hora==0) and (band==0):                 #Abrir la persiana
            band=1
            print("Abriendo persiana.")
            move_motor(motor3_dir, motor3_step, steps=200, direction=True)

        if (hora==1) and (band==1):                 #Cierra la persiana
            band=0
            print("Cerrando persiana.")
            move_motor(motor3_dir, motor3_step, steps=200, direction=False)

        '''CORTINAS'''
        if (caso==0) and (band2==0):                #Abre las 2 cortinas
            band2=1
            print("Abriendo cortina clara.")
            move_motor(motor1_dir, motor1_step, steps=200, direction=True)
            #led_clara.value(1)
            print("Abriendo cortina oscura.")
            move_motor(motor2_dir, motor2_step, steps=200, direction=True)
            #led_oscura.value(1)

        if (caso==1) and (band2==1):                #Cierra cortina clara
            band2=2
            print("Cerrando cortina clara.")
            move_motor(motor1_dir, motor1_step, steps=200, direction=False)
            #led_clara.value(0)
        
        if (caso==2) and (band2==2 or band2==1):    #Cierra cortina oscura
            if (band2==1):
                band2=0
                print("Cerrando cortina clara.")
                move_motor(motor1_dir, motor1_step, steps=200, direction=False)
                #led_clara.value(0)
                print("Cerrando cortina oscura.")
                move_motor(motor2_dir, motor2_step, steps=200, direction=False)
                #led_oscura.value(0)
            if (band2==2):
                band2=0
                print("Cerrando cortina oscura.")
                move_motor(motor2_dir, motor2_step, steps=200, direction=False)
                #led_oscura.value(0)

        if (caso==1) and (band2==0):                #Abriendo cortina oscura
            band2=3
            print("Abriendo cortina oscura.")
            move_motor(motor2_dir, motor2_step, steps=200, direction=True)
            #led_oscura.value(1)
        
        if (caso==0) and (band2==3 or band2==2):    #Abriendo cortina clara
            band2=1
            print("Abriendo cortina clara.")
            move_motor(motor1_dir, motor1_step, steps=200, direction=True)
            #led_clara.value(1)



if __name__ == "__main__":
    main()
GND5VSDASCLSQWRTCDS1307+
A4988
A4988
A4988