#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
// Readable Aliases
#define ON HIGH
#define OFF LOW
// Pin Assignments
const int led1 = 18;// blue LED
const int led2 = 13; // red LED
const int btn1 = 12; // red Button (GPIO12)
const int btn2 = 14; // blue Button (GPIO14)
const int potPin = 34;
const int dhtPin = 4;
// WiFi & MQTT Details
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqtt_server = "test.mosquitto.org";
// MQTT Topics
const char* topicTemp = "np/Azriel/dht22/temperature";
const char* topicHum = "np/Azriel/dht22/humidity";
const char* topicPot = "np/Azriel/potentiometer";
const char* topicStatus = "np/Azriel/sensor/status";
const char* topicLed1Control = "np/Azriel/led1/control"; // BLUE
const char* topicLed2Control = "np/Azriel/led2/control"; // RED
WiFiClient espClient;
PubSubClient client(espClient);
DHT dht(dhtPin, DHT22);
unsigned long lastMsg = 0;
// Variables to remember App states
bool appLed1State = false;
bool appLed2State = false;
// --- CALLBACK: Handles incoming messages for BOTH LED1 and LED2 ---
void callback(char* topic, byte* payload, unsigned int length) {
String message;
for (int i = 0; i < length; i++) { message += (char)payload[i]; }
String strTopic = String(topic);
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("]: ");
Serial.println(message);
// Control LED 1 logic
if (strTopic == topicLed1Control) {
if (message == "ON") appLed1State = true;
else if (message == "OFF") appLed1State = false;
}
// Control LED 2 logic
if (strTopic == topicLed2Control) {
if (message == "ON") appLed2State = true;
else if (message == "OFF") appLed2State = false;
}
}
void setup_wifi() {
delay(10);
Serial.print("\nConnecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi connected");
}
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "ESP32Client-" + String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("connected");
client.publish(topicStatus, "Online");
// SUBSCRIBE to both control topics
client.subscribe(topicLed1Control);
client.subscribe(topicLed2Control);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
// Use INPUT_PULLUP - Buttons must be wired to GND
pinMode(btn1, INPUT_PULLUP);
pinMode(btn2, INPUT);
dht.begin();
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) reconnect();
client.loop(); // Essential for receiving MQTT messages
// --- LED 1 Logic (Red LED) ---
// Stays ON if the App says ON OR if you hold the physical Blue button
if (appLed1State || digitalRead(btn1) == LOW) {
digitalWrite(led1, ON);
} else {
digitalWrite(led1, OFF);
}
// --- LED 2 Logic (Blue LED) ---
// Stays ON if the App says ON OR if you hold the physical Red button
if (appLed2State || digitalRead(btn2) == LOW) {
digitalWrite(led2, ON);
} else {
digitalWrite(led2, OFF);
}
// --- SENSOR DATA PUBLISHING (Every 2 seconds) ---
unsigned long now = millis();
if (now - lastMsg > 2000) {
lastMsg = now;
float t = dht.readTemperature();
float h = dht.readHumidity();
int potValue = analogRead(potPin);
if (!isnan(t) && !isnan(h)) {
client.publish(topicTemp, String(t).c_str());
client.publish(topicHum, String(h).c_str());
client.publish(topicPot, String(potValue).c_str());
Serial.print("Sent -> Temp: "); Serial.print(t);
Serial.print(" | Hum: "); Serial.print(h);
Serial.print(" | Pot: "); Serial.println(potValue);
}
}
}