Build a phone dashboard with MQTT

Publish temperature, humidity and light to a free MQTT broker, show them on a phone dashboard, and switch the colour of an RGB LED from anywhere.
  • Level:Intermediate
  • Duration: 1 h
  • Ages 12+
  • Platform: ESP32

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Build a phone dashboard with MQTT – EEMENTOR STEM™ lesson

MQTT is the language that millions of smart home devices, factory machines and sensors use to talk to each other. Devices don't send messages to each other directly: they send them to a broker, a server that passes each message on to everyone who has asked for it. In this lesson the ESP32 publishes its readings to a free public broker, and an app on your phone turns them into a dashboard with gauges. The phone can also publish a message back, to change the colour of an RGB LED.

What you'll learn

  • How the MQTT broker, topics, publish and subscribe work
  • How to send readings from the ESP32 with the PubSubClient library
  • How to react to messages that arrive
  • How to build a dashboard in an MQTT phone app

What you need

  • ESP32 board, expansion board and USB cable (ESP32 IoT Starter Kit)
  • DHT11 temperature and humidity module (45-in-1 Sensor Kit)
  • Photoresistor module (45-in-1 Sensor Kit)
  • RGB LED module (45-in-1 Sensor Kit)
  • 3 resistors, 220 Ω (ESP32 IoT Starter Kit)
  • A phone with a free MQTT dashboard app, such as IoT MQTT Panel
  • A 2.4 GHz Wi-Fi network
  • The printed parts from the 3D printing box below (two module stands), or the cardboard version described there
  • Breadboard and jumper wires (ESP32 IoT Starter Kit)

Wiring

Breadboard wiring diagram: Build a phone dashboard with MQTT
Breadboard view. Check each connection against the wiring table below.
From To
DHT11 module S ESP32 GPIO 27
Photoresistor module S ESP32 GPIO 34
Both modules + and − 3V3 and GND
RGB module R 220 Ω resistor, then GPIO 25
RGB module G 220 Ω resistor, then GPIO 26
RGB module B 220 Ω resistor, then GPIO 33
RGB module − GND

Sensor modules from different makers can label and order their pins differently. Always follow the labels printed on your module.

Choose your topics

Everyone in the world shares the free public broker at broker.hivemq.com, so your topics need a name nobody else uses. The sketch builds them from BASE, for example eementor/maya-7q2:

Topic Who publishes Message
BASE/temperature ESP32, every 10 s Temperature in °C, for example 21.4
BASE/humidity ESP32, every 10 s Humidity in %
BASE/light ESP32, every 10 s Light level, 0 to 100
BASE/led Your phone red, green, blue, white or off

Important: a public broker is like a notice board in a park. Anyone who knows your topic can read your messages and send their own, so only use it for harmless data like room temperature, never for anything private.

The sketch

Replace YOUR_WIFI_NAME and YOUR_WIFI_PASSWORD with your own network details (2.4 GHz only).

In the Arduino IDE, open Library Manager and install PubSubClient (by Nick O'Leary) and the DHT sensor library by Adafruit.

Change BASE to your own name plus a few random letters.

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

const char* WIFI_NAME = "YOUR_WIFI_NAME";
const char* WIFI_PASSWORD = "YOUR_WIFI_PASSWORD";
const char* BROKER = "broker.hivemq.com";
const String BASE = "eementor/YOUR_NAME_123";   // must be unique

const int LIGHT_PIN = 34;
const int RED_PIN = 25, GREEN_PIN = 26, BLUE_PIN = 33;

WiFiClient net;
PubSubClient mqtt(net);
DHT dht(27, DHT11);
unsigned long lastPublish = 0;

void colour(int r, int g, int b) {
  analogWrite(RED_PIN, r);
  analogWrite(GREEN_PIN, g);
  analogWrite(BLUE_PIN, b);
}

// Runs every time a message arrives on a topic we subscribed to
void onMessage(char* topic, byte* payload, unsigned int length) {
  String text;
  for (unsigned int i = 0; i < length; i++) text += (char)payload[i];
  text.trim();
  text.toLowerCase();
  Serial.println(String("Message on ") + topic + ": " + text);
  if (text == "red") colour(255, 0, 0);
  else if (text == "green") colour(0, 255, 0);
  else if (text == "blue") colour(0, 0, 255);
  else if (text == "white") colour(255, 255, 255);
  else if (text == "off") colour(0, 0, 0);
}

void connectMqtt() {
  while (!mqtt.connected()) {
    String id = "eementor-" + String((uint32_t)ESP.getEfuseMac(), HEX);
    Serial.print("Connecting to the broker... ");
    if (mqtt.connect(id.c_str())) {
      Serial.println("connected");
      mqtt.subscribe((BASE + "/led").c_str());
    } else {
      Serial.printf("failed (%d), trying again in 5 s\n", mqtt.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);
  dht.begin();
  WiFi.begin(WIFI_NAME, WIFI_PASSWORD);
  Serial.print("Connecting to Wi-Fi");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println(" connected");
  mqtt.setServer(BROKER, 1883);
  mqtt.setCallback(onMessage);
}

void loop() {
  if (!mqtt.connected()) connectMqtt();
  mqtt.loop();                          // receive messages and keep the connection alive

  if (millis() - lastPublish > 10000) {
    lastPublish = millis();
    float t = dht.readTemperature();
    float h = dht.readHumidity();
    int light = analogRead(LIGHT_PIN) * 100 / 4095;
    if (!isnan(t)) mqtt.publish((BASE + "/temperature").c_str(), String(t, 1).c_str());
    if (!isnan(h)) mqtt.publish((BASE + "/humidity").c_str(), String(h, 0).c_str());
    mqtt.publish((BASE + "/light").c_str(), String(light).c_str());
    Serial.printf("Published %.1f C, %.0f %%, light %d\n", t, h, light);
  }
}

Build the phone dashboard

  1. Install IoT MQTT Panel (or another MQTT dashboard app) and add a connection: broker broker.hivemq.com, port 1883, protocol TCP, any client ID.
  2. Add a dashboard, then add a Gauge panel with the topic eementor/YOUR_NAME_123/temperature, range 0 to 40. Add two more gauges for humidity and light.
  3. Add a Button or Combo box panel that publishes red, green, blue, white and off to …/led.
  4. Watch the gauges update every 10 seconds, and switch the LED colour. It works on mobile data too.

No phone? Open the HiveMQ WebSocket client in a browser (search for "HiveMQ MQTT websocket client"), connect, subscribe to eementor/YOUR_NAME_123/# and publish to the led topic from there.

How it works

The ESP32 opens one connection to the broker and keeps it open. mqtt.publish() sends a message with a topic; the broker passes it to every client that subscribed to that topic, such as your phone. When your phone publishes to …/led, the broker passes it to the ESP32, because it subscribed to that topic, and onMessage() runs. mqtt.loop() must run often: it receives those messages and sends small "I'm still here" packets so the broker doesn't close the connection.

The # in …/# is a wildcard that means "every topic below this one". Topics are arranged like folders, which is why it helps to start them all with the same BASE.

Try this next

  • Publish an alarm message on …/alert when it gets warmer than 28 °C, and add a notification in the app.
  • Add a slider in the app that publishes 0 to 255 and sets the LED brightness.
  • Read the same topics on a second ESP32 and show them on its LCD: two devices talking through the cloud.

Troubleshooting

  • "failed (-2)": the ESP32 couldn't reach the broker. Some school and office networks block port 1883; try a home network or a phone hotspot.
  • The gauges stay empty: the topic in the app must match the sketch exactly, including capital letters.
  • Strange messages appear: someone else uses the same BASE. Make it longer and more random.
  • The light value is always 0 or 100: the photoresistor must be on GPIO 34; pins 25 to 27 can't read analog values while Wi-Fi is on.
  • It never connects to Wi-Fi: check the network name and password (both are case-sensitive) and make sure the network is 2.4 GHz.
  • A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

ESP32 IoT Starter Kit | Arduino IDE Compatible | Free Tutorials $57.00

Shop the kit