aaa#define BLYNK_TEMPLATE_ID "TMPL3fXDSrrWP"
#define BLYNK_TEMPLATE_NAME "Smart Plug Basic v1"
#define BLYNK_AUTH_TOKEN "bsbb2Hz4nmZqDAeCtlNOlJSsRaJrZzpn"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <TimeLib.h>
#include <WidgetRTC.h>
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
#define RELAY_PIN 3 // D1
#define LED_PIN 8 // D8
#define BUTTON_PIN 4 // D2 -> GND
BlynkTimer timer;
bool relayState = false;
// countdown from V2 menu
bool countdownActive = false;
unsigned long countdownEndMillis = 0;
bool lastButtonState = HIGH;
void setRelay(bool on) {
relayState = on;
digitalWrite(RELAY_PIN, on ? HIGH : LOW);
digitalWrite(LED_PIN, on ? HIGH : LOW);
Blynk.virtualWrite(V1, on ? 1 : 0); // sync app
}
// V1: ON/OFF switch
BLYNK_WRITE(V1) {
int value = param.asInt();
setRelay(value == 1);
if (value == 0) countdownActive = false;
}
// V2: Menu: 1=No timer, 2=+30, 3=+60, 4=+90
BLYNK_WRITE(V2) {
int sel = param.asInt();
int minutes = 0;
if (sel == 2) minutes = 30;
else if (sel == 3) minutes = 60;
else if (sel == 4) minutes = 90;
else minutes = 0;
if (minutes > 0) {
setRelay(true);
countdownActive = true;
countdownEndMillis = millis() + (unsigned long)minutes * 60UL * 1000UL;
Serial.print("Countdown started for ");
Serial.print(minutes);
Serial.println(" min");
} else {
countdownActive = false;
Serial.println("Countdown cancelled");
}
}
void checkCountdown() {
if (countdownActive && millis() > countdownEndMillis) {
countdownActive = false;
setRelay(false);
Serial.println("Countdown finished -> OFF");
}
}
// physical button on D2
void checkButton() {
bool current = digitalRead(BUTTON_PIN);
if (current == LOW && lastButtonState == HIGH) {
delay(30);
if (digitalRead(BUTTON_PIN) == LOW) {
setRelay(!relayState);
Serial.print("Button pressed -> ");
Serial.println(relayState ? "ON" : "OFF");
countdownActive = false; // cancel timer on manual press
}
}
lastButtonState = current;
}
void setup() {
Serial.begin(115200);
pinMode(RELAY_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
setRelay(false);
// ---- Manual WiFi connect with timeout ----
Serial.print("Connecting to WiFi ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 15000) {
delay(500);
Serial.print(".");
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi connected");
Serial.print("IP: ");
Serial.println(WiFi.localIP());
} else {
Serial.println("\nWiFi FAILED, continuing offline (button still works)");
}
// ---- Blynk config (non-blocking) ----
Blynk.config(BLYNK_AUTH_TOKEN);
if (WiFi.status() == WL_CONNECTED) {
if (Blynk.connect(5000)) {
Serial.println("Blynk connected");
} else {
Serial.println("Blynk NOT connected (timeout)");
}
}
// timers
timer.setInterval(1000L, checkCountdown);
timer.setInterval(50L, checkButton);
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
Blynk.run(); // only if WiFi OK
}
timer.run(); // always run (button + countdown)
}