Report the temperature with ESP8266 to MQTT

I recently learned about the ESP8266, a $5 chip that includes WiFi and is Arduino compatible. This means that all your DIY projects can now be done for a fraction of the price.

For this tutorial, I’ll walk through how to get going with ESP8266, get the temperature and humidity and report it to MQTT where Home Assistant can pick it up.

![](upload://7K9kSYhXSpXTAJomUCwU3aVobXH.png) Picture of the final setup (+ 2 LED for decoration)

![](upload://AjPbdv2Jhf194EU6ir66HNxk8q2.png) Home Assistant will keep track of historical values and allow you to integrate it into automation.

Components

I’ve been using Adafruit for my shopping:

Besides this, you will need the usual hardware prototype equipment: a breadboard, some wires, soldering iron + wire, Serial USB cable.

Alternatives

Since this article has been published the HDC1008 has been discontinued. Updated sketches are available for the following alternatives:

Connections

On your breadboard, make the following connections from your ESP8266 to the HDC1008:

ESP8266 HDC1008 GND GND 3V Vin 14 SCL #2 SDA

I picked #2 and 14 myself, you can configure them in the sketch.

Preparing your IDE

Follow these instructions on how to install and prepare the Arduino IDE for ESP8266 development.

After you’re done installing, open the Arduino IDE, in the menu click on sketch -> include library -> manage libraries and install the following libraries:

  • PubSubClient by Nick ‘O Leary
  • Adafruit HDC1000

Sketch

If you have followed the previous steps, you’re all set.

  • Open Arduino IDE and create a new sketch (File -> New)
  • Copy and paste the below sketch to the Arduino IDE
  • Adjust the values line 6 - 14 to match your setup
  • Optional: If you want to connect to an MQTT server without a username or password, adjust line 62.
  • To have the ESP8266 accept our new sketch, we have to put it in upload mode. On the ESP8266 device keep the GPIO0 button pressed while pressing the reset button. The red led will glow half bright to indicate it is in upload mode.
  • Press the upload button in Arduino IDE
  • Open the serial monitor (Tools -> Serial Monitor) to see the output from your device

This sketch will connect to your WiFi network and MQTT broker. It will read the temperature and humidity from the sensor every second. It will report it to the MQTT server if the difference is > 1 since last reported value. Reports to the MQTT broker are sent with retain set to True. This means that anyone connecting to the MQTT topic will automatically be notified of the last reported value.

#include <ESP8266WiFi.h>
#include <Wire.h>
#include <PubSubClient.h>
#include <Adafruit_HDC1000.h>
#define wifi_ssid "YOUR WIFI SSID"
#define wifi_password "WIFI PASSWORD"
#define mqtt_server "YOUR_MQTT_SERVER_HOST"
#define mqtt_user "your_username"
#define mqtt_password "your_password"
#define humidity_topic "sensor/humidity"
#define temperature_topic "sensor/temperature"
WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_HDC1000 hdc = Adafruit_HDC1000();
void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  // Set SDA and SDL ports
  Wire.begin(2, 14);
  // Start sensor
  if (!hdc.begin()) {
    Serial.println("Couldn't find sensor!");
    while (1);
  }
}
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);
  WiFi.begin(wifi_ssid, wifi_password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
         (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diff = 1.0;
void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  long now = millis();
  if (now - lastMsg > 1000) {
    lastMsg = now;
    float newTemp = hdc.readTemperature();
    float newHum = hdc.readHumidity();
    if (checkBound(newTemp, temp, diff)) {
      temp = newTemp;
      Serial.print("New temperature:");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }
    if (checkBound(newHum, hum, diff)) {
      hum = newHum;
      Serial.print("New humidity:");
      Serial.println(String(hum).c_str());
      client.publish(humidity_topic, String(hum).c_str(), true);
    }
  }
}

Configuring Home Assistant

The last step is to integrate the sensor values into Home Assistant. This can be done by setting up Home Assistant to connect to the MQTT broker and subscribe to the sensor topics.

mqtt:
  broker: YOUR_MQTT_SERVER_HOST
  username: your_username
  password: your_password
sensor:
  platform: mqtt
  name: "Temperature"
  state_topic: "sensor/temperature"
  qos: 0
  unit_of_measurement: "ºC"
sensor 2:
  platform: mqtt
  name: "Humidity"
  state_topic: "sensor/humidity"
  qos: 0
  unit_of_measurement: "%"

This is a companion discussion topic for the original entry at https://home-assistant.io/blog/2015/10/11/measure-temperature-with-esp8266-and-report-to-mqtt/
2 Likes

How can I add the availability topic? Should I send hearbeats or reply to requests?

1 Like

Hello Paulus;

I am interested in doing this project, however, I am confused as to your connections. I am using the AM2302 - supposed to be a dht22 in a housing. What confuses me is your connections (SCL #14, SDA #2). On my AM2302, I only have 3 leads; power, ground and one data. How should this be connected in my case?

Hello Stiofan,

these sensors use different communication protocols.
Just use one of the free GPIOs for the data pin.
I choose GPIO 2 in my thermostat project.

But in the .ino code there are definitions for 2 pins. Should i just define them both to the same number?

I used esp home for my am2302

1 Like

The Arduino library which used in paulus sketch is incompatible with the AM2302 / DHT22.
You need to use another library, I use “DHT sensor library for ESPx”

Why not simply use esphome?

2 Likes

My question wasn’t really related to the software, but the physical connections. I have in the mean time got it working.

Thanks everyone for your help.

It’s basic mqtt integration thx for your share

Hi.
I have tried this project by replacing DHT22 with DHT11. Unfortunately it doesn’t work. Temperature and humidity readings are always zero. The electronic circuit works with a simple web server that displays the temperature and humidity on request. I copied the code of the dht22 version.
Any help is very welcome.
R.

// Get ESP8266 going with Arduino IDE
// - https://github.com/esp8266/Arduino#installing-with-boards-manager
// Required libraries (sketch -> include library -> manage libraries)
// - PubSubClient by Nick ‘O Leary
// - DHT sensor library by Adafruit

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

#define wifi_ssid "*"
#define wifi_password "*"

#define mqtt_server "*"
#define mqtt_user "*"
#define mqtt_password "*"

#define humidity_topic "sensor/humidity"
#define temperature_topic "sensor/temperature"

#define DHTTYPE DHT11
#define DHTPIN  2

WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266

void setup() {
  Serial.begin(115200);
  dht.begin();
  setup_wifi();
  client.setServer(mqtt_server, 1883);
}

void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(wifi_ssid);

  WiFi.begin(wifi_ssid, wifi_password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    // If you do not want to use a username and password, change next line to
    // if (client.connect("ESP8266Client")) {
    if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

bool checkBound(float newValue, float prevValue, float maxDiff) {
  return !isnan(newValue) &&
         (newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}

long lastMsg = 0;
float temp = 0.0;
float hum = 0.0;
float diff = 1.0;

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
  delay(10000);
  //for debug
  float newTemp = dht.readTemperature();
  Serial.print("New temperature:");
  Serial.println(String(newTemp).c_str());
  //
  long now = millis();
  if (now - lastMsg > 2000) {
    lastMsg = now;

    float newTemp = dht.readTemperature();
    float newHum = dht.readHumidity();

    if (checkBound(newTemp, temp, diff)) {
      temp = newTemp;
      Serial.print("New temperature:");
      Serial.println(String(temp).c_str());
      client.publish(temperature_topic, String(temp).c_str(), true);
    }

    if (checkBound(newHum, hum, diff)) {
      hum = newHum;
      Serial.print("New humidity:");
      Serial.println(String(hum).c_str());
      client.publish(humidity_topic, String(hum).c_str(), true);
    }
  }
}

Hello. I want to thank all the commentators. I have read your posts very carefully. I understood that I had connected the wrong pin. Now works.

Hello,
I tried this project and it successfully shows humidity sensor and temperature sensor to my home assistant lovelace user interface. In my home assistant, i also installed add-ons named “MQTT Broker”.
I check MQTT Broker in integration tab, but it’s empty. Is it normal to have mqtt broker integration empty, while i successfully publish humidity and temperature sensor? Thanks.

1 Like

Mqtt integrations shows only auto discovered devices. If you configured manual in .yaml, it will not show there.

Has anyone been successful using deepSleep when using this integration? If so, any pointers or code modification ideas would be appreciated . The problem is, I have a good MQTT msg upload but only after esp-01 boots up for the first time. Every subsequent attempt after ESP wake up, is not being sent to the broker for some reason. I read that there’s a general problem with ESP’s deepSleep and MQTT and the suggested solutions involved all kinds of delays and / or client.disconnect(); espClient.flush(); as well as sending multiple client.loop();'s. None of these seem to work. Would really appreciate if someone could share a working solution…

You might like to look at esphome.

I did and the search continues. Have a few sensors running on ESPHome and it’s great.
But this is one of those “why the hell does it not work” kind of a things. I realise that the error is not HA specific. That being said I was hoping someone was trying to follow the provided example and came across similar issues.
Just to be clear, the provided code works great, without deepSleep .

Each time the ESP comes out of deep sleep, it’s the same as a reboot. Nothing done last time can be reused. You need to do everything again every time which is why your code only works the first time after boot.

My flow for waking up, sending MQTT data, and then deep sleep:
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback); //optional
client.publish(outTopic1, msg);
client.disconnect();
ESP.deepSleep(sleepSeconds * 1000000);

I get that. As you said, it’s like a hard reset so it should start the sequence from setup(): onwards. That’’s what I’m actually counting on. But it either gives me a nan as a sensor output after initial sleep period and /or does’ not upload data to the broker. And that’s with forcing it to flush and disconnect before sleep. That’s why I’m confused. To the point where I gave up and went back to ESPHome - but - the built in support for deep sleep doesn’t work there either with this particular board. Same pattern - nan after reset. I’m yet to test a different ESP01 and a Wemos board to see if it makes any difference.

I put everything in setup() when I use deepSleep, the loop() {} is empty. So each time it wakes up, it runs setup() once and goes to sleep until the next reset.