from machine import Pin, ADC, PWM, I2C
from time import sleep
from neopixel import NeoPixel
from servo import Servo
from hcsr04 import HCSR04
import dht
import ssd1306

from alarma import Alarma
from altavoz import Altavoz

# Creación de instancias de los objetos a utilizar.
boton = Pin(2, Pin.IN, Pin.PULL_UP)
luz = NeoPixel(Pin(0), 3)  # Declaración del pin y la cantidad de neopixels.


servo_pin = Pin(14)  # Instancia del servo según su pin
my_servo = Servo(servo_pin) # Enlace a la clase.

Potenciometro = ADC(Pin(4))
sensor = dht.DHT22(Pin(15))
Ultra = HCSR04(13, 12, 10000)

i2c = I2C(0, scl=Pin(22), sda=Pin(21)) # Instancia los pines conectados a la pantalla.
oled = ssd1306.SSD1306_I2C(128, 64, i2c)

alarma = Alarma(pin=0, num_pixels=3) # Instancia de Alarma
Buzzer = Altavoz(pin=18)  # Instancia de la clase Altavoz

# Métodos "funciones" llamadas desde ciclo "While" para el sensor dht22
def leer_temperatura():
    sensor.measure()
    temp = sensor.temperature()
    return temp

def leer_humedad():
    sensor.measure()
    hum = sensor.humidity()
    return hum

def leer_distancia():
    return Ultra.distance_cm()

def control_flujo_agua(temp, hum, distancia):

    if distancia <= 120:   # Condición para apagar el sistema de riego cuando se riega manualmente.
        my_servo.write_angle(0)  # Cerrar la llave del agua si la distancia es menor o igual a 120 cm.
        luz[0] = (0, 0, 0)
        luz.write()
        luz[1] = (0, 0, 0)      # Apagar todos los neopixels.
        luz.write()
        luz[2] = (0, 0, 0)
        luz.write()
        print("Cerrando llave de agua, por asistencia manual..") # Aviso para indicar
        frecuencia = ajustar_frecuencia()  # Obtener la frecuencia del potenciómetro
        Buzzer.alarma_nuclear(frecuencia)  # Activa alarma sonora para indicar que hay alguien presente.
        
    elif hum == 100:
        my_servo.write_angle(0)  # Cerrar la llave del agua cuando se humedezca completamente.
        luz[0] = (0, 0, 255)
        luz.write()
        luz[1] = (0, 0, 255)   # Se enciende azul indicando que está 100% humedecido.
        luz.write()
        luz[2] = (0, 0, 255)
        luz.write()
        print("Riego completado...")
       
        
    elif 5 <= temp <= 30: # Temperatura media "normal"
        my_servo.write_angle(0)  # Cerrar la llave del agua cuando la temperatura esté en el rango normal.
        luz[0] = (0, 255, 0)
        luz.write()
        luz[1] = (0, 255, 0)   # Se enciende verde indicando que la temperatura está normal.
        luz.write()
        luz[2] = (0, 255, 0)
        luz.write()
        
    elif temp > 30: # Temperatura caliente
        my_servo.write_angle(180)  # Abrir la llave del agua al 100%
        alarma.ejecutar() # Método de alarma para encender en rojo de manera consecutiva.
        frecuencia = ajustar_frecuencia()  # Obtener la frecuencia del potenciómetro
        Buzzer.alarma_intermitente(frecuencia)
        print("Temperatura caliente...")

def ajustar_frecuencia():
    # Lee el valor del potenciómetro y ajusta la frecuencia del buzzer 
    pot_value = Potenciometro.read()  # Leer valor del potenciómetro (0-4095)
    # Mapear el valor del potenciómetro (0-4095) a un rango de 100 a 5000 Hz
    frecuencia = int(pot_value * (5000 - 100) / 4095 + 100)
    return frecuencia



estado = 0  # 0: apagado, 1: mostrar temperatura, 2: mostrar humedad

while True:
    if not boton.value():  # Si el botón está presionado (valor bajo)
        estado = (estado + 1) % 4  # Alternar entre 0, 1, 2, 3
        while not boton.value():  # Espera hasta que se suelte el botón
            pass
    sleep(0.5)  # Pequeña pausa para evitar rebotes

    temp = leer_temperatura()
    hum = leer_humedad()
    distancia = leer_distancia()

    # Permite visualizar datos del temperatura
    if estado == 1:
        oled.fill(0) # Función que borra pantalla.
        oled.text("SENSOR", 40,10)
        oled.text("TEMPERATURA", 20,20)
        oled.text("Grados", 40,40)
        oled.show()
        print(temp)
        control_flujo_agua(temp, hum, distancia)

    # Pemite visualizar datos de humedad
    elif estado == 2:
        oled.fill(0) # Función que borra pantalla.
        oled.text("SENSOR", 40,10)
        oled.text("HUMEDAD", 40,20)
        oled.text("Porcent", 30,40)
        oled.show()
        print(hum)
        control_flujo_agua(temp, hum, distancia)

    # Permite visualizar datos de distancia  
    elif estado == 3:
        oled.fill(0) # Función que borra pantalla.
        oled.text("SENSOR", 40,10)
        oled.text("DISTANCIA", 30,20)
        oled.text("CM", 60,40)
        oled.show()
        print(distancia)
        control_flujo_agua(temp, hum, distancia)

    # Estado de apagado para la pantalla y el sistem de riego, todo se detiene.  
    else:
        oled.fill(0) # Función que borra pantalla.
        oled.text("PRESIONA BOTON", 10,20)
        oled.text("--- ON ---", 20,40)
        oled.text("...", 50,50)
        oled.show()
        print("Apagado...")
        my_servo.write_angle(0)  # Se cierra la llave del agua.
        
        luz[0] = (0, 0, 0)
        luz.write()
        luz[1] = (0, 0, 0)  # Se mantiene apagado los neopixels.
        luz.write()
        luz[2] = (0, 0, 0)
        luz.write()
        # Apagar el buzzer cuando el sistema está apagado
        Buzzer.buzzer.duty(0) 

    sleep(1)  # Pausa de un segundo entre cada lectura
$abcdeabcde151015202530354045505560fghijfghij