#define BLYNK_TEMPLATE_ID "TMPL6qkwItLOJ"
#define BLYNK_TEMPLATE_NAME "Homework4"
#define BLYNK_AUTH_TOKEN "nGM5o4ShjL2KGdK1R2tYiW0XNQXzmHxj"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
const char* ssid = "Wokwi-GUEST";
const char* pass = "";
// Firebase
#define FIREBASE_BASE_URL "https://rtdb-iot-hw4-default-rtdb.firebaseio.com"
#define FIREBASE_SECRET "vPmh3PXpsmDrtNhqGOmyy7OF3JTOlMLDkhz4Zia1"
// Pins
#define LED_A 2
#define LED_B 0
#define POT 36
BlynkTimer timer;
WiFiClientSecure tls;
String fbUrl(const String& path) {
return String(FIREBASE_BASE_URL) + path + ".json?auth=" + FIREBASE_SECRET;
}
bool fbSetInt(const String& path, int value) {
HTTPClient http;
http.begin(tls, fbUrl(path));
http.addHeader("Content-Type", "application/json");
int code = http.PUT(String(value));
http.end();
return (code >= 200 && code < 300);
}
bool fbGetInt(const String& path, int &out) {
HTTPClient http;
http.begin(tls, fbUrl(path));
int code = http.GET();
if (code < 200 || code >= 300) {
http.end();
return false;
}
String body = http.getString();
http.end();
body.trim();
if (body == "null" || body.length() == 0) return false;
out = body.toInt();
return true;
}
BLYNK_WRITE(V0) { fbSetInt("/Output/Sol-FerA", param.asInt()); }
BLYNK_WRITE(V1) { fbSetInt("/Output/Sol-FerB", param.asInt()); }
BLYNK_WRITE(V3) { fbSetInt("/DayofWeek", param.asInt()); }
BLYNK_WRITE(V5) { fbSetInt("/Fertilizer/FerA-Time", param.asInt()); }
BLYNK_WRITE(V6) { fbSetInt("/Fertilizer/FerB-Time", param.asInt()); }
BLYNK_WRITE(V7) { fbSetInt("/Moisture/Setting", param.asInt()); }
void updateMoistureFromPot() {
int adc = analogRead(POT);
int percent = map(adc, 0, 4095, 0, 100);
percent = constrain(percent, 0, 100);
fbSetInt("/Moisture/Current", percent);
}
void syncFromFirebase() {
int value;
//a + d) Moisture Current → Gauge
if (fbGetInt("/Moisture/Current", value)) {
Blynk.virtualWrite(V10, value);
}
//c) Moisture Setting → keep slider synced
if (fbGetInt("/Moisture/Setting", value)) {
Blynk.virtualWrite(V7, value);
}
//b) Day of Week → keep menu synced
if (fbGetInt("/DayofWeek", value)) {
Blynk.virtualWrite(V3, value);
}
//h) Fertilizer times → keep numeric inputs synced
if (fbGetInt("/Fertilizer/FerA-Time", value)) {
Blynk.virtualWrite(V5, value);
}
if (fbGetInt("/Fertilizer/FerB-Time", value)) {
Blynk.virtualWrite(V6, value);
}
//e) Sol-FerA LED
if (fbGetInt("/Output/Sol-FerA", value)) {
digitalWrite(LED_A, value ? HIGH : LOW);
Blynk.virtualWrite(V8, value);
}
//f) Sol-FerB LED
if (fbGetInt("/Output/Sol-FerB", value)) {
digitalWrite(LED_B, value ? HIGH : LOW);
Blynk.virtualWrite(V9, value);
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_A, OUTPUT);
pinMode(LED_B, OUTPUT);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) delay(200);
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
tls.setInsecure(); // needed for HTTPS in Wokwi
timer.setInterval(1000L, updateMoistureFromPot);
timer.setInterval(1000L, syncFromFirebase);
}
void loop() {
Blynk.run();
timer.run();
}