import paho.mqtt.client as mqtt import time # --- Configuración del Broker --- BROKER_ADDRESS = "test.mosquitto.org" BROKER_PORT = 1883 # Puerto estándar para MQTT sin cifrado (Non-TLS) TOPIC = "/ProtcolosIoT/QoS2_Test" # Cambiado el tópico para ser más específico de la prueba QOS = 2 # Calidad de Servicio (Quality of Service): ¡Cambiado a 2! # --- Mensaje a Publicar --- PAYLOAD = "Publicando mensaje de prueba con QoS 2 y esperando confirmación de entrega (PUBCOMP)." # Bandera para saber si la publicación con QoS 2 ha sido completada (PUBCOMP recibido) pub_complete = False def on_connect(client, userdata, flags, rc): """Función que se llama cuando el cliente se conecta al broker.""" global pub_complete if rc == 0: print("Conexión exitosa al broker.") # La publicación se realiza una vez que la conexión es exitosa print(f"Intentando publicar: Tópico: {TOPIC}, QoS: {QOS}") # Publicar el mensaje # El resultado ahora incluye el mid (message ID) que es clave para QoS 1 y 2 result, mid = client.publish(TOPIC, PAYLOAD, qos=QOS, retain=False) if result == mqtt.MQTT_ERR_SUCCESS: print(f"[PUBLICADO INICIADO] ID de Mensaje (mid): {mid}") # NO nos desconectamos aquí. Esperaremos 'on_publish'. else: print(f"Error al intentar publicar. Código: {result}") client.disconnect() # Desconectarse en caso de error inmediato else: print(f"Error de conexión. Código: {rc}") # --- Nueva función para manejar la publicación --- def on_publish(client, userdata, mid): """ Función que se llama cuando la publicación es completada por el broker. En QoS 2, esta función se llama cuando el publicador recibe el mensaje 'PUBCOMP' del broker, indicando que el mensaje fue entregado *exactamente una vez* a los suscriptores. """ global pub_complete print(f"\n--- Publicación QoS 2 Completada ---") print(f"Confirmación (PUBCOMP) recibida para ID de Mensaje: {mid}") print(f"[MENSAJE ENTREGADO]: {PAYLOAD}") print("El broker ha confirmado la entrega EXACTA a los suscriptores (QoS 2).") # Establecer la bandera para salir del bucle pub_complete = True # Se podría desconectar aquí si solo se quiere publicar una vez # client.disconnect() # Crear una instancia del cliente client = mqtt.Client(client_id="PythonPublisherClient_QoS2") # Asignar las funciones de conexión y publicación client.on_connect = on_connect client.on_publish = on_publish # ¡Función clave para la confirmación de entrega! # Conectar al broker (esto es asíncrono) try: print(f"Conectando a {BROKER_ADDRESS}:{BROKER_PORT}...") client.connect(BROKER_ADDRESS, BROKER_PORT, 60) # Iniciar el bucle de red en un hilo separado client.loop_start() print("\nCliente en bucle. Esperando la confirmación de la entrega (PUBCOMP)...") # Bloqueamos el hilo principal hasta que se reciba el PUBCOMP timeout = 15 # Tiempo máximo de espera en segundos start_time = time.time() while not pub_complete and (time.time() - start_time < timeout): time.sleep(0.1) # Esperar un poco print("\n-------------------------------------") if pub_complete: print("¡Proceso de publicación QoS 2 completado con éxito!") else: print("¡Tiempo de espera agotado! No se recibió la confirmación completa (PUBCOMP).") # Detener el bucle de red y desconectar client.loop_stop() client.disconnect() print("Cliente desconectado.") except Exception as e: print(f"No se pudo conectar al broker o hubo un error durante la ejecución: {e}")