The NTP Server always says failed to connect and write fs.h cannot be rewritten when there is already a file there

The NTP Server always says failed to connect and write fs.h cannot be rewritten when there is already a file there

#include <ESP8266WiFi.h>
#include <ESPAsyncWebServer.h>
#include <TM1637Display.h>
#include <FS.h>
#include <TimeLib.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <Ticker.h>

#define CLK D5
#define DIO D6

TM1637Display displayLED(CLK, DIO);
const uint8_t allON[] = {0xff, 0xff, 0xff, 0xff};
const uint8_t allOFF[] = {0x00, 0x00, 0x00, 0x00};

const char *apSSID = "Clock Setting";
const char *apPassword = "12345678";

String routerSSID = "";
String routerPassword = "";

unsigned long previousMillisclock = 0;
const long intervalclock = 1000;
unsigned long previousMillisblink = 0;
const long intervalblink = 500;
unsigned long lastWiFiCheckMillis = 0;
const long wifiCheckInterval = 10000; // Check WiFi connection every 10 seconds
unsigned long lastNTPUpdate = 0;
const unsigned long ntpUpdateInterval = 3600000; // Update every hour

bool colonOn = true;
time_t currentTime = 0;

AsyncWebServer server(80);
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

Ticker ntpUpdateTimer;
bool ntpUpdateTimeout = false;

String ntpServer = ""; // Default NTP server

bool displayNeedsUpdate = false;

void loadWiFiCredentials() {
  if (SPIFFS.exists("/wifi_creds.txt")) {
    File file = SPIFFS.open("/wifi_creds.txt", "r");
    if (file) {
      routerSSID = file.readStringUntil('\n');
      routerPassword = file.readStringUntil('\n');
      routerSSID.trim();
      routerPassword.trim();
      file.close();
    }
  }
}

void saveWiFiCredentials() {
  File file = SPIFFS.open("/wifi_creds.txt", "w");
  if (file) {
    file.println(routerSSID);
    file.println(routerPassword);
    file.close();
  }
}

void connectToWiFi() {
  if (routerSSID.length() > 0 && routerPassword.length() > 0) {
    Serial.println("Connecting to WiFi...");
    WiFi.begin(routerSSID.c_str(), routerPassword.c_str());
    int attempts = 0;
    while (WiFi.status() != WL_CONNECTED && attempts < 20) {
      delay(500);
      Serial.print(".");
      attempts++;
    }
    if (WiFi.status() == WL_CONNECTED) {
      Serial.println("\nConnected to WiFi router");
      Serial.print("IP address: ");
      Serial.println(WiFi.localIP());
    } else {
      Serial.println("\nFailed to connect to WiFi router");
    }
  } else {
    Serial.println("No saved WiFi credentials");
  }
}

void loadNTPServer() {
  if (SPIFFS.exists("/ntp_server.txt")) {
    File file = SPIFFS.open("/ntp_server.txt", "r");
    if (file) {
      ntpServer = file.readStringUntil('\n');
      ntpServer.trim();
      file.close();
    }
  }
}

void saveNTPServer(String server) {
  File file = SPIFFS.open("/ntp_server.txt", "w");
  if (file) {
    file.println(server);
    file.close();
  }
}

void updateNTPTime() {
  if (timeClient.update()) {
    currentTime = timeClient.getEpochTime();
    setTime(hour(currentTime), minute(currentTime), second(currentTime), day(currentTime), month(currentTime), year(currentTime));
    lastNTPUpdate = millis();
    Serial.println("NTP time updated successfully");
    displayNeedsUpdate = true; // Set flag to update display
  } else {
    Serial.println("Failed to update NTP time");
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("Starting Setup...");
  
  if (!SPIFFS.begin()) {
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }
  Serial.println("SPIFFS mounted successfully");
  
  loadWiFiCredentials();
  
  // Always set up soft AP
  WiFi.softAP(apSSID, apPassword);
  Serial.println("WiFi AP Initialized");
  
  connectToWiFi();
  
  loadNTPServer();
  timeClient.setPoolServerName(ntpServer.c_str());
  timeClient.begin();
  if (!timeClient.forceUpdate()) {
    Serial.println("Failed to get time from NTP server on startup");
  }
  
  displayLED.setBrightness(7);
  displayLED.clear();
  
  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("/setwifi", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("ssid", true) && request->hasParam("password", true)) {
      routerSSID = request->getParam("ssid", true)->value();
      routerPassword = request->getParam("password", true)->value();
      saveWiFiCredentials();
      request->send(200, "text/plain", "WiFi credentials updated. Restarting...");
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });
  
  server.on("/getnow", HTTP_GET, [](AsyncWebServerRequest *request) {
    char buffer[9];
    sprintf(buffer, "%02d:%02d", hour(currentTime), minute(currentTime));
    Serial.print("Sending current time: ");
    Serial.println(buffer);
    request->send(200, "text/plain", buffer);
  });
  
  server.on("/settime", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("time", true)) {
      String timeParam = request->getParam("time", true)->value();
      int hh, mm;
      if (sscanf(timeParam.c_str(), "%d:%d", &hh, &mm) == 2) {
        setTime(hh, mm, 0, day(), month(), year());
        currentTime = now();
        Serial.print("Received time: ");
        Serial.println(timeParam);
        displayNeedsUpdate = true; // Set flag to update display
        request->send(200, "text/plain", "Time set");
      } else {
        request->send(400, "text/plain", "Invalid time format");
      }
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });
  
  server.on("/devicestatus", HTTP_GET, [](AsyncWebServerRequest *request) {
    String response = "{";
    response += "\"ssid\":\"" + String(WiFi.SSID()) + "\",";
    response += "\"ip\":\"" + WiFi.localIP().toString() + "\",";
    response += "\"ntpConnected\":" + String(timeClient.update() ? "true" : "false") + ",";
    response += "\"currentTime\":\"" + timeClient.getFormattedTime() + "\",";
    response += "\"lastNTPUpdate\":\"" + String(lastNTPUpdate) + "\"";
    response += "}";
    request->send(200, "application/json", response);
  });

  server.on("/getntpserver", HTTP_GET, [](AsyncWebServerRequest *request) {
    request->send(200, "text/plain", ntpServer);
  });
  
  server.on("/setntpserver", HTTP_POST, [](AsyncWebServerRequest *request) {
    if (request->hasParam("server", true)) {
      String newServer = request->getParam("server", true)->value();
      ntpServer = newServer;
      saveNTPServer(ntpServer);
      timeClient.setPoolServerName(ntpServer.c_str());
      request->send(200, "text/plain", "NTP server updated");
    } else {
      request->send(400, "text/plain", "Invalid request");
    }
  });
  
  server.begin();
  Serial.println("Server started");
}

void updateDisplay() {
  if (colonOn) {
    displayLED.showNumberDecEx(hour(currentTime) * 100 + minute(currentTime), 0x40, true);
  } else {
    displayLED.showNumberDec(hour(currentTime) * 100 + minute(currentTime), true);
  }
  colonOn = !colonOn;
}

void loop() {
  unsigned long currentMillis = millis();
  
  if (currentMillis - previousMillisclock >= intervalclock) {
    previousMillisclock = currentMillis;
    currentTime++;
    displayNeedsUpdate = true; // Set flag to update display
  }
  
  if (currentMillis - lastWiFiCheckMillis >= wifiCheckInterval) {
    lastWiFiCheckMillis = currentMillis;
    if (WiFi.status() != WL_CONNECTED) {
      Serial.println("WiFi disconnected. Attempting to reconnect...");
      connectToWiFi();
    } else {
      // Check if it's time to update NTP
      if (currentMillis - lastNTPUpdate >= ntpUpdateInterval) {
        updateNTPTime();
      }
    }
  }

  // Update display if needed
  if (displayNeedsUpdate) {
    updateDisplay();
    displayNeedsUpdate = false;
  }
}
<!doctype html>
<html class="no-js" lang="en">
<head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CLOCK SETTING</title>
    <link rel="stylesheet" href="assets/css/foundation.css">
    <script>
        function syncTime() {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "/settime", true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            var date = new Date();
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var currentTime = hours + ":" + minutes;
            xhr.send("time=" + currentTime);
            xhr.onload = function() {
                if (xhr.status == 200) {
                    alert("Time synced successfully");
                } else {
                    alert("Failed to sync time");
                }
            };
        }

        function syncNTP() {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/syncntp", true);
            xhr.onload = function() {
                if (xhr.status == 200) {
                    alert("NTP sync successful");
                    getDeviceStatus();
                } else {
                    alert("NTP sync failed");
                }
            };
            xhr.send();
        }

        function getNTPServer() {
            var xhr = new XMLHttpRequest();
            xhr.open("GET", "/getntpserver", true);
            xhr.onload = function() {
                if (xhr.status == 200) {
                    document.getElementById("ntpServer").value = xhr.responseText;
                }
            };
            xhr.send();
        }

        function setNTPServer() {
            var server = document.getElementById("ntpServer").value;
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "/setntpserver", true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.send("server=" + server);
            xhr.onload = function() {
                if (xhr.status == 200) {
                    alert("NTP server updated successfully");
                } else {
                    alert("Failed to update NTP server");
                }
            };
        }

        function getDeviceStatus() {
          var xhr = new XMLHttpRequest();
          xhr.open("GET", "/devicestatus", true);
          xhr.onload = function() {
              if (xhr.status == 200) {
                  var status = JSON.parse(xhr.responseText);
                  document.getElementById("wifiName").innerText = status.ssid;
                  document.getElementById("ipAddress").innerText = status.ip;
                  document.getElementById("ntpStatus").innerText = status.ntpConnected ? "Connected" : "Not Connected";
                  document.getElementById("currentTime").innerText = status.currentTime;
                  document.getElementById("lastNTPUpdate").innerText = new Date(parseInt(status.lastNTPUpdate)).toLocaleString();
              }
          };
          xhr.send();
        }

        window.onload = function() {
            getNTPServer();
            getDeviceStatus();
        };
    </script>
</head>
<body>
    <div class="grid-container">
        <div class="grid-x grid-padding-x">
            <div class="large-12 text-center cell">
                <div class="grid-x grid-padding-y">
                    <div class="large-12 cell">
                        <h3>CLOCK SETTING</h3>
                    </div>
                </div>
                <div class="grid-x grid-padding-x">
                    <div class="large-12 cell">
                        <div class="grid-x grid-margin-x">
                            <div class="large-6 medium-6 large-offset-3 medium-offset-3 cell">
                                <div class="callout">
                                    <div class="grid-x grid-padding-x">
                                        <div class="large-12 medium-12 small-12 cell">
                                            WiFi Settings
                                            <div class="grid-x grid-margin-x">
                                                <div class="large-12 medium-12 small-12 cell">
                                                    <input type="text" id="wifiSSID" placeholder="WiFi SSID">
                                                </div>
                                                <div class="large-12 medium-12 small-12 cell">
                                                    <input type="password" id="wifiPassword" placeholder="WiFi Password">
                                                </div>
                                                <div class="large-12 medium-12 small-12 cell">
                                                    <button class="submit success button" onclick="setWiFi()">Set WiFi Credentials</button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="grid-x grid-padding-x">
                                        <div class="large-12 medium-12 small-12 cell">
                                            <div class="callout">
                                                <div class="grid-x grid-padding-x">
                                                    <div class="large-12 medium-12 small-12 cell">
                                                        <h4>Device Status</h4>
                                                        <p>WiFi Name: <span id="wifiName"></span></p>
                                                        <p>IP Address: <span id="ipAddress"></span></p>
                                                        <p>NTP Server Status: <span id="ntpStatus"></span></p>
                                                        <p>Current Time: <span id="currentTime"></span></p>
                                                        <p>Last NTP Update: <span id="lastNTPUpdate"></span></p>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="grid-x grid-padding-x grid-padding-y">
                            <div class="large-6 medium-6 cell">
                                <div class="callout">
                                    <div class="grid-x grid-padding-x">
                                        <div class="large-12 medium-12 small-12 cell">
                                            MANUAL
                                            <div class="grid-x grid-margin-x">
                                                <div class="large-12 medium-12 small-12 cell">
                                                    <button class="submit success button" onclick="syncTime()">Sync Time</button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div class="large-6 medium-6 cell">
                                <div class="callout">
                                    <div class="grid-x grid-padding-x">
                                        <div class="large-12 medium-12 small-12 cell">
                                            NTP
                                            <div class="grid-x grid-margin-x">
                                                <div class="large-12 medium-12 small-12 cell">
                                                    <input type="text" id="ntpServer" placeholder="">
                                                </div>
                                                <div class="large-12 medium-12 small-12 cell">
                                                  <button class="submit success button" onclick="setNTPServer()">Set NTP Server</button>                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        function setWiFi() {
            var ssid = document.getElementById("wifiSSID").value;
            var password = document.getElementById("wifiPassword").value;
            var xhr = new XMLHttpRequest();
            xhr.open("POST", "/setwifi", true);
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            xhr.send("ssid=" + encodeURIComponent(ssid) + "&password=" + encodeURIComponent(password));
            xhr.onload = function() {
                if (xhr.status == 200) {
                    alert("WiFi credentials updated successfully. The device will restart.");
                } else {
                    alert("Failed to update WiFi credentials");
                }
            };
        }
    </script>
</body>
</html>

You did not even write a question.
So just as a guessing: If you haven't yet connected to the Wifi
because your screenshot shows an empty SSID-input-field

It is very clear that you can't connect to a NTP-server.

You should describe in much more detail what you have really done to narrow down the problem.

You can't expect that somebody will take this code-example and writes a specialised
but long "if you do this ... you will see this error-behaviour" list

Do you really need to input the ntp-servers adress on the website?
Most codes I have seen so far use a hard coded ntp-server-adress.

Your code uses an into the html-code embedded javascript for synchronising the time
which means javascript has to be enabled in the browser that is used for showing the web-site.

If java-script is enabled or not is something you can't control from inside the arduino-code.
So me personal I would prefer a solution that does not depend on that.

Pay attention to the website, the status is no connect on NTP. I also can't save a new file to save the wifi variables when I change another wifi and ntp server. there is one more thing, the clock that appears on the TM1637 on NTP is not the same as the manual syncron clock

void loadNTPServer() {
  if (SPIFFS.exists("/ntp_server.txt")) {
    File file = SPIFFS.open("/ntp_server.txt", "r");
    if (file) {
      ntpServer = file.readStringUntil('\n');
      ntpServer.trim();
      file.close();
    }
  }
}

void saveNTPServer(String server) {
  File file = SPIFFS.open("/ntp_server.txt", "w");
  if (file) {
    file.println(server);
    file.close();
  }
}
void loadWiFiCredentials() {
  if (SPIFFS.exists("/wifi_creds.txt")) {
    File file = SPIFFS.open("/wifi_creds.txt", "r");
    if (file) {
      routerSSID = file.readStringUntil('\n');
      routerPassword = file.readStringUntil('\n');
      routerSSID.trim();
      routerPassword.trim();
      file.close();
    }
  }
}

void saveWiFiCredentials() {
  File file = SPIFFS.open("/wifi_creds.txt", "w");
  if (file) {
    file.println(routerSSID);
    file.println(routerPassword);
    file.close();
  }
}

may be you start first with a definition what do you really want to achieve?

Because most of people are just using the time.h on the ESP which comes with a full working NTP.
NTPClient.h is not needed for ESPs.

Here I have some information about NTP on an ESP8266.
https://werner.rothschopf.net/202011_arduino_esp8266_ntp_en.htm

and here I have a working example for the user configuration of NTP server and timezone setting:
https://werner.rothschopf.net/microcontroller/202402_arduino_esp_ntp_user_configuration.htm