# Llamado de librerías
from servo import Servo   #Una biblioteca de micropython para controlar los servos rc de forma ordenada.
                          #Esto utiliza hardware PWM como una forma eficiente de generar la señal de salida. Pero, por lo tanto, los servos 
                          #deben conectarse a pines con funcionalidad PWM.
import time               #El módulo time proporciona un conjunto de funciones para indicar el tiempo que el microcontrolador lleva encendido, medir intervalos 
                          #de tiempo e introducir retardos (esperas) en la ejecución de los programas.
from machine import Pin   #Importa desde el dispositivo lo que se encuentra en un pin de conexión, importar la clase Pin del módulo de la máquina, 
                          #que es un módulo específico de MicroPython para interactuar con las funciones de hardware de los microcontroladores. 
                          #La clase Pin se utiliza para trabajar con los pines GPIO
import network #Importa la librería del módulo Network, importa el módulo network global sta_if sta_if = network para simular una red de wifi
import dht  #Resuelve todos los detalles del protocolo de comunicaciones, que se realiza sobre un único pin (el pin Datos) y es capaz de acceder 
            #tanto al DHT11 como al DHT22 y funciona de manera idéntica tanto para el ESP8266 como el ESP32.
import ujson		#Importa la librería ujson, este módulo permite convertir entre objetos Python y el formato de datos JSON.
from umqtt.simple import MQTTClient	  #Biblioteca cliente MicroPython MQTT (Message Queuing Telemetry Transport), específicamente la clase MQTTClient
                                      #del módulo umqtt.simple., proporciona funcionalidad para conectarse a un broker MQTT

MQTT_CLIENT_ID = "micropython-weather-demo"     #la cadena de identificación de cliente única utilizada al conectarse al broker. Si client_id tiene una 
                                                #longitud cero o Ninguna, se generará uno aleatoriamente.
MQTT_BROKER    = "broker.mqttdashboard.com"     #MQTT es un protocolo controlado por eventos, donde no hay transmisión de datos periódica o continua. 
                                                #Así se mantiene el volumen de transmisión al mínimo. Un cliente sólo publica cuando hay información para 
                                                #enviar, y un bróker sólo envía información a los suscriptores cuando llegan nuevos datos.
MQTT_USER      = ""                             #Se utiliza para nombre de usuario
MQTT_PASSWORD  = ""                             #Se utiliza para usar una contraseña o password
MQTT_TOPIC     = "wokwi-weather"	#En MQTT se denomina Topic a una cadena de texto UTF-8, una longitud máxima de 65536 caracteres (aunque lo normal es que 
                                  #sea mucho menor) y distingue entre mayúsculas y minúsculas.

sensor = dht.DHT22(Pin(15))   #variable toma el valor del micro ESP32 a través del pin 15, el código inicializa un objeto DHT22 llamado "sensor" y lo configura
                              #para comunicarse con Arduino a través del pin digital 15 para leer los datos de temperatura y humedad del sensor.   
motor = Servo(Pin(18))        #A la variable motor, se usa la entrada del pin 18

def motor_0_a_180():#Rutina para mover el motor de 0 a 180 y de 180 a 0    
  while True:
    motor.move(0)   #Mueve el motor a la posición de 0°
    time.sleep(0.7) #Tiempo de espera
    motor.move(180) #Mueve el motor a la posición de 180°
    time.sleep(0.7) #Tiempo de espera
    print("Motor en movimiento de 0° a 180°")
    break           #Rompe el ciclo while y pasa a la siguiente línea de código

def motor_posicion_0(): #Rutina para dejar el motor en la posición 0
  while True:
    motor.move(0)   #Mueve el motor a la posición de 0°
    time.sleep(0.7) #Tiempo de espera
    print("Motor detenido en 0°")
    break           #Rompe el ciclo while y pasa a la siguiente línea de código

temp_ambiente = 18            #Se asigna la variable para tener un valor referencia para activar o detener el servo motor

print("Connecting to WiFi", end="")     #Imprime el mensaje Connecting to WiFi con un espacio
sta_if = network.WLAN(network.STA_IF)   #Instala la función sta_if para controlar la interfaz STA
sta_if.active(True)                     #Activa la la interfaz STA del módulo ESP32
sta_if.connect('Wokwi-GUEST', '')       #Da inicio a la conexión 
while not sta_if.isconnected():         #Sentencia while not, mientras no se cumpla la sentencia, realiza la operación dentro de la sentencia
  print(".", end="")	#Función para imprimir, imprime en este caso un punto y un espacio mientras la sentencia sta_if.isconnected() no se cumpla
  time.sleep(0.1)	#Crea un tiempo de espera de 0.1 segundos
print(" Connected!")	#Imprime la palabara " Connecterd!", cuando sale de la sentencia while not

print("Connecting to MQTT server... ", end="")	#Imprime: Connecting to MQTT server...  seguido de un espacio
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, user=MQTT_USER, password=MQTT_PASSWORD)    #Se crea una instancia de la clase MQTTClient, previamente definida
                                                                                            #en el código. Los parámetros pasados al constructor incluyen: El ID 
                                                                                            #del cliente utilizado para identificar este cliente MQTT al conectarse
                                                                                            #al intermediario. La dirección o nombre de host del broker MQTT al que
                                                                                            #conectarse. El nombre de usuario que se utilizará para la autenticación
                                                                                            #con el agente MQTT. La contraseña que se utilizará para la autenticación
                                                                                            #con el agente MQTT.
client.connect()	#Esta instruccion inicia una conexión con el intermediario MQTT utilizando la configuración proporcionada al crear la instancia MQTTClient. 
                  #Establece una conexión con el corredor MQTT y, si tiene éxito, el cliente está listo para enviar y recibir mensajes.
print("Connected!") #Imprime la palabra: Connected!

prev_weather = ""
while True:
  print("Measuring weather conditions... ", end="")
  sensor.measure() 
  message = ujson.dumps({
    "temp": sensor.temperature(),
    "humidity": sensor.humidity(),    
  })
  if message != prev_weather:
    print("Updated!")
    print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC, message))
    client.publish(MQTT_TOPIC, message)
    prev_weather = message
    temp_sensor = sensor.temperature()    #Se asigna el valor leído de la temperatura del sesnsor a la variable temp_sensor

    #Secuencia en la que se compara la temperatura del sensor Vs la de referencia para mover o no el motor
    if temp_sensor >= temp_ambiente: # funcion if para definir una comparativa de "no es igual" entre el conjunto de caracteres de message y la variable creada vacia al inicio denominada prev_weather
      motor_0_a_180()   #Llamado de rutina
    else:               #Si no se cumple la sentencia if, realiza la siguiente sentencia While
      motor_posicion_0()#Llamado de rutina
  else:                 #Cuando la sentencia if es igual, realiza la secuencia else, donde imprime no change y pasa a la secuencia de movimiento del motor de la linea 71
    print("No change")  #Imprime que no hay cambio en la lectura de la temperatura del sensor
    time.sleep(0.2)     #Tiempo de espera
    
    #Secuencia en la que se compara la temperatura del sensor Vs la de referencia para mover o no el motor
    if temp_sensor >= temp_ambiente: # funcion if para definir una comparativa de "no es igual" entre el conjunto de caracteres de message y la variable creada vacia al inicio denominada prev_weather
      motor_0_a_180()   #Rompe el ciclo while y pasa a la siguiente línea de código
    else:               #Si no se cumple la sentencia if, realiza la siguiente sentencia While
      motor_posicion_0()       #Rompe el ciclo while y pasa a la siguiente línea de código