MQTT Temperature Logger with Home Assistant Easy

Log temperature readings to Home Assistant using DS18B20 and MQTT

🔗Goal

Build a temperature and humidity logger that sends sensor data to an MQTT broker over WiFi. The ESP32 reads a DHT22 sensor every 30 seconds and publishes the values as a JSON message. You can then view the data using any MQTT client — from a simple command-line tool to a full dashboard like MQTT Explorer.

Here is how the system works at a high level:

graph LR
    A[DHT22 Sensor] -->|GPIO 4| B[ESP32]
    B -->|WiFi| C[MQTT Broker]
    C --> D[MQTT Explorer / Dashboard]
    C --> E[mosquitto_sub]

MQTT (Message Queuing Telemetry Transport) is a lightweight messaging protocol designed for IoT devices. The ESP32 acts as a publisher, sending sensor data to a topic on the broker. Any device that subscribes to that topic receives the data in real time.

See our Introduction to MQTT for a beginner-friendly explanation of brokers, topics, publishing, and subscribing.

🔗Prerequisites

You will need the following components:

ComponentQtyNotesBuy
ESP32 dev board1AliExpress | Amazon.de .co.uk .com
DHT22 sensor1Also sold as AM2302AliExpress | Amazon.de .co.uk .com
10k ohm resistor1Pull-up for the DHT22 data lineAliExpress | Amazon.de .co.uk .com
Breadboard1AliExpress | Amazon.de .co.uk .com
Jumper wires~5AliExpress | Amazon.de .co.uk .com

Links marked Amazon/AliExpress are affiliate links. We may earn a small commission at no extra cost to you.

You will also need the following Arduino libraries:

LibraryAuthorPurpose
DHT sensor libraryAdafruitDHT22 sensor driver
Adafruit Unified SensorAdafruitDependency for the DHT library
PubSubClientNick O'LearyMQTT client for Arduino

For viewing the data, you will need one of the following on your computer:

  • mosquitto_sub (command-line MQTT client, part of the Mosquitto package)
  • MQTT Explorer (graphical MQTT client, free and cross-platform)

See our DHT22 guide for more details on the sensor, including timing requirements and the difference between DHT11 and DHT22.

🔗Tutorial

🔗Step 1: Wiring

The DHT22 has four physical pins, but only three are used. If you are looking at the front of the sensor (the side with the grid), the pins from left to right are: VCC, DATA, NC (not connected), and GND.

ComponentPinESP32 Pin
DHT22Pin 1 (VCC)3.3V
DHT22Pin 2 (DATA)GPIO 4
DHT22Pin 3 (NC)Not connected
DHT22Pin 4 (GND)GND
10k ohm resistorBetween DATA and VCCGPIO 4 to 3.3V

The $10\,\text{k}\Omega$ pull-up resistor ensures stable communication on the data line. Some DHT22 breakout modules include this resistor on the PCB — check your module before adding an external one.

Pin labels and GPIO numbers vary between ESP32 boards. Always check your board's pinout diagram and datasheet.

🔗Step 2: Choose an MQTT broker

For this project, we use the free public broker test.mosquitto.org on port 1883. This is great for testing but not secure — anyone can see your messages.

For a permanent setup, consider running your own broker (like Mosquitto on a Raspberry Pi) or using a private cloud broker.

BrokerAddressPortNotes
test.mosquitto.orgtest.mosquitto.org1883Free, public, unencrypted. Good for testing
Local MosquittoYour server's IP1883Private. Install with sudo apt install mosquitto

🔗Step 3: Upload the code

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

// ----- Configuration -----
const char* WIFI_SSID      = "YOUR_WIFI_SSID";
const char* WIFI_PASSWORD   = "YOUR_WIFI_PASSWORD";
const char* MQTT_BROKER     = "test.mosquitto.org";
const int   MQTT_PORT       = 1883;
const char* MQTT_CLIENT_ID  = "esp32_temp_logger";
const char* MQTT_PUB_TOPIC  = "esp32/sensor/data";
const char* MQTT_SUB_TOPIC  = "esp32/command";

#define DHT_PIN  4
#define DHT_TYPE DHT22

// ----- Objects -----
WiFiClient wifiClient;
PubSubClient mqtt(wifiClient);
DHT dht(DHT_PIN, DHT_TYPE);

unsigned long lastPublish = 0;
const unsigned long PUBLISH_INTERVAL = 30000;  // 30 seconds

// ----- WiFi connection -----
void connectWiFi() {
    if (WiFi.status() == WL_CONNECTED) return;

    Serial.print("Connecting to WiFi");
    WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 40) {
        delay(500);
        Serial.print(".");
        attempts++;
    }
    if (WiFi.status() == WL_CONNECTED) {
        Serial.println();
        Serial.print("Connected! IP: ");
        Serial.println(WiFi.localIP());
    } else {
        Serial.println();
        Serial.println("WiFi connection failed. Will retry...");
    }
}

// ----- MQTT connection -----
void connectMQTT() {
    if (mqtt.connected()) return;

    Serial.print("Connecting to MQTT broker...");
    while (!mqtt.connected()) {
        if (mqtt.connect(MQTT_CLIENT_ID)) {
            Serial.println(" connected!");
            mqtt.subscribe(MQTT_SUB_TOPIC);
            Serial.print("Subscribed to: ");
            Serial.println(MQTT_SUB_TOPIC);
        } else {
            Serial.print(" failed (rc=");
            Serial.print(mqtt.state());
            Serial.println("). Retrying in 5 seconds...");
            delay(5000);
        }
    }
}

// ----- MQTT message callback -----
void mqttCallback(char* topic, byte* payload, unsigned int length) {
    String message;
    for (unsigned int i = 0; i < length; i++) {
        message += (char)payload[i];
    }
    Serial.print("Received on [");
    Serial.print(topic);
    Serial.print("]: ");
    Serial.println(message);

    // Example: respond to a "status" command
    if (message == "status") {
        mqtt.publish(MQTT_PUB_TOPIC, "{\"status\":\"online\"}");
        Serial.println("Status request received. Responded.");
    }
}

// ----- Publish sensor data -----
void publishSensorData() {
    float temperature = dht.readTemperature();
    float humidity    = dht.readHumidity();

    if (isnan(temperature) || isnan(humidity)) {
        Serial.println("ERROR: Failed to read from DHT22 sensor.");
        return;
    }

    // Build JSON payload
    String payload = "{";
    payload += "\"temperature\":" + String(temperature, 1) + ",";
    payload += "\"humidity\":" + String(humidity, 1) + ",";
    payload += "\"unit\":\"celsius\"";
    payload += "}";

    // Publish to MQTT
    if (mqtt.publish(MQTT_PUB_TOPIC, payload.c_str())) {
        Serial.print("Published: ");
        Serial.println(payload);
    } else {
        Serial.println("ERROR: MQTT publish failed.");
    }
}

void setup() {
    Serial.begin(115200);
    dht.begin();

    connectWiFi();

    mqtt.setServer(MQTT_BROKER, MQTT_PORT);
    mqtt.setCallback(mqttCallback);

    connectMQTT();

    Serial.println("MQTT Temperature Logger ready.");
    Serial.print("Publishing to topic: ");
    Serial.println(MQTT_PUB_TOPIC);
    Serial.print("Listening on topic: ");
    Serial.println(MQTT_SUB_TOPIC);
}

void loop() {
    // Reconnect if needed
    connectWiFi();
    if (!mqtt.connected()) {
        connectMQTT();
    }
    mqtt.loop();

    // Publish every 30 seconds
    unsigned long now = millis();
    if (now - lastPublish >= PUBLISH_INTERVAL) {
        lastPublish = now;
        publishSensorData();
    }
}

🔗Step 4: View the data with mosquitto_sub

Once the ESP32 is publishing, you can subscribe to the topic from any computer on the network. If you have the Mosquitto client tools installed:

mosquitto_sub -h test.mosquitto.org -t "esp32/sensor/data"

You should see JSON messages arriving every 30 seconds:

{"temperature":23.5,"humidity":48.2,"unit":"celsius"}
{"temperature":23.4,"humidity":48.5,"unit":"celsius"}

🔗Step 5: Send a command to the ESP32

You can also publish a command to the ESP32 from your computer:

mosquitto_pub -h test.mosquitto.org -t "esp32/command" -m "status"

The ESP32 will respond by publishing {"status":"online"} to the sensor data topic.

🔗Step 6: Visualize with MQTT Explorer (optional)

MQTT Explorer is a free graphical tool that shows all topics on a broker as a tree. Connect it to test.mosquitto.org on port 1883 and navigate to esp32 > sensor > data to see your temperature and humidity values update in real time.

Because test.mosquitto.org is a public broker, you will also see messages from other users around the world. This is normal. For privacy, use a unique topic name or run your own broker.

🔗Understanding the JSON Payload

The ESP32 publishes data in JSON format, which is the standard for IoT messaging:

{"temperature":23.5,"humidity":48.2,"unit":"celsius"}

The DHT22 sensor specifications:

ParameterRangeAccuracy
Temperature$-40$ to $+80\,°\text{C}$$\pm 0.5\,°\text{C}$
Humidity$0$ to $100\,\%\,\text{RH}$$\pm 2\,\%\,\text{RH}$
Sampling rateOnce every $2\,\text{s}$Minimum interval between reads

🔗Common Issues and Solutions

ProblemCauseFix
"Failed to read from DHT22"Wiring issue or missing pull-up resistorCheck wiring. Ensure the 10k ohm pull-up is between DATA and VCC. DHT22 needs at least 2 seconds between reads
WiFi connects but MQTT failsBroker unreachable or port blockedCheck internet connection. Try ping test.mosquitto.org from your computer. Some networks block port 1883
MQTT connects but no data appears in mosquitto_subTopic name mismatchEnsure the topic in the code matches exactly what you subscribe to (case-sensitive)
Messages appear sporadicallyWiFi drops and reconnectsThe reconnection logic handles this, but if your WiFi is unstable, check signal strength. Move closer to the router
mqtt.state() returns -2Network connection failedWiFi might be connected but internet access is blocked. Check router firewall settings
JSON looks malformedFloat values contain NaNThe DHT22 occasionally returns NaN. The code checks for this, but ensure the sensor is wired correctly
Readings arrive less often than every 30 secondsmqtt.loop() is blocked or slowEnsure nothing in loop() uses long delay() calls. The mqtt.loop() function must run frequently