Skip to content

Instantly share code, notes, and snippets.

@sarasantos
Last active April 1, 2023 11:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sarasantos/fa4cdd5012c296fbf41141a2f45c5765 to your computer and use it in GitHub Desktop.
Save sarasantos/fa4cdd5012c296fbf41141a2f45c5765 to your computer and use it in GitHub Desktop.
/*
Rui Santos
Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-mqtt-publish-bme280-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>
#define WIFI_SSID "XXXXXXXXXX"
#define WIFI_PASSWORD "XXXXXXXXXX"
// Raspberri Pi Mosquitto MQTT Broker
#define MQTT_HOST IPAddress(192, 168, XX, XX)
#define MQTT_PORT 1883
// For a cloud MQTT broker, type the domain name
//#define MQTT_HOST "example.com"
// Temperature MQTT Topics
#define MQTT_PUB_TEMP "esp/bme280/temperature"
#define MQTT_PUB_HUM "esp/bme280/humidity"
#define MQTT_PUB_PRES "esp/bme280/pressure"
// BME280 I2C
Adafruit_BME280 bme;
// Variables to hold sensor readings
float temp;
float hum;
float pres;
AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;
WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;
unsigned long previousMillis = 0; // Stores last time temperature was published
const long interval = 10000; // Interval at which to publish sensor readings
void connectToWifi() {
Serial.println("Connecting to Wi-Fi...");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}
void connectToMqtt() {
Serial.println("Connecting to MQTT...");
mqttClient.connect();
}
void onWifiConnect(const WiFiEventStationModeGotIP& event) {
Serial.println("Connected to Wi-Fi.");
connectToMqtt();
}
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
Serial.println("Disconnected from Wi-Fi.");
mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
wifiReconnectTimer.once(2, connectToWifi);
}
void onMqttConnect(bool sessionPresent) {
Serial.println("Connected to MQTT.");
Serial.print("Session present: ");
Serial.println(sessionPresent);
}
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
Serial.println("Disconnected from MQTT.");
if (WiFi.isConnected()) {
mqttReconnectTimer.once(2, connectToMqtt);
}
}
/*void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
Serial.println("Subscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
Serial.print(" qos: ");
Serial.println(qos);
}
void onMqttUnsubscribe(uint16_t packetId) {
Serial.println("Unsubscribe acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}*/
void onMqttPublish(uint16_t packetId) {
Serial.print("Publish acknowledged.");
Serial.print(" packetId: ");
Serial.println(packetId);
}
void setup() {
Serial.begin(115200);
Serial.println();
// Initialize BME280 sensor
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);
mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
//mqttClient.onSubscribe(onMqttSubscribe);
//mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);
// If your broker requires authentication (username and password), set them below
//mqttClient.setCredentials("REPlACE_WITH_YOUR_USER", "REPLACE_WITH_YOUR_PASSWORD");
connectToWifi();
delay(2000);
// New BME280 sensor readings
//temp = bme.readTemperature();
temp = 1.8*bme.readTemperature() + 32;
hum = bme.readHumidity();
pres = bme.readPressure()/100.0F;
// Publish an MQTT message on topic esp/bme280/temperature
uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId: %i ", MQTT_PUB_TEMP, packetIdPub1);
Serial.printf("Message: %.2f \n", temp);
// Publish an MQTT message on topic esp/bme280/humidity
uint16_t packetIdPub2 = mqttClient.publish(MQTT_PUB_HUM, 1, true, String(hum).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId: %i ", MQTT_PUB_HUM, packetIdPub2);
Serial.printf("Message: %.2f \n", hum);
// Publish an MQTT message on topic esp/bme280/pressure
uint16_t packetIdPub3 = mqttClient.publish(MQTT_PUB_PRES, 1, true, String(pres).c_str());
Serial.printf("Publishing on topic %s at QoS 1, packetId: %i ", MQTT_PUB_PRES, packetIdPub3);
Serial.printf("Message: %.3f \n", pres);
Serial.println("I'm awake, but I'm going into deep sleep mode for 30 seconds");
delay(2000);
ESP.deepSleep(30e6);
}
void loop() {
}
@hardmar
Copy link

hardmar commented Mar 28, 2023

Seem to have the cart before the horse -
shouldn't the connectToWiFi come before the mqttClient?
As written, I get multiple connect and disconnects instead of connect, read, publish, and disconnect.
I deleted the 2 second delay before the deepSleep with no ill effects.
Also, I used a while loop to check the WiFi.status with a 500mS delay as my router is a bit slower than 2 seconds.

@hardmar
Copy link

hardmar commented Mar 29, 2023

Still have issues - both as you have written and with the mods I have done.
In neither case does it actually publish to Node-Red.
It "appears" to be working on SerialMonitor - connect and disconnects, displays readings, but does NOT display the Publish ack message.
Node-red shows that it is connected, but no readings come out to a Debug.
Any ideas?
Thanks for all your work on ESP and such.

@sarasantos
Copy link
Author

How did you find this code?
Are you following a specific RNT project?

Did you set up your broker with a username and password? If so, you need to insert them into the code. Additionally, you may also need to make some changes to your Node-RED nodes to add the broker username and password.

@hardmar
Copy link

hardmar commented Mar 30, 2023

Sara - Thanks for your response

I was searching for info on actually getting DeepSleep to work with Node-Red and came across this code in an old post you made on GitHub. I have the ebook Smart Home RPi, etc. and worked thru it and have my project working with 6 ESP8266 and BME280 sensors gathering data to an RPi with Node-Red and InfluxDB. Great work on the ebook, by the way.

Getting the six sets of data plotting to three plots for the three variables took awhile for me to sort out - the InfluxDB chapter in particular left me hanging a bit. So, the project is working fine, except I have to tweak the data quite a bit due to self-heating from the ESP and the sensor, hence trying to get the DeepSleep working.

I am at present working with trying to publish just one test ESP and only the mqtt_in node with a debug node attached in Node-Red. I am using the code as you have it with the addition of my credentials for mqtt added. Here is what the Serial Monitor output looks like:

d`� g d
Connecting to Wi-Fi...
Publishing on topic test/temperature at QoS 1, packetId: 0 Message: 74.73
Publishing on topic test/pressure at QoS 1, packetId: 0 Message: 1017.380
I'm awake, but I'm going into deep sleep mode for 30 seconds
Connected to Wi-Fi.
Connecting to MQTT...
Disconnected from MQTT.
Disconnected from Wi-Fi.
// about 30 seconds later
l�l � n �l
Connecting to Wi-Fi...
Publishing on topic test/temperature at QoS 1, packetId: 0 Message: 74.86
Publishing on topic test/pressure at QoS 1, packetId: 0 Message: 1017.389
I'm awake, but I'm going into deep sleep mode for 30 seconds
Connected to Wi-Fi.
Connecting to MQTT...
Disconnected from MQTT.
Disconnected from Wi-Fi.

It "appears" to work on the Serial Monitor output - the Serial Monitor readings are good - they change it I blow on the sensor, for example, and it cools off. The Deep Sleep works as well, but the order of connecting, disconnecting and publishing seems off to me.

The Node-Red mqtt_in node shows Connected, but no data shows up on the debug node. However, if I delete the debug node connection and deploy, connect the debug back and redeploy, I get just one test/temperature reading that has the correct timestamp, but has a bogus data value of 78.25 - always the same.

I would be most appreciative of any insights you might have.

Thanks again, Rick

@sarasantos
Copy link
Author

Please post this issue on our forum or send an email to our support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment