import network, urequests
import dht
from dht import DHT22
import machine
from machine import Pin, SoftI2C, PWM
from utelegram import Bot
import neopixel
from neopixel import NeoPixel
import time
from time import sleep, sleep_ms
from lcd_api import LcdApi
from pico_i2c_lcd import I2cLcd
import ujson
from umqtt.simple import MQTTClient
import privado
import ssd1306

servo_pin = 16
p23 = Pin(23, Pin.OUT)
servo1 = machine.PWM(p23)
servo1.freq(50)
servo1.duty(0)

# Configuración del servo motor
servo = machine.PWM(Pin(servo_pin), freq=50)
servo_min = 40
servo_max = 115

def map(x, in_min, in_max, out_min, out_max):
    # Función para mapear valores de un rango a otro.
    return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)

def servo(pin, angle):
    # La función map toma un valor (angle en este caso) y realiza una 
    # transformación lineal del rango de 0 a 180 grados al nuevo rango de 20 a 120.
    pin.duty(map(angle, 0, 180, 20, 120))

print("")
print('- - - - - - - - - - - Bienvenidos - - - - - - - - - - -')

MQTT_CLIENT_ID = "micropython-weather-demo"
MQTT_BROKER = "broker.mqttdashboard.com"
MQTT_USER = ""
MQTT_PASSWORD = ""
MQTT_TOPIC = "Wokwi-weather"

TOKEN = privado.token
bot = Bot(TOKEN)
rele = Pin(14,Pin.OUT)
sensor = dht.DHT22(Pin(15))

# Configuración de los pines SDA y SCL
sda_pin = 21
scl_pin = 22

# Inicialización de la interfaz I2C
i2c = SoftI2C(scl=Pin(scl_pin), sda=Pin(sda_pin))

#Configuracion Oled
oled_width = 128
oled_height = 64

# Creación del objeto OLED
I2C_ADDR     = 0x27 
I2C_NUM_ROWS = 4
I2C_NUM_COLS = 20

oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
lcd = I2cLcd(i2c, I2C_ADDR, I2C_NUM_ROWS, I2C_NUM_COLS)

#Imprimir en el Oled
oled.fill(0)
oled.text("Cargando....", 0, 0)
oled.show()
pixel = NeoPixel(Pin(13),16)
pixel.fill((0,255,255)) #Aqua
pixel.write()

print("Conexion a la Red")
def conectarWIFI(red,password):
    global miRed
    miRed = network.WLAN(network.STA_IF)
    if not miRed.isconnected():
        miRed.active(True)
        miRed.connect(red,password)
        print('Conectandose a la red ....',red +"...")
        pixel = NeoPixel(Pin(13),16)
        pixel.fill((0, 255, 0)) #Verde
        pixel.write()
        timeout = time.time()
        while not miRed.isconnected():
            if(time.ticks_diff(time.time(),timeout)>10):
                return False
    return True

def menuprincipal():
  lcd.clear()
  lcd.move_to(0,0)
  lcd.putstr("-- BIENVENIDOS --")
  lcd.move_to(0,1) 
  lcd.putstr("CONEXION EXITOSA✓") 
  pixel = NeoPixel(Pin(13),16)
  pixel.fill((0,128,0)) #verde
  pixel.write()
  time.sleep(0.5)
  lcd.clear()
  lcd.putstr("SISTEMA DE RIEGO") 
menuprincipal()

def update_oled(temp, hum):
    oled.fill(0)
    oled.text("Temperatura: {:.1f}C".format(temp), 0, 0)
    oled.text("Humedad: {:.1f}%".format(hum), 0, 20)
    oled.show()
    if (temp <= 25):
        print("La temperatura está fuera del rango ambiente (20 - 25 grados)")
        print("Riegue el cultivo")
        #El servo tomas las posiciones 0, 90 ,180.
        servo(servo1, 0)  
        time.sleep(0.5)
        servo(servo1, 90)
        time.sleep(0.5)
        servo(servo1, 180)
        time.sleep(0.5)
        #Comienza un ciclo que moverá el servo con un dekay de .5 segundos(ahora si infinito hasta que la temperatura cambie)
        for i in range(0, 180, 10):
            servo(servo1, i)
            time.sleep(0.5)
        print("Regado completamente")
    else:
        print("Temperatura Ambiente Detectada")
    time.sleep(5)
    pixel = NeoPixel(Pin(13),16)
    pixel.fill((0, 0, 255))  #Azul
    pixel.write()

def read_texto():
  print("")
  print('- - - - - - - - - - - Bienvenidos - - - - - - - - - - -') 
  lcd.clear()
  lcd.move_to(0,7)
  lcd.putstr("- - - - - - - - - - - Bienvenidos - - - - - - - - - - -")
  pixel = NeoPixel(Pin(13),16)
  pixel.fill((255, 255, 255)) #Blanco
  pixel.write()

read_texto()

# Función para obtener la temperatura del sensor DHT22
def get_temperature():
  sensor.measure()
  temperature = sensor.temperature()
  current_temperature = sensor.temperature()
  print("Temperatura actual:", current_temperature, "°C")
  if (current_temperature <= 25):
    print("La temperatura está fuera del rango ambiente (20 - 25 grados)")
    print("Riegue el cultivo")
    #El servo tomas las posiciones 0, 90 ,180.
    servo(servo1, 0)  
    time.sleep(0.5)
    servo(servo1, 90)
    time.sleep(0.5)
    servo(servo1, 180)
    time.sleep(0.5)
    #Comienza un ciclo que moverá el servo con un dekay de .5 segundos(ahora si infinito hasta que la temperatura cambie)
    for i in range(0, 180, 10):
        servo(servo1, i)
        time.sleep(0.5)
    print("Regado completamente")
  else:
    print("Temperatura Ambiente Detectada")
    time.sleep(5)

def get_humidity():
  sensor.measure()
  humidity = sensor.humidity()
  current_humidity= sensor.humidity()
  print("Humedad actual:", current_humidity, "%")
  time.sleep(5)

get_temperature()
get_humidity()

#Nos conectamos a Wifi
if conectarWIFI("Wokwi-GUEST",""):
    print("")
    print("Conectandome a MQTT ")
    print("Conexión exitosa!!")
    print("")
    print("Datos de la red\n(IP/netmask/gw/DNS):\n",miRed.ifconfig())
    print("")
    print("Ya estas conectado a la Red ✓")
    pixel = NeoPixel(Pin(13),16)
    pixel.fill((0, 128, 0))  # verde
    pixel.write()
    lcd.clear()
    lcd.move_to(0,0)
    lcd.putstr("Ya estas conectado a la Red✓")
    print("")
    print("\n- - - - - - - - - - Sistema de Riego - - - - - - - - - -")
    pixel = NeoPixel(Pin(13),16)
    pixel.fill((0, 128, 0))  # verde
    pixel.write()

    # Lectura del sensor DHT
    sensor.measure()
    temp = sensor.temperature()
    hum = sensor.humidity()

    print("")
    client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER,user=MQTT_USER, password=MQTT_PASSWORD)
    client.connect()

    # Actualización de la pantalla OLED
    update_oled(temp, hum)
    
    if (sensor.temperature() <= 25):
        print("La temperatura está fuera del rango ambiente (20 - 25 grados)")
        print("Riegue el cultivo")
        #El servo tomas las posiciones 0, 90 ,180.
        servo(servo1, 0)  
        time.sleep(0.5)
        servo(servo1, 90)
        time.sleep(0.5)
        servo(servo1, 180)
        time.sleep(0.5)
        #Comienza un ciclo que moverá el servo con un dekay de .5 segundos(ahora si infinito hasta que la temperatura cambie)
        for i in range(0, 180, 10):
            servo(servo1, i)
            time.sleep(0.5)
        print("Regado completamente")
    else:
        print("Temperatura Ambiente Detectada")

    weather = ""
    print('''    |--------------------------|
    | Condicion metereologica  |
    |--------------------------|''')
    sensor.measure()
    
    mensaje = ujson.dumps({
        "temperatura" : sensor.temperature(),
        "humedad" : sensor.humidity(),
    })
    if mensaje != weather:
        print("")
        print("\nActualizando ..............")
        print("Reportando a MQTT {}:\n{}".format(MQTT_TOPIC, mensaje))
        client.publish(MQTT_TOPIC, mensaje)
        weather = mensaje

    @bot.add_message_handler("Menu")
    def help(update):
        update.reply("Menu\n  Activar sistema: On\n  Desactivar sistema: Off\n  Estado del led : Estado\n  Temperatura : Tem")
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("Menu")
        print('''        |---------------------------|
        |           Menu            |
        |---------------------------|
        |  Activar sistema: On      |
        |  Desactivar sistema: Off  |
        |  Estado del led : Estado  |
        |  Temperatura : Tem        |
        |---------------------------|''')
        pixel = NeoPixel(Pin(13),16)
        pixel.fill((255, 255, 0)) #Amarillo
        pixel.write()
    
    @bot.add_message_handler("On")
    def help(update):
        rele.value(1)
        print("")
        update.reply("Sistema de agua Activado")
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("Sistema de agua Ativado")
        print("Sistema de agua Activado")
        pixel = NeoPixel(Pin(13),16)
        pixel.fill((0, 128, 128))  # Teal
        pixel.write()
        # Lectura del sensor DHT
        sensor.measure()
        temp = sensor.temperature()
        hum = sensor.humidity()
        # Actualización de la pantalla OLED
        update_oled(temp, hum)

    @bot.add_message_handler("Off")
    def help(update):
        rele.value(0)
        update.reply("Sistema de agua Desactivado")
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("Sistema de agua Desactivado")
        print("")
        print("Sistema de agua Apagado")
        pixel = NeoPixel(Pin(13),16)
        pixel.fill((0,0,0))
        pixel.write()
        lcd.clear()
        oled.fill(0)
        oled.show()

    @bot.add_message_handler('Estado')
    def help(update):
        print("")
        print("Estado de las Bombas de agua")
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("Estado de las Bombas de agua:")
        lectura=rele.value()
        if lectura==0:
            update.reply("La Bomba esta Apagada")
            print("La Bomba esta Apagada")
            lcd.clear()
            lcd.move_to(0,0)
            lcd.putstr("La Bomba esta Apagada")
            pixel = NeoPixel(Pin(13),16)
            pixel.fill((0,0,0))
            pixel.write()
        else:
            update.reply("La Bomba esta Encendida")
            print("La Bomba esta Encendida")
            lcd.clear()
            lcd.move_to(0,0)
            lcd.putstr("La Bomba esta Encendida")
            pixel = NeoPixel(Pin(13),16)
            pixel.fill((0, 128, 128)) #Teal
            pixel.write()
    
    @bot.add_message_handler('Tem')
    def help(update):
        lcd.clear()
        lcd.move_to(0,0)
        lcd.putstr("Temperatura")
        weather = ""
        sensor.measure()
        mensaje = ujson.dumps({
            "temperatura" : sensor.temperature(),
        })
        if mensaje != weather:
            print("Temperatura {}:{}".format(MQTT_TOPIC, mensaje))
            client.publish(MQTT_TOPIC, mensaje)
            weather = mensaje
            update.reply("La temperatura es " + str(mensaje))
            if (sensor.temperature() <= 25):
                print("La temperatura está fuera del rango ambiente (20 - 25 grados)")
                print("Riegue el cultivo")
            else:
                print("Temperatura Ambiente Detectada")
        
        pixel = NeoPixel(Pin(13),16)
        pixel.fill((0,0,255)) #Azul
        pixel.write()

    bot.start_loop() 

else:
    print("Error al conectar")
    pixel.fill((255, 0, 0))  # Rojo
    pixel.write()
    time.sleep(2)
    pixel.fill((0, 0, 0))  # Apagar led
    pixel.write()
NOCOMNCVCCGNDINLED1PWRRelay Module