diff --git a/src/main.cpp b/src/main.cpp index 9871a60..200b44e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,15 +1,16 @@ // src/main.cpp // Bel Sekolah ESP32 - final version // Pins: -// RESET_PIN = 5 (hold >15s -> reset admin credentials) -// STATUS_LED_PIN = 6 -// RELAY_PIN = 7 (active LOW) -// DFPLAYER_RX_PIN = 15 -// DFPLAYER_TX_PIN = 16 -// BUSY_PIN = 17 (LOW = busy) -//esp32 sda 21 -//esp32 scl 22 -//MCU adalah Wemos ESP32 mini +// TEST_BUTTON = 18 (click -> toggle relay, long press -> play test MP3) +// RESET_BUTTON = 0 (long press >15s -> reset admin credentials) +// STATUS_LED_PIN = 26 +// RELAY_PIN = 19 (active LOW) +// DFPLAYER_RX_PIN = 16 +// DFPLAYER_TX_PIN = 17 +// BUSY_PIN = 5 (LOW = busy) +// esp32 sda 21 +// esp32 scl 22 +// MCU adalah Wemos ESP32 mini #include #include @@ -35,7 +36,8 @@ #define DFPLAYER_TX_PIN 17 //2 df #define RELAY_PIN 19 #define BUSY_PIN 5 //must high at boot (strapping pin) -#define RESET_PIN 18 +#define TEST_BUTTON 18 +#define RESET_BUTTON 0 #define BUZZER_PIN 23 #define RESET_HOLD_MS 15000UL @@ -74,12 +76,19 @@ bool buzzerState = false; bool adminResetBlinking = false; unsigned long adminResetEndTime = 0; -// Button flags -volatile bool btnClickPending = false; -volatile bool btnLongPressPending = false; +// Button flags for TEST_BUTTON +volatile bool testBtnClickPending = false; +volatile bool testBtnLongPressPending = false; -// OneButton instance for RESET_PIN -OneButton button(RESET_PIN, true); +// Button flags for RESET_BUTTON +volatile bool resetBtnLongPressPending = false; + +// Manual relay toggle state (separate from automatic relay control) +bool manualRelayOn = false; + +// OneButton instances +OneButton testButton(TEST_BUTTON, true); +OneButton resetButton(RESET_BUTTON, true); ////////////////////////////////////////////////////////////////////////// // WiFi Channel Selection @@ -659,7 +668,8 @@ void setup(){ pinMode(RELAY_PIN, OUTPUT); digitalWrite(RELAY_PIN, HIGH); // relay active LOW, so HIGH = off pinMode(BUSY_PIN, INPUT_PULLUP); // busy pin input (LOW when busy) - pinMode(RESET_PIN, INPUT_PULLUP); + pinMode(TEST_BUTTON, INPUT_PULLUP); + pinMode(RESET_BUTTON, INPUT_PULLUP); pinMode(BUZZER_PIN, OUTPUT); digitalWrite(BUZZER_PIN, LOW); @@ -732,16 +742,19 @@ void setup(){ ArduinoOTA.begin(); - // Setup OneButton callbacks - button.setPressMs(15000); // Set long press to 15 seconds - button.attachClick([]() { - // Just set flag, don't do heavy work here - btnClickPending = true; + // Setup TEST_BUTTON callbacks (click=toggle relay, long press=play test MP3) + testButton.setPressMs(2000); // 2 seconds for test MP3 play + testButton.attachClick([]() { + testBtnClickPending = true; + }); + testButton.attachLongPressStart([]() { + testBtnLongPressPending = true; }); - button.attachLongPressStart([]() { - // Just set flag - btnLongPressPending = true; + // Setup RESET_BUTTON callbacks (long press=reset admin credentials) + resetButton.setPressMs(15000); // 15 seconds for admin reset + resetButton.attachLongPressStart([]() { + resetBtnLongPressPending = true; }); @@ -754,21 +767,45 @@ void setup(){ void loop(){ ArduinoOTA.handle(); - ws.cleanupClients(); + // Handle OneButton instances + testButton.tick(); + resetButton.tick(); - // Handle OneButton - button.tick(); - - // Process button events outside of callback - if (btnClickPending) { - btnClickPending = false; - Serial.println("[BUTTON] Click detected: playing track 1000"); - playTrack(1000, "Manual Click"); + // Process TEST_BUTTON click: toggle relay manually + if (testBtnClickPending) { + testBtnClickPending = false; + manualRelayOn = !manualRelayOn; + if (manualRelayOn) { + digitalWrite(RELAY_PIN, LOW); // relay active LOW + relayOn = true; + Serial.println("[BUTTON] Manual relay ON"); + DynamicJsonDocument d(256); + d["type"] = "log"; + d["msg"] = "🔊 Relay dinyalakan manual"; + sendJsonWs(d); + } else { + digitalWrite(RELAY_PIN, HIGH); // relay off + relayOn = false; + Serial.println("[BUTTON] Manual relay OFF"); + DynamicJsonDocument d(256); + d["type"] = "log"; + d["msg"] = "🔇 Relay dimatikan manual"; + sendJsonWs(d); + } + broadcastStatus(); } - if (btnLongPressPending) { - btnLongPressPending = false; - Serial.println("[BUTTON] Long press detected: resetting admin credentials"); + // Process TEST_BUTTON long press: play test MP3 + if (testBtnLongPressPending) { + testBtnLongPressPending = false; + Serial.println("[BUTTON] Long press detected: playing track 1000"); + playTrack(1000, "Manual Test"); + } + + // Process RESET_BUTTON long press: reset admin credentials + if (resetBtnLongPressPending) { + resetBtnLongPressPending = false; + Serial.println("[BUTTON] Reset button long press: resetting admin credentials"); resetAdminToDefault(); } @@ -842,8 +879,8 @@ void loop(){ } } - // release relay if conditions met - if (!busy && relayOn && millis() > relayHoldUntil) { + // release relay if conditions met (but not if manual mode is active) + if (!busy && relayOn && millis() > relayHoldUntil && !manualRelayOn) { digitalWrite(RELAY_PIN, HIGH); // OFF relayOn = false; }