
El protocolo MQTT es un protocolo de conectividad de máquina a máquina (M2M). Diseñado como un transporte de mensajería de publicación/suscripción extremadamente liviano, es útil para conexiones con ubicaciones remotas donde se requiere poco código y/o el ancho de banda de la red es un bien escaso.
El protocolo generalmente se ejecuta sobre TCP / IP; sin embargo, cualquier protocolo de red que proporcione conexiones bidireccionales ordenadas y sin pérdidas puede admitir MQTT. RabbbitMQ ofrece MQTT y entre las caracteristicas soportadas se describen a continuación:
* Publicación y consumo de QoS0 y QoS1
* Publicación de QoS2
* TLS
* Mensajes retenidos con backends
Para habilitar el protocolo MQTT sobre RabbitMQ lo primero que se debe realizar es habilitar el Plugin. En este taller se describe los pasos para habilitar RabbitMQ sobre Linux. Adicionalmente, se describe un ejemplo de código publish-subscribe en Python y usando el módulo Paho.
## Habilitar Plugin MQTT en RabbitMQ
El complemento MQTT está incluido en la distribución RabbitMQ. Antes de que los clientes puedan conectarse correctamente, debe habilitarse mediante rabbitmq-plugins.
```
rabbitmq-plugins enable rabbitmq_mqtt
```
1. Antes de digitar la instrucción anterior, compruebe si el servicio del protocolo MQTT está ejecutándose en su servidor broker local. Para realizar dicha acción inicie sesión con el usuario guest y contraseña guest y compruebe los servicios y puertos activos.
En la siguiente figura se muestra la solución instalada desde un servidor en la nube. La versión de RabbitMQ es la 3.12 mientras que Erlang es la versión 25.3.2.2.

En las figuras se muestran los puertos y servicios que se están ejecutando en el servidor nube y local.

2. Utilice un programa de conexión remota (Ejemplo: Solar Putty) y en modo root habilite el plugin que habilita el puerto de mqtt. Para este propósito el comando utilizado es el siguiente:
```
rabbitmq-plugins enable rabbitmq_mqtt
```
3. En la figura siguiente se muestra la respuesta luego de haber habilitado el puerto.

6. Seguidamente, crearemos un nuevo usuario con su respectivo permisos. Para dicho propósito digitaremos las siguientes sentencias:
```
rabbitmqctl add_user mqtt-test mqtt-test
rabbitmqctl set_permissions -p / mqtt-test ".*" ".*" ".*"
rabbitmqctl set_user_tags mqtt-test management
```
En la figura siguiente se muestra la respuesta obtenida luego de la ejecución de dichos comandos. La acción anterior permite crear el usuario mqtt-test con la contraseña mqtt-test

7. Si su servidor se encuentra en un computador remoto configure los accesos del firewall de windows para que pueda permitir el puerto 1883.
9. Finalmente, comprueba el servidor y verifique que se encuentre activo el protocolo mqtt y el puerto 1883 en el cual se encuentra escuchando. Inicie sesión con el usuario guest contraseña guest. Luego inicie sesión con el usuario mqtt-test con su contraseña respectiva para validar lo realizado.
En las siguientes figuras se muestra la configuración de la versión 3.11 y 3.12. Local y en la nube respectivamente.


:::info
:bulb: **TimeoutError: [WinError 10060]**: Se produjo un error durante el intento de conexión ya que la parte conectada no respondió adecuadamente tras un periodo de tiempo, o bien se produjo un error en la conexión establecida ya que el host conectado no ha podido responder.
:::
## Instalación del paquete PAHO
El paquete Paho proporciona una clase cliente que permite que las aplicaciones se conecten a un agente MQTT para publicar mensajes, suscribirse a temas y recibir mensajes publicados. También proporciona algunas funciones auxiliares para que la publicación de mensajes únicos en un servidor MQTT sea muy sencilla.
Es compatible con Python 2.7.9+ o 3.6+.
Para instalar dicha librería lo puede realizar mediante el comando pip para instalaciones en donde no se usa anaconda. O con el comando conda. A continuación se indica las das opciones:
```
pip install paho-mqtt
```
```
conda install -c conda-forge paho-mqtt
```
Está ultima opción se la realiza mediante la consola de anaconda. En las figuras siguientes se muestra la instalación del paquete paho-mqtt mediante la consola de anaconda.


## Código del subscribe - consumidor
Copie el siguiente código en un nuevo archivo denominado `mqtt-subscribe.py` y guarde en una carpeta denominada uleam-iot o en su proyecto de preferencia .
```Python=
import random
import paho.mqtt.client as mqtt
mClientId = f'python-mqtt-{random.randint(0, 1000)}'
mBroker = '127.0.0.1'
mPort = 1883
mTopic = "uleam/fcvt/#"
mUsername = 'mqtt-test'
mPassword = 'mqtt-test'
def connect_mqtt() -> mqtt:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt.Client(mClientId)
client.username_pw_set(mUsername, mPassword)
client.on_connect = on_connect
client.connect(mBroker, mPort)
return client
def subscribe(client: mqtt):
def on_message(client, userdata, msg):
print(f"Received `{msg.payload.decode()}` from `{msg.topic}` topic")
#mData=json.loads(msg.payload)#Decode the JSON string
#print(mData)
client.subscribe(mTopic)
client.on_message = on_message
def run():
client = connect_mqtt()
subscribe(client)
client.loop_forever()
if __name__ == '__main__':
run()
```
En general el código suscriptor (consumidor) proporciona los métodos conectar, y suscriptor. El método suscriptor, define un método que muestra el mensaje y es el que se registra a un tópico específico.
## Configuración del publicador - publisher
El ejemplo siguiente sigue el mismo contexto de los casos anteriores. Copie el código en un nuevo archivo denominado `mqtt-publisher-01.py` y guarde en su proyecto.
```Python=
import random
import paho.mqtt.client as mqtt
mClientId = f'python-mqtt-{random.randint(0, 1000)}'
mBroker = '127.0.0.1'
mPort = 1883
mTopic = "uleam/fcvt/G0"
mUsername = 'mqtt-test'
mPassword = 'mqtt-test'
def connect_mqtt() -> mqtt:
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt.Client(mClientId)
client.username_pw_set(mUsername, mPassword)
client.on_connect = on_connect
client.connect(mBroker, mPort)
return client
client = connect_mqtt()
client.loop_start()
try:
while True:
mensaje = input("Ingrese un mensaje: ")
client.publish(mTopic, mensaje) # Publicar el mensaje en un tema específico
except KeyboardInterrupt:
pass
# Desconexión del cliente MQTT
client.loop_stop()
client.disconnect()
```
Siguiendo el contexto anterior, en el código `mqtt-publisher.py` adicional al método conectar, se define el método publish, este permite enviar (dado un tópico o tema) el mensaje al broker MQTT.
## Ejecución del programa
Para validar la ejecución de los códigos publish/subscribe se sigue el mismo procedimiento que el taller de sockets. Ejecute el consumidor y luego ejecute el publicador. Verifique los resultados. Recuerde que debe usar dos consolas para validar lo anterior.
:::info
:bulb: **Tarea**: Se le solicita que realice lo siguiente:
1. Copie el programa mqtt-publisher-01 y adapte dicho código para que permita enviar la temperatura, humedad, latitud, longitud, y fecha-hora mediante un formato JSON.
2. Mediante su cuenta [CloudAMQP] haga los cambios respectivos y verifique el envío y recepción del mensaje usando MQTT.
:::