Zugriff auf Webseite nur im setup-Teil möglich

Hallo,
Beschäftige mich mit dem "ESP8266 Server".
Als Grundlage dienen dabei die Unterlagen von https://fipsok.de/.
In meinem Hauptprogramm möchte ich mit der Funktion

twilight(12.348283, 51.345751); // geographische Länge und Breite

den Sonnenlauf berechnen und mit dem Webbrowser auf die Ergebnisse zugreifen.
Wenn ich die Funktion im "setup-Teil" aufrufe funktioniert der Zugriff auf die Webseite.
Wenn ich aber die Funktion im "loop-Teil" aufrufe werden die Werte berechnet (siehe serielle Ausgabe) aber ich kann im Webbrowser nicht auf die Daten zugreifen:

Fehler: Netzwerk-Zeitüberschreitung. Der Server unter 192.xxx.xxx.xx braucht zu lange, um eine Antwort zu senden.

Habe keine Ahnung an was das liegen könnte.
Ich hoffe, dass jemand eine Idee hat was ich unzureichend berücksichtigt habe.
Vielen Dank im Voraus für eure Hilfe.

Grüße

Mein "main-Programm":

// ****************************************************************
// Sketch Esp8266 Webserver Modular(Tab)
// created: Jens Fleischer, 2018-05-16
// last mod: Jens Fleischer, 2020-12-28
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 - 3.0.2
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Switch, Sonoff Dual
/******************************************************************
  Copyright (c) 2018 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Der WebServer Tab ist der Haupt Tab mit "setup" und "loop".
// #include <LittleFS.h> bzw. #include <FS.h> und #include <ESP8266WebServer.h> 
// müssen im Haupttab aufgerufen werden.
// Ein Connect Tab ist erforderlich.
// Inklusive Arduino OTA-Updates (Erfordert freien Flash-Speicher)
/**************************************************************************************/

#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>         // https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html
#include <LittleFS.h>           // Library für Dateisystem LittleFS
//#include <FS.h>               // Library für Dateisystem Spiffs einkommentieren wenn erforderlich

#include <time.h>


struct tm tm;   //Kalenderzeit

ESP8266WebServer server(80);

String sketchName() {           // Dateiname für den Admin Tab ab EspCoreVersion 2.6.0
  char file[sizeof(__FILE__)] = __FILE__;
  char * pos = strrchr(file, '.'); *pos = '\0';
  return file;
}

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
  
  //setupFS();                    // setupFS(); oder spiffs(); je nach Dateisystem
  connectWifi();
  //admin();
  //bme280();
  //bme280Duo();
  //dht22();
  //ds18b20();
  //espboardLed();
  //onboardLed();               // Die Tabs die du nutzen möchtest, musst du Einkommentieren
  setupTime();
  //ds18b20list();
  //bh1750();
  //dualRelais();
  //singleTimerSwitch();

  //AM2306();   //Messdaten vom Sensor am2306 einholen

  //Aufruf Berechnung Sonnenaufgang/Sonnernuntergang
  twilight(12.348283, 51.345751);  // geographische Länge und Breite

  ArduinoOTA.onStart([]() {
    //save();                   // Wenn Werte vor dem Neustart gespeichert werden sollen
  });
  ArduinoOTA.begin();
  server.begin();
}


void loop() {
  ArduinoOTA.handle();
  server.handleClient();
  if (millis() < 0x2FFF || millis() > 0xFFFFF0FF) {    // Die Funktion "runtime()" wird nur für den Admin Tab gebraucht.
   // runtime();                                         // Auskommentieren falls du den Admin Tab nicht nutzen möchtest.
  }
 }

Als Tab habe ich das Programm für den Sonnenlauf eingebunden:

// ****************************************************************
// Sketch Esp8266 Sonnen Auf/Untergang Modular(Tab)
// created: Jens Fleischer, 2019-01-05
// last mod: Jens Fleischer, 2021-04-24
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 / 2.5.2 / 2.6.3 / 2.7.4
// Getestet auf: Nodemcu, Wemos D1 Mini Pro
/******************************************************************
  Copyright (c) 2018 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Diese Version von Sonnenlauf sollte als Tab eingebunden werden.
// Der Lokalzeit Tab (bzw. "struct tm") ist zum ausführen erforderlich.
// Gib beim Aufrufen der Funktion "twilight(Länge, Breite)"
// den Längen- und Breitengrad deines Ortes an.
// "twilight(12.348283, 51.345751);" https://www.laengengrad-breitengrad.de/
/**************************************************************************************/

struct SunTime {
  char sunrise[6];
  char sunset[6];
};

void twilight(const double longitude, const double latitude) {
  SunTime sun;
  localTime();                                                                   // Sollte die Lokalzeit schon im loop eingebunden sein, auskommentieren!
  static byte lastday, lastdst;
  if (tm.tm_mday != lastday || tm.tm_isdst != lastdst) {                         // Sonnenlauf für Tage mit Zeitumstellung zweimal Täglich berechnen.
    lastday = tm.tm_mday;
    lastdst = tm.tm_isdst;
    const double h = -0.833333333333333 * DEG_TO_RAD;
    const double w = latitude * DEG_TO_RAD;
    double JD = julianDate(1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday);
    double T = (JD - 2451545.0) / 36525.0;
    double DK;
    double EOT = calculateEOT(DK, T);
    double differenceTime = 12.0 * acos((sin(h) - sin(w) * sin(DK)) / (cos(w) * cos(DK))) / PI;
    strcpy(sun.sunrise, outputFormat((12.0 - differenceTime - EOT) - longitude / 15.0 + (_timezone* -1) / 3600 + tm.tm_isdst));
    strcpy(sun.sunset, outputFormat((12.0 + differenceTime - EOT) - longitude / 15.0 + (_timezone* -1) / 3600 + tm.tm_isdst));
    Serial.printf("Sonnenaufgang: %s\nSonnenuntergang: %s\n", sun.sunrise, sun.sunset);
    server.on("/sun", [=]() {
      char buf[18];
      snprintf(buf, sizeof(buf), "[\"%s\",\"%s\"]", sun.sunrise, sun.sunset);
      server.send(200, "application/json", buf);
    });
  }
}

double julianDate (int y, int m, int d) {        // Gregorianischer Kalender
  if (m <= 2) {
    m = m + 12;
    y = y - 1;
  }
  int gregorian = (y / 400) - (y / 100) + (y / 4); // Gregorianischer Kalender
  return 2400000.5 + 365.0 * y - 679004.0 + gregorian + (30.6001 * (m + 1)) + d + 12.0 / 24.0;
}

double InPi(double x) {
  int n = x / TWO_PI;
  x = x - n * TWO_PI;
  if (x < 0) x += TWO_PI;
  return x;
}

double calculateEOT(double &DK, double T) {
  double RAm = 18.71506921 + 2400.0513369 * T + (2.5862e-5 - 1.72e-9 * T) * T * T;
  double M  = InPi(TWO_PI * (0.993133 + 99.997361 * T));
  double L  = InPi(TWO_PI * (  0.7859453 + M / TWO_PI + (6893.0 * sin(M) + 72.0 * sin(2.0 * M) + 6191.2 * T) / 1296.0e3));
  double e = DEG_TO_RAD * (23.43929111 + (-46.8150 * T - 0.00059 * T * T + 0.001813 * T * T * T) / 3600.0);    // Neigung der Erdachse
  double RA = atan(tan(L) * cos(e));
  if (RA < 0.0) RA += PI;
  if (L > PI) RA += PI;
  RA = 24.0 * RA / TWO_PI;
  DK = asin(sin(e) * sin(L));
  RAm = 24.0 * InPi(TWO_PI * RAm / 24.0) / TWO_PI;
  double dRA = RAm - RA;
  if (dRA < -12.0) dRA += 24.0;
  if (dRA > 12.0) dRA -= 24.0;
  dRA = dRA * 1.0027379;
  return dRA ;
}

char* outputFormat(double sunTime) {
  if (sunTime < 0) sunTime += 24;
  else if (sunTime >= 24) sunTime -= 24;
  int8_t decimal = 60 * (sunTime - static_cast<int>(sunTime)) + 0.5;
  int8_t predecimal = sunTime;
  if (decimal >= 60) {
    decimal -= 60;
    predecimal++;
  }
  else if (decimal < 0) {
    decimal += 60;
    predecimal--;
    if (predecimal < 0) predecimal += 24;
  }
  static char buf[6];
  snprintf(buf, sizeof(buf), "%.2d:%.2d", predecimal, decimal);
  return buf;
}

Die Funktion connection() baut nur eine Verbindung mit dem Router auf.

Wenn du den Aufbau exakt der Vorgabe von Fips gemacht hast, sollte es funktionieren. Ich habe es bisher noch nicht getestet.
Hast du dabei berücksichtigt, dass die Berechnung nur eimalig am Tag durchgeführt wird ?

Bin der Meinung dir fehlen deine zugangs Daten für dein Router im Hauptprogramm , hast Glück das der Router deine NTP anfrage akzeptiert und im Serial Monitor dir die Zeiten anzeigt.

Nee, die stehen standardmäßig im ConnectTab, der hier nicht gezeigt wird, aber eingebunden ist.

OK die Frage ob der TO die auch bearbeitet hat.
Ich nehme mir nur den Tab was mich interessiert, die Haubt ino baue selber.

Ich rate mal: JA.
Ohne der Funktion geht nix und er ha Fehler....

Wollte gerade editieren hast Recht

Danke für deiner raschen Antwort.
Meiner Meinung nach habe ich mich an die Vorgaben gehalten.

Das dachte ich auch und verstehe das Problem daher umso weniger...
Die Sketchs habe ich gepostet.

In der Funktion void twilight() mit der Abfrage

  static byte lastday, lastdst;
  if (tm.tm_mday != lastday || tm.tm_isdst != lastdst) {                         // Sonnenlauf für Tage mit Zeitumstellung zweimal Täglich berechnen.
    lastday = tm.tm_mday;
    lastdst = tm.tm_isdst;

müsste bereits die Abfrage pro Tag begrenzt sein, oder nicht?

stimmt.

siehe [quote="HotSystems, post:4, topic:1060356, full:true"]
Nee, die stehen standardmäßig im ConnectTab, der hier nicht gezeigt wird, aber eingebunden ist.
[/quote]

Dqs ist richtig. Daher kann es sein, dass die Berechnung bzw. Anzeige nicht sofort erfolgt.
Meine Vermutung....
Wo fügst du es im loop ein ?

Die Berechnung erfolgt schon. Sehe es bei der Ausgabe auf den seriellen Monitor.
Nur der Zugriff auf die Webseite ist nur möglich, wenn ich die Funktion
twilight(12.348283, 51.345751);
in den "setup-Teil" schiebe.
Wenn ich die erwähnte Funktion in den "loop-Teil" verschiebe bekomme ich keinen Zugriff mehr auf die Webseite.
Das verstehe ich nicht.

Bei mir funktioniert
http://192.168.178.52/sun
musste nur /sun dazu schreiben
Screenshot 2022-12-01 222312

Wo im loop ?

Danke für deiner Hilfsbereitschaft.
Wo hast du aber die Funktion ? Im setup oder im loop?

twilight(12.348283, 51.345751); 

Setup

// ****************************************************************
// Sketch Esp8266 Webserver Modular(Tab)
// created: Jens Fleischer, 2018-05-16
// last mod: Jens Fleischer, 2020-12-28
// For more information visit: https://fipsok.de
// ****************************************************************
// Hardware: Esp8266
// Software: Esp8266 Arduino Core 2.4.2 - 3.0.2
// Getestet auf: Nodemcu, Wemos D1 Mini Pro, Sonoff Switch, Sonoff Dual
/******************************************************************
  Copyright (c) 2018 Jens Fleischer. All rights reserved.

  This file is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This file is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
*******************************************************************/
// Der WebServer Tab ist der Haupt Tab mit "setup" und "loop".
// #include <LittleFS.h> bzw. #include <FS.h> und #include <ESP8266WebServer.h> 
// müssen im Haupttab aufgerufen werden.
// Ein Connect Tab ist erforderlich.
// Inklusive Arduino OTA-Updates (Erfordert freien Flash-Speicher)
/**************************************************************************************/

#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>         // https://arduino-esp8266.readthedocs.io/en/latest/ota_updates/readme.html
#include <LittleFS.h>           // Library für Dateisystem LittleFS
//#include <FS.h>               // Library für Dateisystem Spiffs einkommentieren wenn erforderlich

#include <time.h>

struct tm tm;   //Kalenderzeit

ESP8266WebServer server(80);

String sketchName() {           // Dateiname für den Admin Tab ab EspCoreVersion 2.6.0
  char file[sizeof(__FILE__)] = __FILE__;
  char * pos = strrchr(file, '.'); *pos = '\0';
  return file;
}

void setup() {
  Serial.begin(115200);
  delay(100);
  Serial.printf("\nSketchname: %s\nBuild: %s\t\tIDE: %d.%d.%d\n%s\n\n",
                (__FILE__), (__TIMESTAMP__), ARDUINO / 10000, ARDUINO % 10000 / 100, ARDUINO % 100 / 10 ? ARDUINO % 100 : ARDUINO % 10, ESP.getFullVersion().c_str());
  
                    // setupFS(); oder spiffs(); je nach Dateisystem
  Connect();
                // Die Tabs die du nutzen möchtest, musst du Einkommentieren
  setupTime();
   //Aufruf Berechnung Sonnenaufgang/Sonnernuntergang
  twilight(12.348283, 51.345751);  // geographische Länge und Breite

  ArduinoOTA.onStart([]() {
    //save();                   // Wenn Werte vor dem Neustart gespeichert werden sollen
  });
  ArduinoOTA.begin();
  server.begin();
}


void loop() {
  ArduinoOTA.handle();
  server.handleClient();
  if (millis() < 0x2FFF || millis() > 0xFFFFF0FF) {    // Die Funktion "runtime()" wird nur für den Admin Tab gebraucht.
   // runtime();                                         // Auskommentieren falls du den Admin Tab nicht nutzen möchtest.
  }
 }

danke für deiner Hilfsbereitschaft.

void loop() {
  ArduinoOTA.handle();
  server.handleClient();
  if (millis() < 0x2FFF || millis() > 0xFFFFF0FF) {    // Die Funktion "runtime()" wird nur für den Admin Tab gebraucht.
   // runtime();                                         // Auskommentieren falls du den Admin Tab nicht nutzen möchtest.
  }
   //Aufruf Berechnung Sonnenaufgang/Sonnernuntergang
  twilight(12.348283, 51.345751);  // geographische Länge und Breite
 }

Das sollte so richtig sein.

da funktioniert es auch bei mir.
Nur wenn ich die Funktion in den loop verschiebe, habe ich die Probleme mit dem Zugriff auf der Webseite.
Wie ich verstanden habe muss die Funktion in den loop Teil kommen, damit jeder Zeit überprüft werden kann, ob ein neuer Tag eingetroffen ist und eine neue Berechnung zu machen ist.

So funktioniert es beim TO auch.
Das hilft dann leider nicht weiter.