Home Assistant temperature
Publish a DS18B20 reading over MQTT every 30 seconds. Home Assistant finds the sensor by itself through MQTT discovery.
Board
ESP32
3V3
GND
EN
23
VP
22
VN
TX
34
RX
35
21
32
GND
33
19
25
18
26
5
27
17
14
16
12
4
GND
0
13
2
D2
15
D3
D1
CMD
D0
5V
CLK
Wiring
| From | To board | Note |
|---|---|---|
| DS18B20 VDD (red) | 3V3 | |
| DS18B20 GND (black) | GND | |
| DS18B20 DATA (yellow) | GPIO 4 | 4.7 kΩ pull-up from DATA to 3V3 |
Tested on this board
Not run on this board yet. Treat the wiring and code as a first draft.
Firmware, Arduino sketch for ESP32 Dev Module
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";
const char* MQTT_HOST = "192.168.1.10"; // your broker, often the Home Assistant machine
const int MQTT_PORT = 1883;
const char* MQTT_USER = ""; // leave empty if the broker allows anonymous clients
const char* MQTT_PASS = "";
OneWire oneWire(4);
DallasTemperature probes(&oneWire);
WiFiClient net;
PubSubClient mqtt(net);
String id, stateTopic, statusTopic;
unsigned long lastSend = 0;
// Tell Home Assistant about the sensor. Retained, so it survives a restart.
void announce() {
String config = String("{\"name\":\"Temperature\",\"device_class\":\"temperature\",")
+ "\"state_class\":\"measurement\",\"unit_of_measurement\":\"°C\","
+ "\"state_topic\":\"" + stateTopic + "\","
+ "\"availability_topic\":\"" + statusTopic + "\","
+ "\"unique_id\":\"" + id + "_temperature\","
+ "\"device\":{\"identifiers\":[\"" + id + "\"],\"name\":\"ESP32 Bench " + id + "\"}}";
String topic = String("homeassistant/sensor/") + id + "/temperature/config";
mqtt.publish(topic.c_str(), config.c_str(), true);
}
void connectMqtt() {
const char* user = strlen(MQTT_USER) > 0 ? MQTT_USER : nullptr;
const char* pass = strlen(MQTT_PASS) > 0 ? MQTT_PASS : nullptr;
while (!mqtt.connected()) {
Serial.printf("mqtt connecting to %s\n", MQTT_HOST);
// The last will marks the sensor unavailable if the board drops off.
if (mqtt.connect(id.c_str(), user, pass, statusTopic.c_str(), 1, true, "offline")) {
mqtt.publish(statusTopic.c_str(), "online", true);
announce();
Serial.printf("mqtt ok as %s, discovery sent\n", id.c_str());
} else {
Serial.printf("mqtt failed, state %d, retry in 5 s\n", mqtt.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
probes.begin();
Serial.printf("wifi joining %s\n", WIFI_NAME);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(300);
Serial.printf("wifi ok %s\n", WiFi.localIP().toString().c_str());
String mac = WiFi.macAddress();
mac.replace(":", "");
mac.toLowerCase();
id = String("esp32bench-") + mac.substring(6);
stateTopic = String("esp32bench/") + id + "/temperature";
statusTopic = String("esp32bench/") + id + "/status";
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setBufferSize(512); // the discovery message is longer than the 256-byte default
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
if (lastSend != 0 && millis() - lastSend < 30000) return;
lastSend = millis();
probes.requestTemperatures();
float c = probes.getTempCByIndex(0);
if (c == DEVICE_DISCONNECTED_C) {
Serial.println("no probe: check the data wire and the 4.7 kOhm pull-up");
return;
}
char value[16];
snprintf(value, sizeof value, "%.2f", c);
mqtt.publish(stateTopic.c_str(), value);
Serial.printf("%s %s\n", stateTopic.c_str(), value);
}S3
3V3
GND
3V3
TX
RST
RX
4
1
5
2
6
42
7
41
15
40
16
39
17
38
18
37
8
36
3
35
46
0
9
45
10
48
11
47
12
21
13
20
14
19
5V
GND
GND
GND
Wiring
| From | To board | Note |
|---|---|---|
| DS18B20 VDD (red) | 3V3 | |
| DS18B20 GND (black) | GND | |
| DS18B20 DATA (yellow) | GPIO 4 | 4.7 kΩ pull-up from DATA to 3V3 |
Tested on this board
Not run on this board yet. Treat the wiring and code as a first draft.
Firmware, Arduino sketch for ESP32S3 Dev Module
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";
const char* MQTT_HOST = "192.168.1.10"; // your broker, often the Home Assistant machine
const int MQTT_PORT = 1883;
const char* MQTT_USER = ""; // leave empty if the broker allows anonymous clients
const char* MQTT_PASS = "";
OneWire oneWire(4);
DallasTemperature probes(&oneWire);
WiFiClient net;
PubSubClient mqtt(net);
String id, stateTopic, statusTopic;
unsigned long lastSend = 0;
// Tell Home Assistant about the sensor. Retained, so it survives a restart.
void announce() {
String config = String("{\"name\":\"Temperature\",\"device_class\":\"temperature\",")
+ "\"state_class\":\"measurement\",\"unit_of_measurement\":\"°C\","
+ "\"state_topic\":\"" + stateTopic + "\","
+ "\"availability_topic\":\"" + statusTopic + "\","
+ "\"unique_id\":\"" + id + "_temperature\","
+ "\"device\":{\"identifiers\":[\"" + id + "\"],\"name\":\"ESP32 Bench " + id + "\"}}";
String topic = String("homeassistant/sensor/") + id + "/temperature/config";
mqtt.publish(topic.c_str(), config.c_str(), true);
}
void connectMqtt() {
const char* user = strlen(MQTT_USER) > 0 ? MQTT_USER : nullptr;
const char* pass = strlen(MQTT_PASS) > 0 ? MQTT_PASS : nullptr;
while (!mqtt.connected()) {
Serial.printf("mqtt connecting to %s\n", MQTT_HOST);
// The last will marks the sensor unavailable if the board drops off.
if (mqtt.connect(id.c_str(), user, pass, statusTopic.c_str(), 1, true, "offline")) {
mqtt.publish(statusTopic.c_str(), "online", true);
announce();
Serial.printf("mqtt ok as %s, discovery sent\n", id.c_str());
} else {
Serial.printf("mqtt failed, state %d, retry in 5 s\n", mqtt.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
probes.begin();
Serial.printf("wifi joining %s\n", WIFI_NAME);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(300);
Serial.printf("wifi ok %s\n", WiFi.localIP().toString().c_str());
String mac = WiFi.macAddress();
mac.replace(":", "");
mac.toLowerCase();
id = String("esp32bench-") + mac.substring(6);
stateTopic = String("esp32bench/") + id + "/temperature";
statusTopic = String("esp32bench/") + id + "/status";
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setBufferSize(512); // the discovery message is longer than the 256-byte default
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
if (lastSend != 0 && millis() - lastSend < 30000) return;
lastSend = millis();
probes.requestTemperatures();
float c = probes.getTempCByIndex(0);
if (c == DEVICE_DISCONNECTED_C) {
Serial.println("no probe: check the data wire and the 4.7 kOhm pull-up");
return;
}
char value[16];
snprintf(value, sizeof value, "%.2f", c);
mqtt.publish(stateTopic.c_str(), value);
Serial.printf("%s %s\n", stateTopic.c_str(), value);
}C3
GND
GND
3V3
TX
3V3
RX
2
GND
3
9
GND
8
RST
GND
GND
7
0
6
1
5
10
4
GND
GND
5V
18
5V
19
GND
GND
Wiring
| From | To board | Note |
|---|---|---|
| DS18B20 VDD (red) | 3V3 | |
| DS18B20 GND (black) | GND | |
| DS18B20 DATA (yellow) | GPIO 4 | 4.7 kΩ pull-up from DATA to 3V3 |
Tested on this board
Not run on this board yet. Treat the wiring and code as a first draft.
Firmware, Arduino sketch for ESP32C3 Dev Module
#include <WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h>
#include <DallasTemperature.h>
const char* WIFI_NAME = "your-network";
const char* WIFI_PASS = "your-password";
const char* MQTT_HOST = "192.168.1.10"; // your broker, often the Home Assistant machine
const int MQTT_PORT = 1883;
const char* MQTT_USER = ""; // leave empty if the broker allows anonymous clients
const char* MQTT_PASS = "";
OneWire oneWire(4);
DallasTemperature probes(&oneWire);
WiFiClient net;
PubSubClient mqtt(net);
String id, stateTopic, statusTopic;
unsigned long lastSend = 0;
// Tell Home Assistant about the sensor. Retained, so it survives a restart.
void announce() {
String config = String("{\"name\":\"Temperature\",\"device_class\":\"temperature\",")
+ "\"state_class\":\"measurement\",\"unit_of_measurement\":\"°C\","
+ "\"state_topic\":\"" + stateTopic + "\","
+ "\"availability_topic\":\"" + statusTopic + "\","
+ "\"unique_id\":\"" + id + "_temperature\","
+ "\"device\":{\"identifiers\":[\"" + id + "\"],\"name\":\"ESP32 Bench " + id + "\"}}";
String topic = String("homeassistant/sensor/") + id + "/temperature/config";
mqtt.publish(topic.c_str(), config.c_str(), true);
}
void connectMqtt() {
const char* user = strlen(MQTT_USER) > 0 ? MQTT_USER : nullptr;
const char* pass = strlen(MQTT_PASS) > 0 ? MQTT_PASS : nullptr;
while (!mqtt.connected()) {
Serial.printf("mqtt connecting to %s\n", MQTT_HOST);
// The last will marks the sensor unavailable if the board drops off.
if (mqtt.connect(id.c_str(), user, pass, statusTopic.c_str(), 1, true, "offline")) {
mqtt.publish(statusTopic.c_str(), "online", true);
announce();
Serial.printf("mqtt ok as %s, discovery sent\n", id.c_str());
} else {
Serial.printf("mqtt failed, state %d, retry in 5 s\n", mqtt.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
probes.begin();
Serial.printf("wifi joining %s\n", WIFI_NAME);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NAME, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) delay(300);
Serial.printf("wifi ok %s\n", WiFi.localIP().toString().c_str());
String mac = WiFi.macAddress();
mac.replace(":", "");
mac.toLowerCase();
id = String("esp32bench-") + mac.substring(6);
stateTopic = String("esp32bench/") + id + "/temperature";
statusTopic = String("esp32bench/") + id + "/status";
mqtt.setServer(MQTT_HOST, MQTT_PORT);
mqtt.setBufferSize(512); // the discovery message is longer than the 256-byte default
}
void loop() {
if (!mqtt.connected()) connectMqtt();
mqtt.loop();
if (lastSend != 0 && millis() - lastSend < 30000) return;
lastSend = millis();
probes.requestTemperatures();
float c = probes.getTempCByIndex(0);
if (c == DEVICE_DISCONNECTED_C) {
Serial.println("no probe: check the data wire and the 4.7 kOhm pull-up");
return;
}
char value[16];
snprintf(value, sizeof value, "%.2f", c);
mqtt.publish(stateTopic.c_str(), value);
Serial.printf("%s %s\n", stateTopic.c_str(), value);
}Parts
| Quantity | Part | Where to buy |
|---|---|---|
| 1× | ESP32 dev board | Buy at Amazon |
| 1× | DS18B20 waterproof probe | Buy at Adafruit |
| 1× | 4.7 kΩ resistor, pull-up for the data line | Buy at Amazon |
| 1× | An MQTT broker, such as the Mosquitto add-on in Home Assistant |
Amazon buy links may include an Associates tag, and this site may earn a commission from qualifying Amazon purchases at no extra cost to you. Adafruit links are direct.
Libraries
PubSubClient (Nick O'Leary), OneWire, DallasTemperature, WiFi (built in)
Load it
- In the Arduino IDE, install the esp32 board package and pick the board named above the sketch.
- Install the libraries listed above from the Library Manager.
- Paste the sketch, choose the board's port and upload. Hold BOOT if the upload stalls at Connecting.
- Close the IDE's serial monitor, then open the bench here to watch the output.
Field notes
- Home Assistant needs the MQTT integration set up and pointed at the same broker. The sensor then appears under Settings, Devices and services, MQTT.
- mqtt failed, state -2 means the broker could not be reached: check MQTT_HOST and that port 1883 is open. State 4 or 5 means the user name or password was refused.
- The sketch raises PubSubClient's buffer to 512 bytes. With the default 256 the discovery message is silently dropped and nothing appears in Home Assistant.
- The device id comes from the board's MAC address, so each board shows up as its own device.
Not tested yet
- Not tested on hardware or with Home Assistant yet. Compiles for every board listed with Arduino-ESP32 core 3.3.12.