# IoT Lab 1: MQTT with Python ###### tags: `RSE` `Labs` > curso 2019/2020 This lab aims to offer you an hands-on experience with MQTT. You will perform experiments that will allow you to learn how to "publish" data and "subscribe" to get data. **All the code necessary for this Lab session is available at [bit.ly/rse2019lab](http://bit.ly/rse2019lab)** in folder `codigo/IoT`. ## Section 1: Basic MQTT #### regarding the clients: In this section you will work with MQTT using the [**MQTT Paho** library](https://www.eclipse.org/paho/clients/python/) for Python. The documentation of the MQTT Paho API is [here](https://www.eclipse.org/paho/clients/python/docs/). You have to first install it using: ``` $ sudo pip3 install paho-mqtt ``` #### regarding the broker: In this session we will use a **public broker**. There are various public brokers (also called `sandboxes`) in the Internet. For example: * `iot.eclipse.org` (https://iot.eclipse.org/getting-started#sandboxes) * `test.mosquitto.org` (http://test.mosquitto.org/) * `broker.hivemq.com` (https://www.hivemq.com/public-mqtt-broker/) A more or less updated list is available here: https://github.com/mqtt/mqtt.github.io/wiki/public_brokers An alternative **local** broker is here: `mqttbroker.grc.upv.es` :::info BTW, it's very easy to install one's own broker (see for example https://mosquitto.org/download/). ::: ### A simple subscriber The code of the simplest subscriber is the one below. ```python= # File: sisub.py import paho.mqtt.client as mqtt THE_BROKER = "test.mosquitto.org" THE_TOPIC = "$SYS/#" CLIENT_ID = "" # The callback for when the client receives a CONNACK # response from the server. def on_connect(client, userdata, flags, rc): print("Connected to ", client._host, "port: ", client._port) print("Flags: ", flags, "returned code: ", rc) client.subscribe(THE_TOPIC, qos=0) # The callback for when a message is received from the server. def on_message(client, userdata, msg): print("sisub: msg received with topic: {} and payload: {}".format(msg.topic, str(msg.payload))) client = mqtt.Client(client_id=CLIENT_ID, clean_session=True, userdata=None, protocol=mqtt.MQTTv311, transport="tcp") client.on_connect = on_connect client.on_message = on_message client.username_pw_set(None, password=None) client.connect(THE_BROKER, port=1883, keepalive=60) # Blocking call that processes network traffic, dispatches callbacks and # handles reconnecting. client.loop_forever() ``` This code connects to the broker `"test.mosquitto.org"` and subscribes to topic `"$SYS/#"`. :::danger 1.- Ejecuta este codigo y explica el resultado obtenido. ::: ### A simple producer The code of the simplest producer is the one below. ```python= # File: sipub.py import random import time import paho.mqtt.client as mqtt THE_BROKER = "test.mosquitto.org" THE_TOPIC = "PMtest/rndvalue" CLIENT_ID = "" # The callback for when the client receives a CONNACK # response from the server. def on_connect(client, userdata, flags, rc): print("Connected to ", client._host, "port: ", client._port) print("Flags: ", flags, "returned code: ", rc) # The callback for when a message is published. def on_publish(client, userdata, mid): print("sipub: msg published (mid={})".format(mid)) client = mqtt.Client(client_id=CLIENT_ID, clean_session=True, userdata=None, protocol=mqtt.MQTTv311, transport="tcp") client.on_connect = on_connect client.on_publish = on_publish client.username_pw_set(None, password=None) client.connect(THE_BROKER, port=1883, keepalive=60) client.loop_start() while True: msg_to_be_sent = random.randint(0, 100) client.publish(THE_TOPIC, payload=msg_to_be_sent, qos=0, retain=False) time.sleep(5) client.loop_stop() ``` This code connects to the broker `"test.mosquitto.org"` and periodically publishes random values to topic `"PMtest/rndvalue"` :::danger 2.- Ejecuta este codigo y explica el resultado obtenido. ::: :::danger 3.- Modifica `sisub.py` para poder recibir los datos enviados por `sipub.py`. ::: ## Some basic test ### one to many communication MQTT is very useful when we have to distribute the same piece of information to various users... but we have to be careful with topics. For example, using the code from Question_3, set as ``topic`` for the "subscriber" the value ``i/LOVE/Python`` and execute it. Now modify the code of the "producer" so that it uses the same topic (i.e., ``i/love/python``) and as the message use the text that you want. Execute the "producer". :::danger 4.- Describe lo que obtienes y por que. ::: ### Retained messages: Normally, if a publisher publishes a message to a topic, and **no one is subscribed** to that topic the message is simply discarded by the broker. If you want your broker to remember the last published message, you'll have to use the ``retained`` option. Only one message is retained per topic. The next message published on that topic replaces the retained message for that topic. Modify the `loop_start/loop_stop` section of `sipub.py` like indicated below: ```python= client.loop_start() msg_to_be_sent = "__whatevertextyouwant__" client.publish(THE_TOPIC, payload=msg_to_be_sent, qos=0, retain=False) client.loop_stop() ``` Try now the following cases, but **remember to always execute the "subscriber" AFTER the "producer"** in all cases: :::danger 5.- Prueba los siguentes casos: * Publica un mensaje con la opcion de retained a "False". ¿Qué recibe el "subscriber"? * Publica un mensaje con la opcion de retained a "True". ¿Qué recibe el "subscriber"? * Publica varios mensajes (diferentes) con la opcion de retained a "True" antes de activar el "subscriber". ¿Qué recibe el "subscriber"? ::: Finally, how do you remove or delete a retained message? You have to publish a blank message with the retain flag set to true. ==Try it.== :::danger Ejercicio final... 6.- Crea grupos de dos o tres miembros. Crea una aplicación de chat muy básica, donde todos los mensajes publicados de cualquiera de los miembros sean recibidos **solo por los miembros** del grupo. > la lectura de texto desde el teclado en Python se puede hacer usando: > `name = input("Enter text: ")` :::