import network
import time
import machine
import neopixel
import dht  
from machine import Pin
from utime import sleep
from hd44780 import HD44780
from umqtt.simple import MQTTClient
import ujson

# Настройки MQTT
MQTT_CLIENT_ID = "esp-neopixel-dht"
# MQTT_BROKER = "test.e-ln.ru"
MQTT_BROKER = "broker.hivemq.com"
MQTT_PORT = 1883
MQTT_TOPIC_SUB = "led_ring"  # Топик для управления светодиодами
MQTT_TOPIC_WEATHER = "dmitiy-belayev-wether"  # Топик для публикации погоды

# Настройки NeoPixel
NUM_PIXELS = 16  
DATA_PIN = 18     
np = neopixel.NeoPixel(Pin(DATA_PIN), NUM_PIXELS)

# Настройка DHT-датчика
sensor_pin = Pin(22) 
sensor = dht.DHT22(sensor_pin)

# Настройка LCD дисплея
lcd = HD44780(rs=Pin(12), enable=Pin(13), d4=Pin(14), d5=Pin(27), d6=Pin(26), d7=Pin(25)) 
lcd.init()
lcd.clear()

# Настройка светодиодов
led_red_pin = Pin(2, Pin.OUT)   # Красный светодиод
led_blue_pin = Pin(21, Pin.OUT)  # Синий светодиод

# Подключение к Wi-Fi
def connect_wifi(ssid, password):
    sta_if = network.WLAN(network.STA_IF)
    sta_if.active(True)
    sta_if.connect(ssid, password)
    while not sta_if.isconnected():
        time.sleep(0.1)
    print("Connected to Wi-Fi:", sta_if.ifconfig())

# Управление светодиодами
def set_leds(color, count):
    rgb = {
        "red": (255, 0, 0),
        "green": (0, 255, 0),
        "blue": (0, 0, 255)
    }
    led_color = rgb.get(color.lower(), (0, 0, 0))
    for i in range(NUM_PIXELS):
        np[i] = led_color if i < count else (0, 0, 0)
    np.write()

# Обработчик сообщений MQTT
def sub_cb(topic, msg):
    print(f"Received message: {msg} on topic: {topic.decode()}")
    try:
        data = ujson.loads(msg)
        color = data.get("color", "off")
        count = data.get("count", 1)
        if 1 <= count <= NUM_PIXELS:
            set_leds(color, count)
        else:
            print("Invalid count value")
    except Exception as e:
        print("Error handling message:", e)

# Подключение к MQTT
def connect_mqtt():
    client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, MQTT_PORT)
    client.set_callback(sub_cb)
    try:
        client.connect()
        client.subscribe(MQTT_TOPIC_SUB.encode())  # Преобразуем топик в байты
        print("Connected to MQTT and subscribed to topic:", MQTT_TOPIC_SUB)
    except Exception as e:
        print("MQTT connection error:", e)
        time.sleep(1)
    return client

# Управление индикаторными светодиодами в зависимости от температуры и влажности
def control_indicator_leds(temp, hum):
    if temp < 17 or temp > 25:
        led_red_pin.on()   # Включаем красный светодиод
    else:
        led_red_pin.off()  # Выключаем красный светодиод

    if hum < 40 or hum > 60:
        led_blue_pin.on()   # Включаем синий светодиод
    else:
        led_blue_pin.off()   # Выключаем синий светодиод

try:
    connect_wifi('Wokwi-GUEST', '')
    client = connect_mqtt()
    
    prev_weather = ""
    
    while True:
        # Проверка сообщений MQTT
        try:
            client.check_msg()
            
            # Считывание данных с DHT22 и публикация в MQTT
            sensor.measure() 
            temp = sensor.temperature() 
            hum = sensor.humidity() 
            
            # Печать данных в консоль и на LCD-дисплей
            print('Temperature: %3.1f C' % temp) 
            print('Humidity: %3.1f %%' % hum) 
            lcd.move_to(0, 0) 
            lcd.putstr('Temp: %3.1f C' % temp) 
            lcd.move_to(0, 1)  
            lcd.putstr('Hum: %3.1f %%' % hum)  

            # Формирование сообщения для MQTT
            message = ujson.dumps({
                "temp": temp,
                "humidity": hum,
            })
            
            # Публикация данных о погоде только при изменении
            if message != prev_weather:
                print("Reporting weather to MQTT topic {}: {}".format(MQTT_TOPIC_WEATHER, message))
                client.publish(MQTT_TOPIC_WEATHER, message)
                prev_weather = message
            
            # Управление индикаторными светодиодами в зависимости от показателей температуры и влажности
            control_indicator_leds(temp, hum)

            sleep(2)  # Обновление каждые 5 секунд
            
        except Exception as e:
            print("Error in main loop:", e)
            time.sleep(1)

except Exception as e:
    print("General error:", e)

finally:
    client.disconnect()
    print("Disconnected from MQTT broker.")