from umqtt.simple import MQTTClient
import network
from machine import Pin, PWM
from utime import sleep
import ujson
from hcsr04 import HCSR04

def handle_interrupt(pin):
    global motion
    motion = True

switch = Pin(26, Pin.IN)
pir = Pin(23, Pin.IN)
pir.irq(trigger=Pin.IRQ_RISING, handler=handle_interrupt)

sensor1 = HCSR04(trigger_pin=14, echo_pin=27)
sensor2 = HCSR04(trigger_pin=21, echo_pin=19)

buzzer = PWM(Pin(13), duty=0)
led = Pin(15, Pin.OUT)
servoMotor = PWM(Pin(12, mode=Pin.OUT), freq=50)

def publish(action, address, status, activation, response):
    try:
        print("action: ", action, "Address: ", address, " | ", "status: ", status, " | ", "activation: ", activation, " | ", "response: ", response)
        client.publish(MQTT_TOPIC_SEND, ujson.dumps({"action": action, "address": address, "status" : status, "activation": activation, "response": response}))
    except OSError as e:
        print("Erro ao publicar mensagem:", e)

def mqtt_callback(topic, msg):
    print("Received message: ", msg)
    msg_str = msg.decode('utf-8')
    data = ujson.loads(msg_str)

    global pir_init, ldr_init, servo_init, buzzer_init, switch_init, led_init

    
    if 'Connect' in data:
        if data['Connect'] == 'MOT3003':
            pir_init = True
            publish("publish", "MOT3003", "Conectado", "On", "Sem resposta")

        if data['Connect'] == 'HC-SR04':
            ldr_init = True
            publish("publish", "HC-SR04", "Conectado", "On", "Sem resposta")
            
        if data['Connect'] == 'SWITCH':
            switch_init = True
            publish("publish", "SWITCH", "Conectado", "On", "Sem resposta")

        if data['Connect'] == 'BUZZER-123':
            buzzer_init = True
            publish("publish", "BUZZER-123", "Conectado", "On", "Sem resposta")

        if data['Connect'] == 'SERV-789':
            servo_init = True
            publish("publish", "SERV-789", "Conectado", "On", "Sem resposta")

        if data['Connect'] == 'LED':
            led_init = True
            publish("publish", "LED", "Conectado", "On", "Sem resposta")

    if 'Disconnect' in data:
        if data['Disconnect'] == 'MOT3003':
            pir_init = False
            publish("publish", "MOT3003", "Desconectado", "Off", "Sem resposta")

        if data['Disconnect'] == 'HC-SR04':
            ldr_init = False
            publish("publish", "HC-SR04", "Desconectado", "Off", "Sem resposta")
        
        if data['Disconnect'] == 'SWITCH':
            switch_init = False
            publish("publish", "SWITCH", "Desconectado", "Off", "Sem resposta")

        if data['Disconnect'] == 'BUZZER-123':
            buzzer_init = False
            publish("publish", "BUZZER-123", "Desconectado", "Off", "Sem resposta")

        if data['Disconnect'] == 'SERV-789':
            servo_init = False
            publish("publish", "SERV-789", "Desconectado", "Off", "Sem resposta")

        if data['Disconnect'] == 'LED':
            led_init = False
            publish("publish", "LED", "Desconectado", "Off", "Sem resposta")

# Global variable declaration
motion = False
pir_init = False
ldr_init = False
servo_init = False
buzzer_init = False

MQTT_CLIENT_ID = "connect_demo"
MQTT_BROKER    = "broker.mqttdashboard.com"
MQTT_TOPIC_SEND = "experiencia/send"
MQTT_TOPIC_RECEIVE = "experiencia/receive" 
MQTT_USER      = "crystofer"
MQTT_PASSWORD  = "crystofer"
LDR_THRESHOLD = 20 

# Connect to WiFi
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="")
    sleep(0.1)
print(" Conectado!")

# Connect to MQTT server
print("Connecting to MQTT server... ", end="")
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER, user=MQTT_USER, password=MQTT_PASSWORD)
client.set_callback(mqtt_callback)
client.connect()
print("Conectado!")
client.subscribe(MQTT_TOPIC_RECEIVE)

while True:
    try:
        client.check_msg()
        sleep(1)
        led.on()
    except OSError as e:
        print("Erro ao verificar mensagem:", e)

    if pir_init:
        if motion:
            publish("publish_response", "MOT3003", "Conectado", "On", "Movimento detectado")

            if buzzer_init:
                buzzer.duty(512)
                publish("publish_response", "BUZZER-123", "Conectado", "On",  "Buzina ativada")

            if servo_init:
                servoMotor.duty(75)
                publish("publish_response", "SERV-789", "Conectado", "On",  "Câmera ligada na posição padrão")

            sleep(10)
            motion = False

            publish("publish_response", "MOT3003", "Conectado", "On",  "Nenhum movimento detectado")

            if buzzer_init:
                buzzer.duty(0)
                publish("publish_response", "BUZZER-123", "Conectado", "On",  "Buzina desativada")

            if servo_init:
                
                publish("publish_response", "SERV-789", "Conectado", "On",  "Câmera desligada")

    if ldr_init:        
        if sensor1.distance_cm() < LDR_THRESHOLD:
            publish("publish_response", "HC-SR04", "Conectado", "On",  "Movimento no sensor 1")

            if buzzer_init:
                buzzer.duty(512)
                publish("publish_response", "BUZZER-123", "Conectado", "On",  "Buzina ativada")

            if servo_init:
                servoMotor.duty(50)
                publish("publish_response", "SERV-789", "Conectado", "On",  "Câmera ligada na posição 1")

            sleep(10)

            publish("publish_response", "HC-SR04", "Conectado", "On",  "Nenhum movimento detectado")

            if buzzer_init:
                buzzer.duty(0)
                publish("publish_response", "BUZZER-123", "Conectado", "On",  "Buzina desativada")

            if servo_init:
                servoMotor.duty(75)
                publish("publish_response", "SERV-789", "Conectado", "On",  "Câmera desligada")

        if sensor2.distance_cm() < LDR_THRESHOLD:
            publish("publish_response", "HC-SR04", "Conectado", "On",  "Movimento no sensor 2")

            if buzzer_init:
                buzzer.duty(512)
                publish("publish_response", "BUZZER-123", "Conectado", "On",  "Buzina ativada")

            if servo_init:
                servoMotor.duty(100)
                publish("publish_response", "SERV-789", "Conectado", "On",  "Câmera ligada na posição 2")

            sleep(10)

            publish("publish_response", "HC-SR04", "Conectado", "On",  "Nenhum movimento detectado")

            if buzzer_init:
                buzzer.duty(0)
                publish("publish_response", "BUZZER-123", "Conectado", "On",  "Buzina desativada")

            if servo_init:
                servoMotor.duty(75)
                publish("publish_response", "SERV-789", "Conectado", "On",  "Câmera desligada")

    sleep(1)