Institute of Computer Science
  1. Courses
  2. 2020/21 fall
  3. Mobile Computing and Internet of Things (LTAT.06.009)
ET
Log in

Mobile Computing and Internet of Things 2020/21 fall

  • Main
  • Lectures
  • Labs
  • Homeworks & Home Assignments
  • Quizes
  • Task submission
  • Extra Materials
  • Projects
    • Teams & Topics
    • Presentations & Report
    • Grading & Submission

Lab11 : Working with MQTT

In this lab, we will connect to a MQTT broker using various clients: our development machine, from Android and from Arduino.

1. Installing a MQTT Client (and Broker)

There are several implementations in different languages of the MQTT protocol, both for the server (broker) and client side. We will use mosquitto, an open-source implementation of MQTT. It includes both the broker and client.

  • Download & Install mosquitto for your platform : https://mosquitto.org/download/
    • Windows Steps
    • Linux Steps
    • MacOS Steps

Let's try to use the MQTT client to connect to an existing MQTT broker

Broker address : test.mosquitto.org
  1. Subscribe to topic "lab11/<<yourname>>" by running mosquitto_sub -t "lab11/<<yourname>>" -h <<BROKER_ADDRESS>>
    • The program will keep running and print out any messages published to that topic.
  2. Publish a message to the topic by opening a second terminal, and running:
    • mosquitto_pub -h <<BROKER_ADDRESS>> -t "lab11/<<yourname>>" -m "Hello, MQTT!"

The message should appear in the 1st terminal. Try also subscribing to the topic "lab11/#", the "#" wildcard will subscribe to all subtopics under "hello", so if anybody else was publishing messages simultaneously, you'd see them too.

For more information about MQTT topics, this material has a good overview.

Note: By default, installing mosquitto will also start running the broker on your machine, on the default MQTT port 1883. You can try the broker running in your machine by substituting the IP with "localhost", for example.

2. MQTT Client on Android

2.1 Setting up library

  • Create a new (Blank Empty Activity) Android Studio Project.

Let's add the Eclipse Paho MQTT Client Library to our project:

  • in Project .gradle file:
    allprojects {
      repositories {
          google()
          jcenter()

          maven {
            url "https://repo.eclipse.org/content/repositories/paho-snapshots/"
          }
     }
    }
  • in Module .gradle file:
    // MQTT client
    implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.1'
    implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
    implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0' // needed to resolve     java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/localbroadcastmanager/content/LocalBroadcastManager;
  • In AndroidManifest.xml:
    ‹!-- Mqtt Service --›
    <service android:name="org.eclipse.paho.android.service.MqttService" />
  • MQTT client also needs these permissions:
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

2.2 Logging MQTT messages

  • Add the code from here to your Activity.
  • Study the code, run it, verify that it can connect to the broker.
  • Update the Kotlin code so that once the MQTT client is connected, it subscribes to topic "lab11/<<XXX>>" , where <<XXX>> is some unique topic name for you (e.g. your matricle number if you don't mind that somebody sees it)
    Toast.makeText(applicationContext, "MQTT Connected, subscribing...", Toast.LENGTH_SHORT).show()
    mqttClient.subscribe("<<<topic>>>", 0) // 0 - is the QoS value
  • Publish some message to the correct topic and verify you can see it being logged.

2.3 Drawing a plot with the data

Let's re-create the Arduino IDE plotter in Android, using a custom View. When creating a custom View, we can control the entire 2D drawing of the UI component down to pixel precision (if necessary), instead of using one of the existing View Widgets (e.g. Button, Spinner, etc) or Layouts.

We will use Android custom drawing capabilities to draw a line graph showing values sent to a MQTT topic.

  • Create a new class that extends View, and overrides the constructor with signature (c: Context, atrs: AttributeSet)
    class LinePlot(context: Context, attrs: AttributeSet) : View(context, attrs)
  • Override onDraw(canvas: Canvas) method
    • Using the Canvas object, we can actually draw something onto the screen
    • Canvas provides various useful methods such as drawCircle, drawRectangle, drawText, drawLine, drawBitmap, etc.
    • To draw something on the canvas, you must specify the coordinates and a Paint object which defines the drawing style (e.g. brush color, thickness).

Now, you place your custom View into a Layout XML, e.g. activity_main.xml:

    <ee.ut.cs.lab11.LinePlot
        android:id="@+id/line_graph"
        android:layout_width="0dp"
        android:layout_height="0dp"
        ...
    ></ee.ut.cs.lab11.LinePlot>

Note, it's possible to define your XML attributes for your custom View (e.g. LinearLayout had a orientation attribute), see here for more info.

  • Add the following to your custom View:
    private val bluePaint = Paint().apply {
        color = Color.BLUE
        strokeWidth = 8f
    }

    // Sample dataset:
    var dataSet = mutableListOf(3.3f,4.0f,4.5f,6.6f,4.6f,2.6f,1.0f,1.5f,6.7f)
    var plotYMax: Float = Collections.max(dataSet)
    var plotYMin: Float = Collections.min(dataSet)

    /** Helper functions which scale the numeric values to screen dimensions */
    private fun scaledX(value : Float) : Float { return (value / dataSet.size) * width }
    // Y- value is also reversed because 0,0 coordinate is in top-left corner in Canvas
    private fun scaledY(value : Float) : Float { return height - (((value - plotYMin) / (plotYMax-plotYMin)) * height) }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        dataSet.forEachIndexed { i, value ->
            canvas?.drawPoint(scaledX(i.toFloat()), scaledY(value), bluePaint ) }
    }

Try to run the application. The code creates some sample data and draws a point for each element in the dataSet collection. Note that the numeric values are adjusted based on screen height/width and dataset max value.

  • Now, inside onDraw(), write code which would also draw lines connecting each pair of points in the dataset (using canvas.drawLine(x1,y1,x2,y2,paint) ). Try using a different colour paint.
    • First try to get the line drawing to work by yourself, but if you need an example, see here

2.4 Joining the MQTT client and plotter

Add this function to your View:

   fun addData(value : Float){
        dataSet.add(value)
        if (dataSet.size > 20 ){
            dataSet.removeAt(0) // remove oldest (FIFO)
        }
        // Update Max, Min
        plotYMax = if (value > plotYMax) value else plotYMax
        plotYMin = if (value < plotYMin) value else plotYMin
        // Force UI refresh:
        invalidate()
    }
  • Update the MQTT client code so that it invokes the addData function of the custom View when a message arrives.
    • You can refer to the View from Activity by its ID and thus access its methods.
  • Test that it works by publishing some messages with mosquitto_pub

Arduino MQTT Client

Let's install the library PubSubClient

  • Open Tools -> Manage Libraries and find PubSubClient by Nick O'Leary

Open the following Arduino code . This code:

  • Establishes a connection to a pre-configured WiFi access point (in setup() )
    • Using the WiFi library, #include <WiFi.h>
  • Once the WiFi connection is established, it tries to connect to the MQTT broker (end of setup() )
  • In the main loop(), every 100ms it reads an analog sensor value and publishes it as a MQTT message
    • Every iteration of loop(), mqttClient.loop() is also called, this allows the client to process incoming messages and maintain its connection to the server.

Modify the code accordingly (update WiFi & MQTT Credentials and MQTT topic) and run it. Make sure all your devices are in the same network. Depending on your setup, a firewall may be blocking port 1883 (e.g. when creating a hotspot from Windows).

Other information

It is possible to configure authentication and SSL encryption for brokers, but we did not consider those options in this lab.

  • Institute of Computer Science
  • Faculty of Science and Technology
  • University of Tartu
In case of technical problems or questions write to:

Contact the course organizers with the organizational and course content questions.
The proprietary copyrights of educational materials belong to the University of Tartu. The use of educational materials is permitted for the purposes and under the conditions provided for in the copyright law for the free use of a work. When using educational materials, the user is obligated to give credit to the author of the educational materials.
The use of educational materials for other purposes is allowed only with the prior written consent of the University of Tartu.
Terms of use for the Courses environment