#include <WiFi.h>
#include <PubSubClient.h>
#include "DHT.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <HTTPClient.h>
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT Server
const char* mqttServer = "broker.hivemq.com";
int port = 1883;
// ThingSpeak Server
const char* thingspeakServer = "http://api.thingspeak.com/update";
const char* writeAPIKey = "V9U2815QSMW0PPJB";
// Pushsafer Server
const char* pushsaferServer = "https://www.pushsafer.com/api";
const char* pushsaferKey = "cZcQbkk25V4eflPoSjcl";
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long period = 1000;
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int DHTPIN = 15;
const int DHTTYPE = DHT22;
int relayPin = 23;
int runningLedPin = 27; // Green LED: show that the system is running
int wateringLedPin = 14; // Yellow LED: show the watering status
int errorLedPin = 12; // Red LED: show that the system can't fetch data
DHT dht(DHTPIN, DHTTYPE);
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
// Send notification to Pushsafer
void sendPushsaferNotification(const char* title, const char* message) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String payload = "k=" + String(pushsaferKey) +
"&t=" + String(title) +
"&m=" + String(message) +
"&d=a";
http.begin(pushsaferServer);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpResponseCode = http.POST(payload);
if (httpResponseCode > 0) {
//Serial.println("Pushsafer notification sent!");
} else {
Serial.println("Error sending Pushsafer notification");
}
http.end();
} else {
Serial.println("WiFi not connected. Cannot send notification.");
}
}
void wifiConnect() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected!");
}
void mqttConnect() {
while (!mqttClient.connected()) {
Serial.println("Attempting MQTT connection...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (mqttClient.connect(clientId.c_str())) {
Serial.println("Connected");
mqttClient.subscribe("Group21/nhietdo");
mqttClient.subscribe("Group21/doam");
mqttClient.subscribe("Group21/tuoicay");
} else {
Serial.println("Try again in 5 seconds");
delay(5000);
}
}
}
// MQTT Receiver
void callback(char* topic, byte* message, unsigned int length) {
Serial.println(topic);
String strMsg;
for (int i = 0; i < length; i++) {
strMsg += (char)message[i];
}
Serial.println(strMsg);
if (strMsg == "TuoiCay") {
digitalWrite(relayPin, HIGH); // Turn on relay
digitalWrite(wateringLedPin, HIGH); // Turn on LED
}
else if (strMsg == "TuoiCayThuCong") {
digitalWrite(relayPin, HIGH); // Turn on relay
digitalWrite(wateringLedPin, HIGH); // Turn on LED
delay(5000);
digitalWrite(relayPin, LOW); // Turn off relay
digitalWrite(wateringLedPin, LOW); // Turn off LED
}
}
// Send data to ThingSpeak
void sendToThingSpeak(float temperature, float humidity) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
String url = String(thingspeakServer) +
"?api_key=" + writeAPIKey +
"&field1=" + String(temperature) +
"&field2=" + String(humidity);
http.begin(url);
int httpResponseCode = http.GET(); // Send the GET request
if (httpResponseCode <= 0) {
Serial.println("Error sending data to ThingSpeak");
}
http.end();
}
}
void setup() {
Serial.begin(9600);
Serial.print("Connecting to WiFi");
wifiConnect();
mqttClient.setServer(mqttServer, port);
mqttClient.setCallback(callback);
mqttClient.setKeepAlive(90);
lcd.init();
lcd.backlight();
pinMode(relayPin, OUTPUT);
pinMode(runningLedPin, OUTPUT);
pinMode(wateringLedPin, OUTPUT);
pinMode(errorLedPin, OUTPUT);
dht.begin();
startMillis = millis();
}
bool isWatering = false; // Flag to check if watering already started
float lastTemp = -1000;
float lastHum = -1000;
void loop() {
if (!mqttClient.connected()) {
mqttConnect();
}
mqttClient.loop();
digitalWrite(runningLedPin, HIGH);
currentMillis = millis();
if (currentMillis - startMillis >= period)
{
startMillis = currentMillis;
// Read temperature and humidity
float temp = dht.readTemperature();
float hum = dht.readHumidity();
// Publish data to MQTT Server
char nhietdo[50];
sprintf(nhietdo, "%f", temp);
mqttClient.publish("Group21/nhietdo", nhietdo);
char doam[50];
sprintf(doam, "%f", hum);
mqttClient.publish("Group21/doam", doam);
// Publish data to ThingSpeak
sendToThingSpeak(temp, hum);
// Avoid uneccessarily update LCD
if (temp != lastTemp || hum != lastHum) {
lastTemp = temp;
lastHum = hum;
// Display data on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp: ");
lcd.print(temp);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("Humidity: ");
lcd.print(hum);
lcd.print(" %");
}
if ((temp >= 33 || hum <= 50) && !isWatering) {
// Start watering
isWatering = true;
// Send notifications to Pushsafer
if (temp >= 33) {
sendPushsaferNotification("Overheat", "High temperature detected. Watering started.");
mqttClient.publish("Group21/tuoicay", "TuoiCay");
}
if (hum <= 50) {
sendPushsaferNotification("Low Humidity", "Humidity is low. Watering started.");
mqttClient.publish("Group21/tuoicay", "TuoiCay");
}
} else if (temp < 33 && hum > 50 && isWatering) {
// Stop watering
isWatering = false;
digitalWrite(relayPin, LOW); // Turn off relay
digitalWrite(wateringLedPin, LOW); // Turn off LED
}
// Turn on red LED if system can't fetch data
if (isnan(temp) || isnan(hum)) {
digitalWrite(errorLedPin, HIGH);
digitalWrite(runningLedPin, LOW);
digitalWrite(wateringLedPin, LOW);
}
}
}