#include #include #include #include #include #include #include #include // Tambahkan library EEPROM const char* serverName = "https://touchlight.000webhostapp.com/esp-outputs-action.php?action=outputs_state&board=2"; const long interval = 5000; // Interval waktu pembaruan diatur menjadi 5 detik unsigned long previousMillis = 0; String outputsState; // Mendefinisikan NTP Client untuk mendapatkan waktu WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "pool.ntp.org", 7 * 3600, 60000); /* Offset waktu 7 jam untuk WIB (GMT+7) */ // Menyimpan status output terakhir di EEPROM int lastOutputStates[4]; // Asumsikan keluaran 4 pin void loadEEPROM() { for (int i = 0; i < 4; i++) { lastOutputStates[i] = EEPROM.read(i); } } void saveEEPROM() { for (int i = 0; i < 4; i++) { EEPROM.write(i, lastOutputStates[i]); } } void setup() { Serial.begin(115200); WiFiManager wifiManager; wifiManager.autoConnect("AutoConnectAP"); // Nama default dari AP Serial.println("Terhubung ke jaringan WiFi dengan Alamat IP:"); Serial.println(WiFi.localIP()); // Menginisialisasi klien NTP timeClient.begin(); // Memuat status output terakhir dari EEPROM loadEEPROM(); } void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; // Memastikan baris ini selalu diperbarui // Mendefinisikan variabel untuk menyimpan status relay saat ini int currentRelayState[4]; for (int i = 0; i < 4; i++) { currentRelayState[i] = lastOutputStates[i]; // Inisialisasi dengan nilai terakhir } // Memeriksa status koneksi WiFi if (WiFi.status() == WL_CONNECTED) { timeClient.update(); // Memperbarui NTP client outputsState = httpGETRequest(serverName); Serial.println(outputsState); JSONVar myObject = JSON.parse(outputsState); // JSON.typeof(jsonVar) dapat digunakan untuk mendapatkan tipe variabel if (JSON.typeof(myObject) == "undefined") { Serial.println("Parsing input failed!"); return; } Serial.print("JSON object = "); Serial.println(myObject); // myObject.keys() dapat digunakan untuk mendapatkan array dari semua kunci dalam objek JSONVar keys = myObject.keys(); for (int i = 0; i < keys.length(); i++) { JSONVar value = myObject[keys[i]]; int gpioPin = atoi(keys[i]); int gpioState = atoi(value); pinMode(gpioPin, OUTPUT); digitalWrite(gpioPin, gpioState); currentRelayState[i] = gpioState; // Perbarui currentRelayState // Menyimpan status output terbaru ke EEPROM lastOutputStates[i] = gpioState; saveEEPROM(); printGPIOStatus(gpioPin, gpioState); } } else { Serial.println("WiFi Disconnected"); delay(50); // Pertahankan status relay menggunakan currentRelayState for (int i = 0; i < 4; i++) { pinMode(i, OUTPUT); digitalWrite(i, currentRelayState[i]); printGPIOStatus(i, currentRelayState[i]); } } } } String httpGETRequest(const char* serverName) { WiFiClientSecure *client = new WiFiClientSecure; // Mengatur client yang aman tanpa sertifikat client->setInsecure(); HTTPClient https; // Alamat IP atau nama domain dengan path URL https.begin(*client, serverName); // Mengirimkan permintaan HTTP GET int httpResponseCode = https.GET(); String payload = "{}"; if (httpResponseCode > 0) { Serial.print("HTTP Response code: "); Serial.println(httpResponseCode); payload = https.getString(); } else { Serial.print("Error code: "); Serial.println(httpResponseCode); } // Membebaskan sumber daya https.end(); delete client; // Membebaskan memori client return payload; } void printGPIOStatus(int gpio, int state) { // Mendapatkan waktu saat ini String formattedTime = timeClient.getFormattedTime(); Serial.print("Time: "); Serial.print(formattedTime); Serial.print(" - GPIO "); Serial.print(gpio); Serial.print(" set to : "); Serial.println(state); }