import machine
import time
import network
import dht
import neopixel
from BlynkLib import Blynk
from umqtt.simple import MQTTClient

# WiFi credentials
wifi_ssid = 'Wokwi-GUEST'
wifi_password = ''

# Blynk credentials
BLYNK_AUTH = 'GRAlyPkQtNZoHEp1Qth6q9iNA5K5IDBi'
BLYNK_TEMPLATE_ID = 'TMPL6bjQpjsvG'
BLYNK_TEMPLATE_NAME = 'greenhouse'

# MQTT credentials
MQTT_BROKER = 'mqtt-dashboard.com'
MQTT_PORT = 1883
MQTT_TOPIC_TEMP = 'greenhouse/temperature'
MQTT_TOPIC_HUMIDITY = 'greenhouse/humidity'

# Connect to WiFi
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(wifi_ssid, wifi_password)

while not station.isconnected():
    pass

print("Connected to WiFi")

# Initialize Blynk
blynk = Blynk(BLYNK_AUTH)

# Initialize MQTT client
client = MQTTClient('client_id', MQTT_BROKER, port=MQTT_PORT)

def connect_mqtt():
    try:
        client.connect()
        print("Connected to MQTT Broker")
    except OSError as e:
        print("Failed to connect to MQTT Broker. Retrying...")
        time.sleep(5)
        connect_mqtt()

connect_mqtt()

# Setup DHT22 sensor
dht22 = dht.DHT22(machine.Pin(4))

# Setup NeoPixel strip
neo_pin = machine.Pin(18)
num_pixels = 16  # Adjust this to the number of pixels in your NeoPixel strip
np = neopixel.NeoPixel(neo_pin, num_pixels)

def read_sensors():
    dht22.measure()
    temp = dht22.temperature()
    humidity = dht22.humidity()
    return temp, humidity

def set_neopixel_color(temp):
    if temp > 30:
        color = (255, 0, 0)  # Red
    elif temp < 20:
        color = (0, 0, 255)  # Blue
    else:
        color = (0, 255, 0)  # Green
    
    for i in range(num_pixels):
        np[i] = color
    np.write()

while True:
    try:
        blynk.run()
        temp, humidity = read_sensors()
        blynk.virtual_write(0, temp)
        blynk.virtual_write(1, humidity)
        set_neopixel_color(temp)
        
        # Publish data to MQTT broker with error handling
        try:
            client.publish(MQTT_TOPIC_TEMP, str(temp))
            client.publish(MQTT_TOPIC_HUMIDITY, str(humidity))
        except OSError as e:
            print("Failed to publish to MQTT Broker. Reconnecting...")
            connect_mqtt()

        # Display data on serial monitor
        print("Temperature:", temp, "°C")
        print("Humidity:", humidity, "%")
        
        time.sleep(3)  # Update every 3 seconds

    except Exception as e:
        print("An error occurred:", e)
        time.sleep(5)