First part: ESP-32 Temperature Monitor.
In this second part the output of the temperature sensor will be fed into Home Assistant. This will be achieved using MQTT which uses a publish-subscribe model.
According to mqtt.org,
"MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT)."
The plan is that the ESP will publish its data as a topic to a server called an MQTT broker and Home Assistant will subscribe to the topic, displaying it on a dashboard and enabling automations.
This sounds like it's going to be complicated but it was fairly easy; it's just that it took several steps. I might write another application or tool to work with this data via MQTT, but that's something for the future.
I installed mosquitto, an MQTT broker on a Raspberry Pi in my homelab.
sudo apt install mosquitto mosquitto-clients
sudo systemctl enable mosquitto.service
Mosquitto runs as a system service:
$ systemctl status mosquitto.service
● mosquitto.service - Mosquitto MQTT v3.1/v3.1.1 Broker
Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-09-11 22:01:45 BST; 5 days ago
Docs: man:mosquitto.conf(5)
man:mosquitto(8)
Main PID: 27509 (mosquitto)
Tasks: 1 (limit: 4915)
CGroup: /system.slice/mosquitto.service
└─27509 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Sep 11 22:01:45 raspberrypi systemd[1]: Starting Mosquitto MQTT v3.1/v3.1.1 Broker...
It's quite easy to publish a message to a topic on one terminal and subscribe to it from another terminal in order to test it's working.
After finding the ASyncMQTT library for ESP microcontrollers, I installed it via the Library Manager in the Arduino IDE. I chose this version rather than the ESP-32 specific one because in the future I want to use similar code for ESP-01S/ESP8266. Later on I discovered that I needed to install the AsyncTCP library as well.
Following the example, I made the following additions to the previous code, which are straightforward but look more complicated than they really are:
Include headers for networking and MQTT
#include <WiFi.h>
#include <AsyncMqtt_Generic.h>
Define WiFi credentials and MQTT broker IP address
#define MY_SSID "Name of your WiFi network"
#define MY_WIFI_PASSWD "password"
#define MQTT_HOST "NN.NN.NN.NN" // Broker IP address
#define MQTT_PORT 1883
Declare a client and topics to publish
Note: I chose to publish two topics from this sensor and used the prefix
lh-mqtt to keep it separate from any other topic.
AsyncMqttClient mqttClient;
// Topics to publish
const char *PubTopic1 = "lh-mqtt/temperature";
const char *PubTopic2 = "lh-mqtt/humidity";
Add functions to connect to WiFi and the MQTT broker
// Connect to wifi
void connectWiFi(){
WiFi.begin(MY_SSID, MY_WIFI_PASSWD);
Serial.println("Connecting Wifi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
}
void connectMqtt()
{
Serial.println("Connecting to MQTT...");
mqttClient.connect();
}
Add callback functions for MQTT to aid in debugging
void onMqttConnect(bool sessionPresent)
{
Serial.print("Connected to MQTT broker: "); Serial.print(MQTT_HOST);
Serial.print(", port: "); Serial.println(MQTT_PORT);
Serial.print("Session present: "); Serial.println(sessionPresent);
}
void onMqttPublish(const uint16_t &packetId)
{
Serial.println("Publish acknowledged");
Serial.print(" packetId: "); Serial.println(packetId);
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason)
{
(void) reason;
Serial.println("Disconnected from MQTT.");
}
Insert calls to connect to MQTT and WiFi in the setup() function
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
// Initialize Wi-Fi
connectWiFi();
// Connect to broker
connectMqtt();
Call functions to publish when reading values, in the loop() function
char pubMesg[5];
snprintf(pubMesg, 5, "%2.1f\0", temperature);
mqttClient.publish(PubTopic1, 0, true, pubMesg);
// etc
I tested the code by uploading it to the ESP-32 and then using a terminal on the broker to subscribe to the topic.
There is an official Mosquitto broker add on for Home Assistant but I chose to install an external broker because I wanted to make sure that it wasn't tied to HA.
In Home Assistnt,
Home Assistant Dashboard Reporting My Topics
Here is the text I added to the configuration file:
mqtt:
sensor:
- name: "ESP32 Temperature"
state_topic: "lh-mqtt/temperature"
state_class: measurement
unit_of_measurement: "C"
- name: "ESP32 Humidity"
state_topic: "lh-mqtt/humidity"
state_class: measurement
unit_of_measurement: "%"
This is proof of concept, the code could be nicer and the set up in Home Assistant could be improved. This concludes this section of the project, I'll make another project to control a fan using PWM for controlling temperature.
I would like to add some kind of redundancy in case the broker goes offline - it shouldn't stop automations from running. This might be achieved using an automation based off the UptimeKuma integration or maybe running the broker from a Kubernetes cluster so that a new one can be spawned if it goes down.
< Back