Ethernet can't get an IP address

I managed to save the IP address but the problem here is that Ethernet says static IP configuration failed, what's wrong?

#include <SPI.h>
#include <Ethernet.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>

char apSSID[33] = "LT 3 KMR";  // 32 karakter + null terminator
char apPassword[65] = "Hantu1208";   // 64 karakter + null terminator

#define W5500_CS 4
#define W5500_RESET 5  // Pin untuk reset W5500, sesuaikan jika perlu
#define SERIAL_BAUD 115200

uint8_t mac[6] = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
IPAddress w5500IP(192, 168, 1, 8);
IPAddress w5500Gateway(192, 168, 1, 1);
IPAddress w5500Subnet(255, 255, 255, 0);

AsyncWebServer server(80);
bool webServerRunning = false;
bool apRunning = false;

bool isAPMode = false;

const int switchPin = 6; // Menggunakan GPIO6 sebagai switch untuk toggle web server dan AP

bool desiredState = false;

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 100;
bool lastSwitchState = HIGH;
bool currentSwitchState = HIGH;

unsigned long previousMillis = 0;

EthernetClient client;

void resetSettings() {
  strncpy(apSSID, "LT 3 KMR", sizeof(apSSID) - 1);
  strncpy(apPassword, "Hantu1208", sizeof(apPassword) - 1);
  apSSID[sizeof(apSSID) - 1] = '\0';
  apPassword[sizeof(apPassword) - 1] = '\0';
  saveAPSettings();
  
  w5500IP = IPAddress(192, 168, 1, 8);
  w5500Gateway = IPAddress(192, 168, 1, 1);
  w5500Subnet = IPAddress(255, 255, 255, 0);
  saveW5500Settings();

  Serial.println("Semua pengaturan direset ke nilai default");
}

void loadAPSettings() {
  if (SPIFFS.exists("/ap_settings.txt")) {
    File file = SPIFFS.open("/ap_settings.txt", "r");
    if (file) {
      String ssid = file.readStringUntil('\n');
      String password = file.readStringUntil('\n');
      ssid.trim();
      password.trim();
      strncpy(apSSID, ssid.c_str(), sizeof(apSSID) - 1);
      strncpy(apPassword, password.c_str(), sizeof(apPassword) - 1);
      apSSID[sizeof(apSSID) - 1] = '\0';
      apPassword[sizeof(apPassword) - 1] = '\0';
      Serial.println("Pengaturan AP dimuat: " + String(apSSID));
      file.close();
    }
  }
}

void saveAPSettings() {
  File file = SPIFFS.open("/ap_settings.txt", "w");
  if (file) {
    file.println(apSSID);
    file.println(apPassword);
    file.close();
    Serial.println("Pengaturan AP disimpan");
  }
}

WiFiMode_t loadWiFiMode() {
  WiFiMode_t mode = WIFI_AP;  // Default mode
  if (SPIFFS.exists("/wifi_mode.txt")) {
    File file = SPIFFS.open("/wifi_mode.txt", "r");
    if (file) {
      String modeStr = file.readStringUntil('\n');
      modeStr.trim();
      mode = (WiFiMode_t)modeStr.toInt();
      file.close();
    }
  }
  return mode;
}

void resetWiFiConnection() {
  WiFi.disconnect(true);
  delay(1000);
}

void loadW5500Settings() {
  if (SPIFFS.exists("/w5500_settings.txt")) {
    File file = SPIFFS.open("/w5500_settings.txt", "r");
    if (file) {
      String ip = file.readStringUntil('\n');
      String gw = file.readStringUntil('\n');
      String sn = file.readStringUntil('\n');
      file.close();
      
      ip.trim();
      gw.trim();
      sn.trim();
      
      // Only update if valid IP addresses are found
      if (w5500IP.fromString(ip) && w5500Gateway.fromString(gw) && w5500Subnet.fromString(sn)) {
        Serial.println("W5500 settings loaded: " + ip);
      } else {
        Serial.println("Invalid W5500 settings in file, using defaults");
      }
    }
  } else {
    Serial.println("W5500 settings file not found, using defaults");
  }
  
  // Print the settings being used (either loaded or default)
  Serial.println("Using W5500 settings:");
  Serial.println("IP: " + w5500IP.toString());
  Serial.println("Gateway: " + w5500Gateway.toString());
  Serial.println("Subnet: " + w5500Subnet.toString());
}

void saveW5500Settings() {
  File file = SPIFFS.open("/w5500_settings.txt", "w");
  if (file) {
    file.println(w5500IP.toString());
    file.println(w5500Gateway.toString());
    file.println(w5500Subnet.toString());
    file.close();
    Serial.println("W5500 settings saved");
  }
}

void loadMACAddress() {
  if (SPIFFS.exists("/mac_address.txt")) {
    File file = SPIFFS.open("/mac_address.txt", "r");
    if (file) {
      String macStr = file.readStringUntil('\n');
      macStr.trim();
      sscanf(macStr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
      Serial.println("MAC address loaded: " + macStr);
      file.close();
    }
  }
}

void saveMACAddress() {
  File file = SPIFFS.open("/mac_address.txt", "w");
  if (file) {
    char macStr[18];
    snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    file.println(macStr);
    file.close();
    Serial.println("MAC address saved");
  }
}

void setupServerRoutes() {
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });
  
  server.on("/assets/css/foundation.css", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(SPIFFS, "/assets/css/foundation.css", "text/css");
  });

  server.on("/reset", HTTP_POST, [](AsyncWebServerRequest *request) {
    resetSettings();
    request->send(200, "text/plain", "Semua pengaturan direset. Memulai ulang...");
    ESP.restart();
  });

  server.on("/setap", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("ssid", true) && request->hasParam("password", true)) {
      String newSSID = request->getParam("ssid", true)->value();
      String newPassword = request->getParam("password", true)->value();
      
      strncpy(apSSID, newSSID.c_str(), sizeof(apSSID) - 1);
      strncpy(apPassword, newPassword.c_str(), sizeof(apPassword) - 1);
      apSSID[sizeof(apSSID) - 1] = '\0';  // Ensure null termination
      apPassword[sizeof(apPassword) - 1] = '\0';  // Ensure null termination
      
      saveAPSettings();
      request->send(200, "text/plain", "Pengaturan AP diperbarui. Memulai ulang...");
      ESP.restart();
    } else {
      request->send(400, "text/plain", "Permintaan tidak valid");
    }
  });

  server.on("/setw5500", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("ip", true) && request->hasParam("gateway", true) && request->hasParam("subnet", true)) {
      String ip = request->getParam("ip", true)->value();
      String gw = request->getParam("gateway", true)->value();
      String sn = request->getParam("subnet", true)->value();
      
      if (w5500IP.fromString(ip) && w5500Gateway.fromString(gw) && w5500Subnet.fromString(sn)) {
        saveW5500Settings();
        request->send(200, "text/plain", "W5500 settings updated. Restarting...");
        ESP.restart();
      } else {
        request->send(400, "text/plain", "Invalid IP format");
      }
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });

  server.on("/setmac", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("mac", true)) {
      String macStr = request->getParam("mac", true)->value();
      uint8_t newMac[6];
      if (sscanf(macStr.c_str(), "%x:%x:%x:%x:%x:%x", &newMac[0], &newMac[1], &newMac[2], &newMac[3], &newMac[4], &newMac[5]) == 6) {
        memcpy(mac, newMac, sizeof(mac));
        saveMACAddress();
        request->send(200, "text/plain", "MAC address updated. Restarting...");
        ESP.restart();
      } else {
        request->send(400, "text/plain", "Invalid MAC format");
      }
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });

  server.on("/devicestatus", HTTP_GET, [](AsyncWebServerRequest *request) {
    String response = "{";
    response += "\"ssid\":\"" + String(apSSID) + "\",";
    response += "\"ip\":\"" + WiFi.localIP().toString() + "\",";
    response += "\"w5500IP\":\"" + w5500IP.toString() + "\",";
    response += "\"w5500Gateway\":\"" + w5500Gateway.toString() + "\",";
    response += "\"w5500Subnet\":\"" + w5500Subnet.toString() + "\",";
    response += "\"freeHeap\":\"" + String(ESP.getFreeHeap()) + "\",";
    
    // Include MAC address in the response
    char macStr[18];
    snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    response += "\"macAddress\":\"" + String(macStr) + "\"";
    
    response += "}";
    request->send(200, "application/json", response);
  });
}

void setup() {
  Serial.begin(115200);

  if (!SPIFFS.begin(true)) {
    Serial.println("Terjadi kesalahan saat memasang SPIFFS");
    return;
  }
  Serial.println("SPIFFS berhasil dipasang");

  delay(1000);

  loadAPSettings();
  loadW5500Settings();
  loadMACAddress();

  WiFi.mode(WIFI_STA);

  delay(1000);  // Tunggu sebentar sebelum mencoba koneksi WiFi
  
  // Inisialisasi AP dan web server dalam keadaan mati
  webServerRunning = false;
  apRunning = false;

  SPI.begin();
  pinMode(W5500_CS, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
  digitalWrite(W5500_CS, HIGH);
  Serial.println("SPI initialized");

  // Reset W5500
  pinMode(W5500_RESET, OUTPUT);
  digitalWrite(W5500_RESET, LOW);
  delay(100);
  digitalWrite(W5500_RESET, HIGH);
  delay(100);

  Serial.println("Initializing Ethernet...");
  Ethernet.init(W5500_CS);

  Serial.println("Attempting to configure Ethernet using static IP...");
  Ethernet.begin(mac, w5500IP, w5500Gateway, w5500Subnet);

  // Wait for Ethernet to initialize
  delay(2000);

  // Check Ethernet status
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found. Please check wiring.");
  } else if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  } else {
    Serial.println("Ethernet connection established");
    IPAddress currentIP = Ethernet.localIP();
    Serial.print("Current IP Address: ");
    Serial.println(currentIP);
    Serial.print("Configured Static IP: ");
    Serial.println(w5500IP);
    
    if (currentIP == w5500IP) {
      Serial.println("Static IP configuration successful");
    } else {
      Serial.println("Static IP configuration failed");
    }

    Serial.print("Subnet Mask: ");
    Serial.println(Ethernet.subnetMask());
    Serial.print("Gateway IP: ");
    Serial.println(Ethernet.gatewayIP());
    Serial.print("DNS Server IP: ");
    Serial.println(Ethernet.dnsServerIP());
    
    char macStr[18];
    snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    Serial.print("MAC Address: ");
    Serial.println(macStr);
  }

  server.begin();
  setupServerRoutes();

  Serial.printf("Free heap: %d bytes\n", ESP.getFreeHeap());
}

void loop() {
  unsigned long currentMillis = millis();

  static bool lastSwitchState = HIGH;
  bool switchState = digitalRead(switchPin);

  if (switchState != lastSwitchState && switchState == LOW) {
    // Button is pressed (LOW) and the state has changed
    desiredState = !desiredState; // Toggle the desired state
    
    if (desiredState) {
      // Turn ON
      if (!webServerRunning || !apRunning) {
        webServerRunning = true;
        apRunning = true;
        WiFi.mode(WIFI_AP);
        WiFi.softAP(apSSID, apPassword);
        server.begin();
        Serial.println("AP dan Web server dihidupkan");
      }
    } else {
      // Turn OFF
      if (webServerRunning || apRunning) {
        webServerRunning = false;
        apRunning = false;
        WiFi.softAPdisconnect(true);
        server.end();
        WiFi.mode(WIFI_OFF);
        Serial.println("AP dan Web server dimatikan");
      }
    }
    delay(50); // Debounce delay
  }
  lastSwitchState = switchState;

  if (!webServerRunning) {
    return; // Exit the loop if web server is off
  }

  // Simple loop to maintain DHCP lease
  Ethernet.maintain();

  // Add a periodic connection check
  static unsigned long lastCheck = 0;
  if (millis() - lastCheck > 5000) { // Check every 5 seconds
    lastCheck = millis();
    if (Ethernet.linkStatus() == LinkON) {
      Serial.println("Ethernet link is UP");
      Serial.print("Current IP: ");
      Serial.println(Ethernet.localIP());
    } else {
      Serial.println("Ethernet link is DOWN");
    }
  }
}

examples of the Ethernet library work?

why do you want to use the old Ethernet library with the ESP32? in version 3 ESP32 Arduino platform has its own Ethernet library ETH.h. (alternatively you can use my EthernetESP32 library, which is more similar to the old Arduino Ethernet library)

Don't know if this is your challenge but this call is not correct.

Ethernet.begin(mac, w5500IP, w5500Gateway, w5500Subnet);
#it should be this
Ethernet.begin(mac, w5500IP, w5500Gateway, w5500Gateway, w5500Subnet);

Here are the choices:

// Manual configuration
static void begin(uint8_t *mac, IPAddress ip);
static void begin(uint8_t *mac, IPAddress ip, IPAddress dns);
static void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway);
static void begin(uint8_t *mac, IPAddress ip, IPAddress dns, IPAddress gateway, IPAddress subnet);

Hi guys, I brought up what I saved in spiff but when everything goes current it shows 0.0.0.0

I tried what is in the google tutorial, I have trouble when local ip(); always gets the value 0.0.0.0 even though Ethernet.begin calls the ip address

The latest code I made displays 255.255.255.0 instead of the ip I saved
IMG-20240903-WA0002

#include <SPI.h>
#include <Ethernet.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>

char apSSID[33] = "LT 3 KMR";  // 32 karakter + null terminator
char apPassword[65] = "Hantu1208";   // 64 karakter + null terminator

#define W5500_CS 15
#define SERIAL_BAUD 115200
#define ETHERNET_INIT_TIMEOUT 10000 // 10 seconds

uint8_t mac[6] = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
IPAddress w5500IP(192, 168, 1, 8);
IPAddress w5500Gateway(192, 168, 1, 1);
IPAddress w5500Subnet(255, 255, 255, 0);

AsyncWebServer server(80);
bool webServerRunning = false;
bool apRunning = false;

bool isAPMode = false;

const int switchPin = 5; // Menggunakan GPIO5 sebagai switch untuk toggle web server dan AP

bool desiredState = false; // New variable to track the desired state

unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 100;
bool lastSwitchState = HIGH;
bool currentSwitchState = HIGH;

unsigned long previousMillis = 0;

EthernetClient client;

void resetSettings() {
  strncpy(apSSID, "LT 3 KMR", sizeof(apSSID) - 1);
  strncpy(apPassword, "Hantu1208", sizeof(apPassword) - 1);
  apSSID[sizeof(apSSID) - 1] = '\0';
  apPassword[sizeof(apPassword) - 1] = '\0';
  saveAPSettings();
  
  w5500IP = IPAddress(192, 168, 1, 8);
  w5500Gateway = IPAddress(192, 168, 1, 1);
  w5500Subnet = IPAddress(255, 255, 255, 0);
  saveW5500Settings();

  Serial.println("Semua pengaturan direset ke nilai default");
}

void loadAPSettings() {
  if (SPIFFS.exists("/ap_settings.txt")) {
    File file = SPIFFS.open("/ap_settings.txt", "r");
    if (file) {
      String ssid = file.readStringUntil('\n');
      String password = file.readStringUntil('\n');
      ssid.trim();
      password.trim();
      strncpy(apSSID, ssid.c_str(), sizeof(apSSID) - 1);
      strncpy(apPassword, password.c_str(), sizeof(apPassword) - 1);
      apSSID[sizeof(apSSID) - 1] = '\0';
      apPassword[sizeof(apPassword) - 1] = '\0';
      Serial.println("Pengaturan AP dimuat: " + String(apSSID));
      file.close();
    }
  }
}

void saveAPSettings() {
  File file = SPIFFS.open("/ap_settings.txt", "w");
  if (file) {
    file.println(apSSID);
    file.println(apPassword);
    file.close();
    Serial.println("Pengaturan AP disimpan");
  }
}

WiFiMode_t loadWiFiMode() {
  WiFiMode_t mode = WIFI_AP;  // Default mode
  if (SPIFFS.exists("/wifi_mode.txt")) {
    File file = SPIFFS.open("/wifi_mode.txt", "r");
    if (file) {
      String modeStr = file.readStringUntil('\n');
      modeStr.trim();
      mode = (WiFiMode_t)modeStr.toInt();
      file.close();
    }
  }
  return mode;
}

void resetWiFiConnection() {
  WiFi.disconnect(true);
  delay(1000);
}

void loadW5500Settings() {
  if (SPIFFS.exists("/w5500_settings.txt")) {
    File file = SPIFFS.open("/w5500_settings.txt", "r");
    if (file) {
      String ip = file.readStringUntil('\n');
      String gw = file.readStringUntil('\n');
      String sn = file.readStringUntil('\n');
      file.close();
      
      ip.trim();
      gw.trim();
      sn.trim();
      
      // Only update if valid IP addresses are found
      if (w5500IP.fromString(ip) && w5500Gateway.fromString(gw) && w5500Subnet.fromString(sn)) {
        Serial.println("W5500 settings loaded: " + ip);
      } else {
        Serial.println("Invalid W5500 settings in file, using defaults");
      }
    }
  } else {
    Serial.println("W5500 settings file not found, using defaults");
  }
  
  // Print the settings being used (either loaded or default)
  Serial.println("Using W5500 settings:");
  Serial.println("IP: " + w5500IP.toString());
  Serial.println("Gateway: " + w5500Gateway.toString());
  Serial.println("Subnet: " + w5500Subnet.toString());
}

void saveW5500Settings() {
  File file = SPIFFS.open("/w5500_settings.txt", "w");
  if (file) {
    file.println(w5500IP.toString());
    file.println(w5500Gateway.toString());
    file.println(w5500Subnet.toString());
    file.close();
    Serial.println("W5500 settings saved");
  }
}

void loadMACAddress() {
  if (SPIFFS.exists("/mac_address.txt")) {
    File file = SPIFFS.open("/mac_address.txt", "r");
    if (file) {
      String macStr = file.readStringUntil('\n');
      macStr.trim();
      sscanf(macStr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
      Serial.println("MAC address loaded: " + macStr);
      file.close();
    }
  }
}

void saveMACAddress() {
  File file = SPIFFS.open("/mac_address.txt", "w");
  if (file) {
    char macStr[18];
    snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    file.println(macStr);
    file.close();
    Serial.println("MAC address saved");
  }
}

void setupServerRoutes() {
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(SPIFFS, "/index.html", "text/html");
  });
  
  server.on("/assets/css/foundation.css", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(SPIFFS, "/assets/css/foundation.css", "text/css");
  });

  server.on("/reset", HTTP_POST, [](AsyncWebServerRequest *request) {
    resetSettings();
    request->send(200, "text/plain", "Semua pengaturan direset. Memulai ulang...");
    ESP.restart();
  });

  server.on("/setap", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("ssid", true) && request->hasParam("password", true)) {
      String newSSID = request->getParam("ssid", true)->value();
      String newPassword = request->getParam("password", true)->value();
      
      strncpy(apSSID, newSSID.c_str(), sizeof(apSSID) - 1);
      strncpy(apPassword, newPassword.c_str(), sizeof(apPassword) - 1);
      apSSID[sizeof(apSSID) - 1] = '\0';  // Ensure null termination
      apPassword[sizeof(apPassword) - 1] = '\0';  // Ensure null termination
      
      saveAPSettings();
      request->send(200, "text/plain", "Pengaturan AP diperbarui. Memulai ulang...");
      ESP.restart();
    } else {
      request->send(400, "text/plain", "Permintaan tidak valid");
    }
  });

  server.on("/setw5500", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("ip", true) && request->hasParam("gateway", true) && request->hasParam("subnet", true)) {
      String ip = request->getParam("ip", true)->value();
      String gw = request->getParam("gateway", true)->value();
      String sn = request->getParam("subnet", true)->value();
      
      if (w5500IP.fromString(ip) && w5500Gateway.fromString(gw) && w5500Subnet.fromString(sn)) {
        saveW5500Settings();
        request->send(200, "text/plain", "W5500 settings updated. Restarting...");
        ESP.restart();
      } else {
        request->send(400, "text/plain", "Invalid IP format");
      }
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });

  server.on("/setmac", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("mac", true)) {
      String macStr = request->getParam("mac", true)->value();
      uint8_t newMac[6];
      if (sscanf(macStr.c_str(), "%x:%x:%x:%x:%x:%x", &newMac[0], &newMac[1], &newMac[2], &newMac[3], &newMac[4], &newMac[5]) == 6) {
        memcpy(mac, newMac, sizeof(mac));
        saveMACAddress();
        request->send(200, "text/plain", "MAC address updated. Restarting...");
        ESP.restart();
      } else {
        request->send(400, "text/plain", "Invalid MAC format");
      }
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });

  server.on("/devicestatus", HTTP_GET, [](AsyncWebServerRequest *request) {
    String response = "{";
    response += "\"ssid\":\"" + String(apSSID) + "\",";
    response += "\"ip\":\"" + WiFi.localIP().toString() + "\",";
    response += "\"w5500IP\":\"" + w5500IP.toString() + "\",";
    response += "\"w5500Gateway\":\"" + w5500Gateway.toString() + "\",";
    response += "\"w5500Subnet\":\"" + w5500Subnet.toString() + "\",";
    response += "\"freeHeap\":\"" + String(ESP.getFreeHeap()) + "\",";
    
    // Include MAC address in the response
    char macStr[18];
    snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    response += "\"macAddress\":\"" + String(macStr) + "\"";
    
    response += "}";
    request->send(200, "application/json", response);
  });
}

void setup() {
  Serial.begin(SERIAL_BAUD);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  if (!SPIFFS.begin(true)) {
    Serial.println("An error occurred while mounting SPIFFS");
    return;
  }
  Serial.println("SPIFFS mounted successfully");

  delay(1000);

  loadAPSettings();
  loadW5500Settings();
  loadMACAddress();

  WiFi.mode(WIFI_STA);

  delay(1000);  // Wait a bit before trying WiFi connection
  
  // Initialize AP and web server in OFF state
  webServerRunning = false;
  apRunning = false;

  SPI.begin();
  pinMode(W5500_CS, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
  digitalWrite(W5500_CS, HIGH);
  Serial.println("SPI initialized");
  delay(100);  // Short delay after SPI initialization

  Serial.println("Initializing Ethernet...");
  Ethernet.init(W5500_CS);

  // Print stored W5500 settings
  Serial.println("Stored W5500 settings:");
  Serial.println("IP: " + w5500IP.toString());
  Serial.println("Gateway: " + w5500Gateway.toString());
  Serial.println("Subnet: " + w5500Subnet.toString());

  // Try to configure using stored static IP
  Serial.println("Configuring Ethernet using stored static IP...");
  Ethernet.begin(mac, w5500IP, w5500Gateway, w5500Subnet);

  // Print Ethernet connection details
  Serial.print("IP Address: ");
  Serial.println(Ethernet.localIP());
  Serial.print("Subnet Mask: ");
  Serial.println(Ethernet.subnetMask());
  Serial.print("Gateway IP: ");
  Serial.println(Ethernet.gatewayIP());
  Serial.print("DNS Server IP: ");
  Serial.println(Ethernet.dnsServerIP());

  // Check Ethernet link status
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  } else {
    Serial.println("Ethernet connection established");
    
    // Print MAC address
    char macStr[18];
    snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    Serial.print("MAC Address: ");
    Serial.println(macStr);
  }

  server.begin();
  setupServerRoutes();

  Serial.printf("Free heap: %d bytes\n", ESP.getFreeHeap());
}

void loop() {
  unsigned long currentMillis = millis();

  static bool lastSwitchState = HIGH;
  bool switchState = digitalRead(switchPin);

  // Add a periodic connection check
  static unsigned long lastCheck = 0;
  if (millis() - lastCheck > 5000) { // Check every 5 seconds
    lastCheck = millis();
    if (Ethernet.linkStatus() == LinkON) {
      Serial.println("Ethernet link is UP");
    } else {
      Serial.println("Ethernet link is DOWN");
    }
  }

  // Simple loop to maintain DHCP lease
  Ethernet.maintain();

  if (switchState != lastSwitchState && switchState == LOW) {
    // Button is pressed (LOW) and the state has changed
    desiredState = !desiredState; // Toggle the desired state
    
    if (desiredState) {
      // Turn ON
      if (!webServerRunning || !apRunning) {
        webServerRunning = true;
        apRunning = true;
        WiFi.mode(WIFI_AP);
        WiFi.softAP(apSSID, apPassword);
        server.begin();
        Serial.println("AP dan Web server dihidupkan");
      }
    } else {
      // Turn OFF
      if (webServerRunning || apRunning) {
        webServerRunning = false;
        apRunning = false;
        WiFi.softAPdisconnect(true);
        server.end();
        WiFi.mode(WIFI_OFF);
        Serial.println("AP dan Web server dimatikan");
      }
    }
    delay(50); // Debounce delay
  }
  lastSwitchState = switchState;

  if (!webServerRunning) {
    return; // Exit the loop if web server is off
  }
}

Did you not read my post? Or did you not understand it?
This is wrong. You are setting the gateway with the subnet value.

By far the easiest way to get a fixed IP address is to configure it in the router. Use the router's web page to assign a fixed (static) IP address to the Arduino's MAC address. Then use regular DCHP in the Arduino, it will be given the same IP address every time.

Looks like you don't understand, see what I followed here

I understand. That is NOT the header file you included.
You used
#include <Ethernet.h>

/home/gonit/Dokumen/Project file/77/w55000/w55000.ino:298:33: error: expected primary-expression before 'w5500IP'
  298 |   Ethernet.begin(mac, IPAddress w5500IP, IPAddress w5500Gateway, IPAddress w5500Subnet);
      |                                 ^~~~~~~
/home/gonit/Dokumen/Project file/77/w55000/w55000.ino:298:52: error: expected primary-expression before 'w5500Gateway'
  298 |   Ethernet.begin(mac, IPAddress w5500IP, IPAddress w5500Gateway, IPAddress w5500Subnet);
      |                                                    ^~~~~~~~~~~~
/home/gonit/Dokumen/Project file/77/w55000/w55000.ino:298:76: error: expected primary-expression before 'w5500Subnet'
  298 |   Ethernet.begin(mac, IPAddress w5500IP, IPAddress w5500Gateway, IPAddress w5500Subnet);

exit status 1

Compilation error: expected primary-expression before 'w5500IP'

Did you import the Adafruit Ethernet2 library?
IDE -> Tools -> Manage Libraries
Search for "Ethernet2"

examples are in the Arduino IDE in the File->Examples menu

I have tried example but the ip is still 0.0.0.0 when I display Ethernet.localip();

did you use Ethernet.init to set the CS pin in the example? did you wire the Ethernet module to the default SPI pins?