import network
from utime import sleep, sleep_ms
from machine import Pin, ADC
from umqtt.simple import MQTTClient
import ujson
import dht

# Configuración de ThingBoard
THINGBOARD_BROKER = "thingsboard.cloud"  # Dirección del broker MQTT de ThingBoard
THINGBOARD_TOKEN = "1Kbzdz2gOd0EqqG1irPK"  # Token de autenticación

# Inicializar el sensor DHT22
sensor = dht.DHT22(Pin(15))
# Simulación de sensor de PH
pot1 = ADC(Pin(34))
# Simulación de sensor de Turbidez
pot2 = ADC(Pin(35))
# Simulación de sensor de Conductividad
pot3 = ADC(Pin(32))
# Simulación de sensor de Caudalímetro
pot4 = ADC(Pin(33))

# Configuración de LEDs
led_conductividad = Pin(17, Pin.OUT)
led_turbidez = Pin(18, Pin.OUT)
led_ph = Pin(19, Pin.OUT)
led_alerta = Pin(25, Pin.OUT)
led_temperatura = Pin(26, Pin.OUT)
led_turbidez_alerta = Pin(27, Pin.OUT)  # LED para turbidez

# Inicializar variables globales
consumo_total = 0
agua_ahorrada = 0  # Nueva variable para el agua ahorrada

def measure_conditions():
    sensor.measure()
    temp = sensor.temperature()
    return temp

def measure_ph():
    pot1_value = pot1.read()
    pH = (pot1_value / 4095) * 14  # Mapeamos el valor a la escala de pH (0-14)
    pH = round(pH, 1)
    return pH

def measure_turbidez():
    pot2_value = pot2.read()
    turbidez = (pot2_value / 4095) * 1000  # Mapeamos el valor a la escala de turbidez (0-1000 NTU)
    turbidez = round(turbidez, 1)
    return turbidez

def measure_conductividad():
    pot3_value = pot3.read()
    conductividad = (pot3_value / 4095) * 5000  # Mapeamos el valor a la escala de conductividad (0-5000 µS/cm)
    conductividad = round(conductividad, 1)
    return conductividad

def measure_caudal():
    pot4_value = pot4.read()
    caudal = (pot4_value / 4095) * 30  # Mapeamos el valor a la escala de caudal (0-30 L/min)
    caudal = round(caudal, 1)
    return caudal

def calcular_consumo(caudal, intervalo):
    # Caudal está en L/min y el intervalo en segundos (convertido a minutos)
    consumo = (caudal * intervalo) / 60  # Calculamos el consumo en litros por el intervalo en segundos
    return consumo

# Conectar a Wi-Fi
def connect_wifi(ssid, password):
    print("Conectando al Wifi", end="")  
    sta_if = network.WLAN(network.STA_IF)
    sta_if.active(True)
    sta_if.connect(ssid, password)
    while not sta_if.isconnected():
        print(".", end="")
        sleep_ms(100)
    print(" Conectado!")

# Conectar a ThingBoard a través de MQTT
def connect_mqtt():
    print("Conectando al servidor de ThingBoard... ", end="")    
    client = MQTTClient(THINGBOARD_TOKEN, THINGBOARD_BROKER, user=THINGBOARD_TOKEN, password="")
    try:
        client.connect()
        print("Conectado!")
    except Exception as e:
        print(f"Fallo al conectar a ThingBoard: {e}")
        client = None
    return client

# Publicar los valores a ThingBoard
def publish_to_thingboard(client, temp, pH, turbidez, conductividad, caudal, consumo, consumo_total, agua_ahorrada, agua_ahorrada_actual):
    try:
        # Crear un mensaje en formato JSON
        payload = ujson.dumps({
            "temperature_2": temp,
            "pH_2": pH,
            "Turbidez_2": turbidez,
            "Conductividad_2": conductividad,
            "Caudal_2": caudal,
            "Consumo_2": consumo,
            "ConsumoTotal_2": consumo_total,
            "AguaAhorradaTotal_2": agua_ahorrada,  # Total acumulado
            "AguaAhorradaActual_2": agua_ahorrada_actual  # Agua ahorrada en este intervalo, solo si temp < 30°C
        })
        
        # Publicar el mensaje en el tópico correspondiente
        client.publish("v1/devices/me/telemetry", payload)  
        print(f"Datos reportados: {payload}")
        
    except OSError as e:
        print(f"Fallo al publicar los datos en ThingBoard: {e}")
        client = None  # Desconectar si falla la publicación
        return False
    return True

def main():
    global consumo_total, agua_ahorrada  # Para actualizar las variables globales
    connect_wifi('Wokwi-GUEST', '')  # Cambiar por tus credenciales Wi-Fi reales
    client = connect_mqtt()
    intervalo = 1  # Intervalo de tiempo en segundos entre cada medición

    while True:
        if not client:
            print("Reconectando a ThingBoard...")
            client = connect_mqtt()
            if not client:
                print("Fallo al reconectar a ThingBoard. Reintentando en 5 segundos...")
                sleep(5)
                continue

        # Leer los datos de sensores
        temp = measure_conditions()
        pH = measure_ph()
        turbidez = measure_turbidez()
        conductividad = measure_conductividad()
        caudal = measure_caudal()

        # Calcular el consumo antes de ajustar el caudal
        consumo = calcular_consumo(caudal, intervalo)

        # Definir el valor de "AguaAhorradaEsteMomento" solo si la temperatura es menor a 30°C
        if temp < 30:
            agua_ahorrada_actual = consumo  # Si la temperatura es menor a 30°C, se ahorra toda el agua que se "detendría"
            agua_ahorrada += agua_ahorrada_actual  # Acumular agua ahorrada antes de poner caudal a 0
            caudal = 0  # Detener flujo de agua si la temperatura es menor a 30°C
            consumo = 0  # Si el caudal es 0, el consumo también debe ser 0
        else:
            agua_ahorrada_actual = 0  # Si la temperatura es 30°C o más, no se ahorra agua

        # Acumular el consumo total
        consumo_total += consumo  

        # Control de LEDs
        led_conductividad.value(conductividad > 1000)
        led_turbidez.value(turbidez > 2)
        led_ph.value(pH > 8.5 or pH < 6.5)
        led_temperatura.value(temp >= 30)

        # Encender el LED de turbidez en el pin 27 si la turbidez es mayor a 2
        led_turbidez_alerta.value(turbidez > 2)

        # El LED en el pin 25 se enciende solo cuando el pH está fuera de rango (menor a 6.5 o mayor a 8.5) 
        # Y la conductividad es mayor a 1000
        led_alerta.value((pH > 8.5 or pH < 6.5) or conductividad > 1000)

        # Mostrar datos en consola
        print(f"Consumo en este intervalo: {round(consumo, 2)} L")
        print(f"Consumo total: {round(consumo_total, 2)} L")
        print(f"Agua ahorrada: {round(agua_ahorrada, 2)} L")

        # Publicar los valores
        if not publish_to_thingboard(client, temp, pH, turbidez, conductividad, caudal, round(consumo, 2), round(consumo_total, 2), round(agua_ahorrada, 2), round(agua_ahorrada_actual, 2)):
            print("Error al publicar los datos, intentando reconectar...")
            client = connect_mqtt()

        # Esperar antes de la siguiente medición
        sleep(intervalo)  # Espera 1 segundo antes de la siguiente medición


if __name__ == "__main__":
    main()
PH 7
Conductividad <1000 µS/cm
Turbidez <2 NTU
Temperatura Agua tibia 30 °C
Caudal 14 Lt/m
Válvula que dirige hacia filtro de osmosis inversa
Válvula que permite paso de agua de ducha
l
l
l
l
l
l
Válvula que dirige hacia filtro de carbón activado