#include <WiFi.h>
#include <PubSubClient.h>
#include <DallasTemperature.h>
#include <OneWire.h>
// Change the credentials below, so your ESP32 connects to your router
#define ssid "Wokwi-GUEST" // It D E F I N E S the meaning of wifi
#define password ""
// /\
// /||\
// ||
#define oneWireBus 4
// Change the variable to your server address, so it connects to your MQTT broker
#define mqtt_server "jpsantos.ddns.net"
// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient espClient;
PubSubClient client(espClient);
OneWire oneWire(oneWireBus);
DallasTemperature sensors(&oneWire);
long lastMsg = 0;
char msg[1024];
int value = 0;
#define analogInPin 34 // Using ESP32 Analog ADC1_CH6 = GPIO34
int sensorValue = 0; // value read from the ADC
// Timers auxiliar variables
long now = millis();
long lastMeasure = 0;
// The setup function initializes the LED_BUILTIN pin as an output, starts the serial communication at a baud rate of 115200 (the same the board uses to printout its initial information just after reset)
// Sets your mqtt broker and sets the callback function
// The callback function is what receives messages and actually controls the LEDs
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200); // Begin the UART port, so that it is in sync with the USB UART chip
setup_wifi(); // Call our wifi setup
sensors.begin(); // Start the DS18B20
client.setServer(mqtt_server, 18839); // uses the string defined with the server address: const char* mqtt_server = "jpsantos.ddns.net"; and the server communication port
client.setCallback(callback); // uses the function with prototype: void callback(String topic, byte* message, unsigned int length);
}
// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
// delay(10); [Why is this here? It slows us down!]
// We start by connecting to a WiFi network
// Serial.println();
// Serial.print("Connecting to ");
// Serial.println(ssid);
// Take advantage of currently unused variables!
sprintf(msg, "\nConnecting to %s\n", ssid); // sprintf is a function that
// moves a string with a %
// to a char[#]. In this case
// we take advantage of the
// unused variable msg to
// store it.
Serial.print(msg); // Now print the variable msg to the Serial Port.
// Now it's only 2 lines!
WiFi.begin(ssid, password); // This function is handy if you like the
// internet. It connects the ESP32's internal
// wifi modem to your network.
while (WiFi.status() != WL_CONNECTED) { // Do a loop while it's not connected
delay(500); // We must add a delay or it would be sending
// so many dots, that it would seem insane.
Serial.print(".");
}
// blinks the builtin LED when connected to a WiFi network
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
// Serial.println("");
// Serial.print("WiFi connected - IP address: ");
// Serial.println(WiFi.localIP());
sprintf(msg, "\nWiFi connected - IP address: %s\n", WiFi.localIP().toString().c_str());
// Again, above this comment, we use sprintf to save us a line.
// But if we wanted to be more fancy, we could use Serial.printf.
// But I chose not to.
Serial.print(msg);
// delay(1000); [Please stop, We want speed!]
}
// This function is executed when some device publishes a message to a topic that your ESP32 is subscribed to
// Change the function below to add logic to your program, so when a device publishes a message to a topic that
// your ESP32 is subscribed you can actually do something
//
// In this function's first line, I tried out Serial.printf.
void callback(String topic, byte* message, unsigned int length) {
Serial.printf("Message arrived on topic: %s %s", topic, ". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.write((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
// If a message is received on the topic room/lamp, you check if the message is either on or off. Turns the lamp GPIO according to the message
if(topic=="board/led"){
Serial.print("Changing board LED to ");
if(messageTemp == "on"){
digitalWrite(LED_BUILTIN, HIGH); // the builtin LED in the NodeMCU board is on with LOW
Serial.print("On");
}
else if(messageTemp == "off"){
digitalWrite(LED_BUILTIN, LOW); // the builtin LED in the NodeMCU board is off with HIGH
Serial.print("Off");
}
}
Serial.println();
}
// This functions reconnects your ESP8266 to your MQTT broker
// Change the function below if you want to subscribe to more topics with your ESP8266
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
/*
YOU MIGHT NEED TO CHANGE THIS LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS
To change the ESP device ID, you will have to give a new name to the ESP8266.
Here's how it looks:
if (client.connect("ESP8266Client")) {
You can do it like this:
if (client.connect("ESP1_Office")) {
Then, for the other ESP:
if (client.connect("ESP2_Garage")) {
That should solve your MQTT multiple connections problem
*/
if (client.connect("ESP32Client")) {
// double blinks the builtin LED when connected to the MQTT broker
for(int ledLoop=0; ledLoop < 2; ledLoop++)
{
digitalWrite(LED_BUILTIN, HIGH);
delay(100);
digitalWrite(LED_BUILTIN, LOW);
delay(100);
}
Serial.println("connected");
// Subscribe or resubscribe to a topic
// You can subscribe to more topics (to control more LEDs in this example)
client.subscribe("board/led");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
// For this project, you don't need to change anything in the loop function. Basically it ensures that you ESP is connected to your broker
void loop() {
if (!client.connected()) {
reconnect();
}
if(!client.loop())
client.connect("ESP32Client");
now = millis();
// Publishes new ADC voltage every 1 second
if (now - lastMeasure > 1000) {
lastMeasure = now;
// reads the analog in value, converts the ADC result to voltage, converts the float with the voltage value to a string:
sensors.requestTemperatures();
sensorValue = analogRead(analogInPin);
float voltage = sensorValue/4096.0*3.3;
static char adcVoltage[7];
static char dsTemp[7];
dtostrf(voltage, 3, 2, adcVoltage);
dtostrf(sensors.getTempCByIndex(0), 3, 2, dsTemp);
// Publishes ADC voltage value
client.publish("board/adc", adcVoltage);
client.publish("board/ds18b20", dsTemp);
sensors.requestTemperatures();
Serial.print("ADC voltage: ");
Serial.print(voltage);
Serial.print(" V | DS Temp reading: ");
Serial.print(sensors.getTempCByIndex(0));
Serial.println(" C ");
}
}