import time
import machine
import micropython
import network
import neopixel
import dht
from neopixel import NeoPixel
from machine import Pin,PWM
from umqtt.simple import MQTTClient
from time import sleep,sleep_ms
#Indicamos red WIFI y clave
ssid = 'Wokwi-GUEST'
wifipassword = ''
#Datos Server MQTT (Broker)
#Indicamos datos MQTT Broker (server y puerto)
mqtt_server = 'io.adafruit.com'
port = 1883
user = 'joelrueda' #definido en adafruit
password = 'aio_YmmY86wdTJDgGXR6pGLD1CPYjt5L' #key adafruit
#Indicamos ID(unico) y topicos
client_id = 'SensorPrueba'
topic_LED = 'joelrueda/feeds/LedTemperatura'
topic_SENSOR = 'joelrueda/feeds/SensorTemperatura'
topic_Humedad = 'joelrueda/feeds/AlarmaHumedad'
#Usamos una variable para definir si los sensores están activos.
sensorTempActivo =False
alarmaHumedadActiva = False
#Definimos modo Station (conectarse a Access Point remoto)
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
#Conectamos al wifi
sta_if.connect(ssid, wifipassword)
print("Conectando")
while not sta_if.isconnected():
  print(".", end="")
  sleep(0.1)
print("Conectado a Wifi!")
#Vemos cuales son las IP
print(sta_if.ifconfig())

#Antes de conectarnos al broker, vamos a definir una funcion
#que sera llamada cada vez que se produzca un publish sobre
#un topico donde estamos suscriptos
def callback_sensor(topic, msg):
    global sensorTempActivo,ledEstado,alarmaHumedadActiva
    #Cuando se ejecuta esta funcion quere decir que
    #hubo un mensaje nuevo en algun topico, verificamos esto
    #Dado que lo que llega viene en UTF-8, lo decodificamos
    #para que sea una cadena de texto regular
    dato = msg.decode('utf-8')
    topicrec = topic.decode('utf-8')
    print("Cambio en: "+topicrec+":"+dato)
    #Nos fijamos si es el topico esperado y el valor del dato
    if topicrec == topic_SENSOR:
        if "OFF" in dato:
            sensorTempActivo = False
        else:
            sensorTempActivo = True
    elif topicrec == topic_Humedad:
        if "OFF" in dato:
            alarmaHumedadActiva = False
        else:
            alarmaHumedadActiva = True

#Intentamos conectarnos al broker MQTT
try:
    conexionMQTT = MQTTClient(client_id, mqtt_server,user=user,password=password,port=int(port))
    conexionMQTT.set_callback(callback_sensor)
    conexionMQTT.connect()
    conexionMQTT.subscribe(topic_SENSOR)
    conexionMQTT.subscribe(topic_Humedad)
    print("Conectado con Broker MQTT")
except OSError as e:
    #Si fallo la conexion, reiniciamos todo
    print("Fallo la conexion al Broker, reiniciando...")
    sleep(5)
    machine.reset()

#Armamos un loop infinito que chequea por mensajes nuevos
#y verifica el estado del Sensor

nroLeds = 16
npTemperatura = NeoPixel(Pin(2), nroLeds)
ledCalor = (255,0,0)
ledNormal = (0,255,0)
ledFrio = (0,0,255)
ledApagado = (0,0,0)

SensorDHT22 = dht.DHT22(Pin(14))
SensorDHT22.measure()
temp = SensorDHT22.temperature()
hume = SensorDHT22.humidity()

limEstadosTemp= [[-40,10],[11,59],[60,80]]
#                  FRIO    NORMAL   CALOR
frio = 0
normal = 1
calor = 2
apagado = 3
limInf = 0 #Para acceder al
limSup = 1 #array limEstadosTemp

print("Comenzando monitoreo del sensor")
alarma = PWM(Pin(5), freq=1200, duty_u16=32768)
alarma.duty(0)
alarmaHumSonando = False
estActualTemp = apagado
while True:
    try:
    #Tenemos que verificar si hay mensajes nuevos publicados por el broker
        conexionMQTT.check_msg()
        sleep_ms(500)
        #Actualizamos los valores de los sensores
        SensorDHT22.measure()
        nuevaHume = SensorDHT22.humidity()
        nuevaTemp = SensorDHT22.temperature()
        #Si el sensor de temperatura esta activo...
        if sensorTempActivo:
            if nuevaTemp <= limEstadosTemp[frio][limSup] and estActualTemp != frio:
                npTemperatura.fill(ledFrio)
                conexionMQTT.publish(topic_LED,str(frio))
                estActualTemp = frio
            elif limEstadosTemp[normal][limInf] <= nuevaTemp <= limEstadosTemp[normal][limSup] and estActualTemp != normal:
                npTemperatura.fill(ledNormal)
                conexionMQTT.publish(topic_LED,str(normal))
                estActualTemp = normal
            elif limEstadosTemp[calor][limInf] <= nuevaTemp and estActualTemp != calor:
                npTemperatura.fill(ledCalor)
                conexionMQTT.publish(topic_LED,str(calor))
                estActualTemp = calor
        else:
            if estActualTemp != apagado:
                npTemperatura.fill(ledApagado)
                npTemperatura.write()
                conexionMQTT.publish(topic_LED,str(apagado))
                estActualTemp = apagado
        npTemperatura.write()
        #Si el sensor de humedad esta activo
        if alarmaHumedadActiva:
            if nuevaHume > 50 and not alarmaHumSonando:
                alarma.duty(512)
                alarmaHumSonando = True
            elif nuevaHume <= 50 and alarmaHumSonando:
                alarma.duty(0)
                alarmaHumSonando = False
        else:
            if alarmaHumSonando:
                alarma.duty(0)
                alarmaHumSonando = False
        temp = nuevaTemp
        hume = nuevaHume
    except OSError as e:
        print("Error ",e)
        time.sleep(5)
        machine.reset()


"""
np[0] = (255,0,0)
np[1] = (0,255,0)
np[2] = (0,0,255)
np[14] = (100,100,100)
np.write()
"""

"""
while True:
    for color in [rojo,verde,azul]:
        np.fill(color)
        np.write()
        sleep(1)
"""

"""
np.fill((255,255,255))
while True:
    for nPixel in range(NroLeds):
        np[nPixel] = verde
        np.write()
        sleep(0.5)
        np[nPixel] = (255,255,255)
        np.write()
"""