import math
import network
import time
import utime

from dht import DHT22
from umqtt.simple import MQTTClient
from machine import Pin, PWM, ADC
from servo import Servo

# LED
# led = Pin(22, Pin.OUT)
led_pwm = PWM(Pin(22), freq=5000)   # 5k Hz
led_pwm.duty(0)
# Configurar el ADC
adc = ADC(Pin(34))                  # Debe ser PIN ADC en el microcontrolador
adc.atten(ADC.ATTN_11DB)            # Voltaje: 0 - 3.3V
adc.width(ADC.WIDTH_10BIT)          # Resolución 10 bits: 0 - 1023

duty = 1023
led = False
led_button = Pin(0, Pin.IN)

# Sensor DHT22
sensor = DHT22(Pin(21))

# Servo motor for Door
# sg90 = PWM(Pin(18, mode=Pin.OUT))
# sg90.freq(50)
door = Servo(pin=18)
door_button = Pin(5, Pin.IN)
door_reed_switch = Pin(17, Pin.IN)
last_door_status = 0
door_action = -1
door.move(0)
time.sleep(1)

wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('Internet Movil Claro_13B2', '02081774')
# wlan.connect('SOMOS OFICINA-2.4G', '43169781')
print('Connecting to WiFi...', end='')

while not wlan.isconnected():
    print('.', end='')
    time.sleep(0.1)

print('Connected!')
print('network config:', wlan.ipconfig('addr4'))

# MQTT Server Parameters
MQTT_CLIENT_ID = 'esp32-mqtt'
MQTT_BROKER = 'test.mosquitto.org'
# Topics
MQTT_DOOR_TOPIC = 'ou/room/door'
MQTT_DKEY_TOPIC = 'ou/room/door/key'
MQTT_LED_TOPIC = 'ou/room/living/led'
MQTT_LED_BRIGHT_TOPIC = 'ou/room/living/led/bright'

MQTT_TEMPERATURE_TOPIC = 'ou/room/env/temperature'
MQTT_HUMEDITY_TOPIC = 'ou/room/env/humedity'


get_bright = lambda adc_value: 10 * math.ceil(float((adc_value/1023)*100)/10)

def timer(time, last_time):
    diff = utime.ticks_diff(utime.ticks_ms(), last_time)
    wait = time * 1000
    is_out_of_range = diff >= wait
    wait_time = round((wait - diff)/1000)
    return is_out_of_range

def action_door():
    global door_action
    door_action = -door_action
    print(f'Actioning door... action status: {door_action}')

    if door_action > 0:
        door.move(90)
    else:
        door.move(0)

    print('Door actioned!')

# --- Callback para mensajes entrantes ---
def receive(topic, msg):
    print('Message in topic:', topic.decode())
    print('Content:', msg.decode())

    topic = topic.decode()
    msg = msg.decode()
    global duty, led, door_action

    if topic == 'ou/room/living/led':
        led = bool(int(msg))

        if led:
            print('Led: On')
            led_pwm.duty(duty)
        else:
            print('Led: Off')
            led_pwm.duty(0)

    elif topic == 'ou/room/living/led/bright':
        # Rango duty para ESP32: 0 - 1023
        bright = round(float(msg))/100
        duty = round(1023 * bright)
        print(f'Led bright: {msg}%')
        print(f'Duty: {duty}')

        if led:
            led_pwm.duty(duty)

    elif topic == 'ou/room/door/key':
        action_door()

print('Connecting to MQTT server... ', end='')
client = MQTTClient(MQTT_CLIENT_ID, MQTT_BROKER)
client.set_callback(receive)
client.connect()
client.subscribe(MQTT_LED_TOPIC)
client.subscribe(MQTT_LED_BRIGHT_TOPIC)
client.subscribe(MQTT_DKEY_TOPIC)
print("Connected!")

sensor.measure()
T = sensor.temperature()
H = sensor.humidity()

led_button_last_state = led_button.value()
door_button_last_state = door_button.value()
adc_last_state = get_bright(adc.read())

DHT_last_time = utime.ticks_ms()
counter_last_time = utime.ticks_ms()

# Sync local and remote status
client.publish(MQTT_LED_TOPIC, '0'.encode())
client.publish(MQTT_LED_BRIGHT_TOPIC, str(adc_last_state).encode())
client.publish(MQTT_DOOR_TOPIC, str(last_door_status).encode())

while True:
    client.check_msg()
    current_door_status = door_reed_switch.value()
    led_button_state = led_button.value()
    door_button_state = door_button.value()
    adc_state = get_bright(adc.read())

    if adc_state != adc_last_state and adc_state >= 10:
        print(f'ADC Value: {adc_state} - Last ADC: {adc_last_state}')
        adc_last_state = adc_state
        client.publish(MQTT_LED_BRIGHT_TOPIC, str(adc_state).encode())

    if current_door_status != last_door_status:
        client.publish(MQTT_DOOR_TOPIC, str(current_door_status).encode())
        last_door_status = current_door_status

        if current_door_status == 0:
            print('Closed door')
        else:
            print("Opened door")

    if (led_button_last_state == 1 and led_button_state == 0):
        if led:
            print('Led: Off')
            led_pwm.duty(0)
            led = False
            client.publish(MQTT_LED_TOPIC, '0'.encode())
        else:
            print(f'Led: On - Duty: {duty}')
            led_pwm.duty(duty)
            led = True
            client.publish(MQTT_LED_TOPIC, '1'.encode())

    if (door_button_last_state == 1 and door_button_state == 0):
        action_door()

    led_button_last_state = led_button_state
    door_button_last_state = door_button_state
    
    if timer(10, DHT_last_time):
        sensor.measure()
        T = sensor.temperature()
        H = sensor.humidity()
        DHT_last_time = utime.ticks_ms()
        
        print('Measure!')
        print('----------------------')
        print(f'Temperature: {T}°C')
        print(f'Humidity: {H}% \n')

        client.publish(MQTT_TEMPERATURE_TOPIC, str(T).encode())
        client.publish(MQTT_HUMEDITY_TOPIC, str(H).encode())

    time.sleep(0.1)
$abcdeabcde151015202530354045505560fghijfghij