import network
import time
from machine import Pin, PWM
import dht
import ujson
from umqtt.simple import MQTTClient

# MQTT Server Parameters
MQTT_CLIENT_ID = "micropython-compost-demo"
MQTT_BROKER = "broker.mqttdashboard.com"
MQTT_PORT = 1883
MQTT_USER = ""
MQTT_PASSWORD = ""
MQTT_TOPIC_TEMP = "wokwi-compost/temp"
MQTT_TOPIC_HUMIDITY = "wokwi-compost/humidity"
MQTT_TOPIC_DISTANCE = "wokwi-compost/level"
MQTT_TOPIC_MOTION = "wokwi-compost/motion"
MQTT_TOPIC_SERVO = "wokwi-compost/servo"
MQTT_TOPIC_WARNING = "wokwi-compost/warning"

# Initialize DHT22 sensor
dht_sensor = dht.DHT22(Pin(15))

# Initialize HC-SR04 sensor
trigger = Pin(2, Pin.OUT)
echo = Pin(4, Pin.IN)

# Initialize PIR sensor
pir_sensor = Pin(5, Pin.IN)

# Initialize Servo motor
servo = PWM(Pin(16), freq=50)
servo.duty_u16(8000)

def get_distance():
    trigger.value(0)
    time.sleep_us(2)
    trigger.value(1)
    time.sleep_us(10)
    trigger.value(0)
    while echo.value() == 0:
        pass
    start = time.ticks_us()
    while echo.value() == 1:
        pass
    end = time.ticks_us()
    distance = (time.ticks_diff(end, start) * 0.0343) / 2
    return distance


print("Connecting to WiFi", end="")
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect('Wokwi-GUEST', '')
while not sta_if.isconnected():
    print(".", end="")
    time.sleep(0.1)
print(" Connected!")

print("Connecting to MQTT server... ", end="")
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, port=MQTT_PORT, user=MQTT_USER, password=MQTT_PASSWORD)
client.connect()
print("Connected!")

# Time to keep the bin open in seconds
open_duration = 10
bin_open = False

while True:
    print("Measuring compost conditions... ", end="")

    dht_sensor.measure()
    temp = dht_sensor.temperature()
    humidity = dht_sensor.humidity()
    print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_TEMP, temp))
    client.publish(MQTT_TOPIC_TEMP, ujson.dumps(temp))
    print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_HUMIDITY, humidity))
    client.publish(MQTT_TOPIC_HUMIDITY, ujson.dumps(humidity))

    distance = get_distance()
    print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_DISTANCE, distance))
    client.publish(MQTT_TOPIC_DISTANCE, ujson.dumps(400 - distance))

    motion = pir_sensor.value()
    print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_MOTION, motion))
    client.publish(MQTT_TOPIC_MOTION, ujson.dumps(motion))

    if motion and not bin_open:
        servo_message = "OPENED"
        print("Servo rotated!")

        print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_SERVO, servo_message))
        client.publish(MQTT_TOPIC_SERVO, ujson.dumps(servo_message))
        servo.duty_u16(1800) # Rotate servo to 180 degrees
        bin_open = True
        time.sleep(open_duration)  
        servo.duty_u16(8000)  # Rotate servo back to 0 degrees
        servo_message = "CLOSED"
        print("Servo reset!")
        print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_SERVO, servo_message))
        client.publish(MQTT_TOPIC_SERVO, ujson.dumps(servo_message))
        bin_open = False

    warning_message = ""
    if humidity < 40:
        warning_message = "Humidity too low!"
    elif humidity > 65:
        warning_message = "Humidity too high!"

    if temp < 32:
        warning_message = "Temperature too low!"
    elif temp > 60:
        warning_message = "Temperature too high!"

    if distance < 100:
        warning_message = "BIN FULL"

    print("Reporting to MQTT topic {}: {}".format(MQTT_TOPIC_WARNING, warning_message))
    client.publish(MQTT_TOPIC_WARNING, ujson.dumps(warning_message))

    time.sleep(1)
$abcdeabcde151015202530fghijfghij