from machine import Pin, PWM, ADC, SoftI2C, time_pulse_us
from hcsr04 import HCSR04
import ssd1306
import time
import dht
from time import sleep, ticks_ms

i2c = SoftI2C(scl=Pin(22), sda=Pin(21))
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)

sensor = dht.DHT22(Pin(15))
i2c2 = SoftI2C(scl=Pin(18), sda=Pin(19))
oled2 = ssd1306.SSD1306_I2C(128, 64, i2c2)
pir = Pin(2, Pin.IN)

ldr = ADC(Pin(34))
ldr.atten(ADC.ATTN_11DB)
led2 = Pin(14, Pin.OUT)

medidor = HCSR04(trigger_pin=4, echo_pin=5)
led = Pin(13, Pin.OUT)
pwm_led = PWM(led)

#oled 3
i2c3 = SoftI2C(scl=Pin(32), sda=Pin(33))
oled3 = ssd1306.SSD1306_I2C(128, 64, i2c3)

ledRojo = Pin(0, Pin.OUT)
ledAmarillo = Pin(16, Pin.OUT)
ledVerde = Pin(17, Pin.OUT)
trig = Pin(26, Pin.OUT)
echo = Pin(27, Pin.IN)

TIEMPO_VERDE = 10000
TIEMPO_ROJO = 10000
INTERVALO_PARPADEO = 500

timerVerde = 0
timerRojo = 0
estado = "VERDE"

motion_message = "Movimiento detectado"
no_motion_message = "No hay movimiento"

def LuzRoja():
    ledRojo.value(1)
    ledAmarillo.value(0)
    ledVerde.value(0)
    print("Luz roja, vehiculo detectado, cambiando en cuanto no se detecte")

def LuzAmarilla(parpadeos=3):
    for _ in range(parpadeos):
        ledAmarillo.value(1)
        sleep(INTERVALO_PARPADEO / 1000)
        ledAmarillo.value(0)
        sleep(INTERVALO_PARPADEO / 1000)

def LuzVerde():
    ledRojo.value(0)
    ledAmarillo.value(0)
    ledVerde.value(1)

def d():
    trig.value(0)
    sleep(0.000002)
    trig.value(1)
    sleep(0.00001)
    trig.value(0)

    duration = time_pulse_us(echo, 1, 1000000)
    detector = (duration / 2) / 29.1
    return detector

def intensidad(distancia):
    if distancia <= 100:
        pwm_led.duty(1023)
    elif distancia <= 200:
        pwm_led.duty(256)
    else:
        pwm_led.duty(0)

while True:
    distancia = medidor.distance_cm()
    intensidad(distancia)
    time.sleep(1)

    # pt2
    val_ldr = ldr.read()
    oled.fill(0)
    oled.text("Iluminacion: ", 14, 10)
    oled.text(str(val_ldr), 50, 30)
    
    umbral = 500
    
    if val_ldr < umbral:
        led2.on()
    else:
        led2.off()
    
    oled.show()

    # pt3
    if pir.value() == 1:
        # Si se detecta movimiento, mide la temperatura y humedad
        sensor.measure()
        temp = sensor.temperature()
        humidity = sensor.humidity()
        
        # Muestra los datos en la pantalla OLED
        oled2.fill(0)
        oled2.text(motion_message, 0, 0)
        oled2.text("Temp: {:.1f}C".format(temp), 0, 10)
        oled2.text("Humedad: {:.1f}%".format(humidity), 0, 20)
        oled2.show()
    else:
        # Si no hay movimiento, muestra un mensaje
        oled2.fill(0)
        oled2.text(no_motion_message, 0, 0)
        oled2.show()

    # pt4: Gestión de semáforo y pantalla OLED3
    detector = d()
    tiempo_actual = ticks_ms()

    oled3.fill(0)
    if estado == "VERDE":
        if tiempo_actual - timerVerde >= TIEMPO_VERDE:
            if detector <= 50:
                estado = "AMARILLO"
                mensaje = "Vehiculo detectado,\ncambiando a amarillo"
                print(mensaje)
            else:
                timerVerde = tiempo_actual
                mensaje = "Tiempo en verde cumplido,\nreiniciando el tiempo"
                print(mensaje)
        else:
            mensaje = "Luz verde, no hay\nvehiculo detectado"
            print(mensaje)
        LuzVerde()

    elif estado == "AMARILLO":
        ledVerde.value(0)
        LuzAmarilla(parpadeos=3)
        estado = "ROJO"
        timerRojo = tiempo_actual
        mensaje = "Cambiando a rojo"
        print(mensaje)
        LuzRoja()

    elif estado == "ROJO":
        if tiempo_actual - timerRojo >= TIEMPO_ROJO:
            estado = "VERDE"
            timerVerde = tiempo_actual
            mensaje = "Tiempo en rojo cumplido,\ncambiando a verde"
            print(mensaje)
        LuzRoja()

    mensaje_detector = f"Deteccion a: {detector} cm"
    print(mensaje_detector)

    oled3.text(mensaje, 0, 0)
    oled3.text(mensaje_detector, 0, 20)
    oled3.show()

    sleep(1)