ESP826-Webserver: Response sehr träge

Hallo zusammen,

Bin aktuell dabei mir eine MQTT-Steckdose zu bauen. Das Projekt ist eher als Lernprojekt zu verstehen, da es u.A. Shellies ja bereits als preiswerte Fertiglösung gibt. Am Ende soll es aber mit den gleichen Basisfunktionen daherkommen wie eben so ein Shelly 1, nur mit 2-4 Relays.
MQTT-Schnittstelle läuft prima und eigentlich ist er sogar schon seit 6 Monaten im Einsatz.

Nun wollte ich eine Config-Schnittstelle bauen über für HTTP-Requests mit der ESP8266WebServer-Bibliothek. Das Ergebnis sind JSON-Response Nachrichten (ebenfalls ähnlich Shelly):

void ServerConnection()
{
  Serial.print("Start web-server ... ");

  // Control Website
  server.on("/", []() {
    server.send(200, "text/html", "Testsite");
    Serial.println("Opend homepage");
  });
  server.on("/settings", []() {
    RequestTimeStamp = 1;
    Serial.print("Request Settings -> [Start]: ");
    Serial.print(millis());
    if(server.args() > 0)
    {
      if (server.arg("mqtt_enable") != "") // ToDo
      { 
        if(server.arg("mqtt_enable").equals("true"))
          MQTTconfig.enable = true;
        else
        {
          MQTTconfig.enable = false;
          MQTT.disconnect();
        }
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
      if (server.arg("mqtt_server") != "") // ok
      {   
        if(server.arg("mqtt_server").indexOf(":") > 0 &&server.arg("mqtt_server").lastIndexOf(":") == server.arg("mqtt_server").indexOf(":"))
        {
          String tempMQTTserver = server.arg("mqtt_server").substring(0, server.arg("mqtt_server").indexOf(":"));
          String tempMQTTport = server.arg("mqtt_server").substring(server.arg("mqtt_server").indexOf(":")+1,server.arg("mqtt_server").length());
          
          MQTTconfig.server = tempMQTTserver;
          MQTTconfig.port = tempMQTTport.toInt();
          MQTT.disconnect();
          saveMQTTconfig(MQTTconfigFile, MQTTconfig);
        }
      }
      if (server.arg("mqtt_user") != "") //ok
      {   
        MQTTconfig.user = server.arg("mqtt_user");
        MQTT.disconnect();
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
      if (server.arg("mqtt_id") != "") //ok
      {   
        MQTTconfig.clientID = server.arg("mqtt_id");
        MQTT.disconnect();
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
      if (server.arg("mqtt_clean_session") != "") //ok
      {
        if(server.arg("mqtt_clean_session").equals("true"))   
          MQTTconfig.cleansession = true;
        else
          MQTTconfig.cleansession = false;
        MQTT.disconnect();
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
      if (server.arg("mqtt_keep_alive") != "") //ok
      {   
        if(server.arg("mqtt_keep_alive").toInt() >= 0)
          MQTTconfig.keepalive = server.arg("mqtt_keep_alive").toInt();
        else
          MQTTconfig.keepalive = 0;
        MQTT.disconnect();
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
      if (server.arg("mqtt_max_qos") != "")
      {   
        if(server.arg("mqtt_max_qos").toInt() <= 2 && server.arg("mqtt_max_qos").toInt() >= 0)
          MQTTconfig.maxqos = server.arg("mqtt_max_qos").toInt();
        else
          MQTTconfig.maxqos = 0;
        MQTT.disconnect();
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
      if (server.arg("mqtt_update_period")!= "")
      {   
        if(server.arg("mqtt_update_period").toInt() >= 0)
          MQTTconfig.updateperiod = server.arg("mqtt_update_period").toInt()*1000;
        else
          MQTTconfig.updateperiod = 0;
        MQTTcycleTimer.SetCountdown(MQTTconfig.updateperiod);
        saveMQTTconfig(MQTTconfigFile, MQTTconfig);
      }
    }
    
    String ResponseStr;
    String MqttStr;
    MqttStr = openJSON(MqttStr);
    MqttStr = addJSONbool(MqttStr,"enable",MQTTconfig.enable); // ToDo
    MqttStr = addJSONstr(MqttStr,"server",MQTTconfig.server + ":" + MQTTconfig.port); // ToDo
    MqttStr = addJSONstr(MqttStr,"user",MQTTconfig.user); // ToDo
    MqttStr = addJSONstr(MqttStr,"id",MQTTconfig.clientID);
    MqttStr = addJSONbool(MqttStr,"clean_session",MQTTconfig.cleansession); // ToDo
    MqttStr = addJSONint(MqttStr,"keep_alive",MQTTconfig.keepalive); // ToDo
    MqttStr = addJSONint(MqttStr,"max_qos",MQTTconfig.maxqos); // ToDo
    MqttStr = addJSONbool(MqttStr,"retain",MQTTconfig.retain); // ToDo
    MqttStr = addJSONint(MqttStr,"update_period",MQTTconfig.updateperiod/1000); // ToDo
    MqttStr = closeJSON(MqttStr);

    ResponseStr = openJSON(ResponseStr);
    ResponseStr = addJSONjson(ResponseStr,"mqtt",MqttStr);
    ResponseStr = closeJSON(ResponseStr);
    server.send(200, "text/json", ResponseStr.c_str());
    Serial.print(" [End] ");
    Serial.println(millis());
  });
  server.on("/ota", []() {
    String ResponseStr;
    ResponseStr = openJSON(ResponseStr);
    ResponseStr = addJSONstr(ResponseStr,"status","idle");
    ResponseStr = addJSONstr(ResponseStr,"old_version",SWversion);
    ResponseStr = closeJSON(ResponseStr);

    server.send(200, "text/json", ResponseStr.c_str());
  });
  
  server.onNotFound([]() {
    String message = "File Not Found\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET) ? "GET" : "POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";
    for (uint8_t i = 0; i < server.args(); i++) {
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }
    server.send(404, "text/plain", message);
    Serial.println(message.c_str());
  });
  server.begin();
  Serial.println("ok");
}


// Create JSON String
String openJSON(String JSONstr)
{
  JSONstr = "{";
  return JSONstr;
}
String closeJSON(String JSONstr)
{
  if(JSONstr.endsWith(","))
    JSONstr = JSONstr.substring(0, JSONstr.lastIndexOf(","));
  JSONstr += "}";
  return JSONstr;
}

String addJSONbool(String JSONstr, String Name, bool Value)
{
  JSONstr += "\"" + Name + "\"" + ":\"";
  if(JSONstr)
    JSONstr += "true";
  else
    JSONstr += "false";
  JSONstr += "\",";
  return JSONstr;
}

String addJSONint(String JSONstr, String Name, int Value)
{
  JSONstr += "\"" + Name + "\"" + ":\"" + Value + "\",";
  return JSONstr;
}

String addJSONstr(String JSONstr, String Name, String Value)
{
  JSONstr += "\"" + Name + "\"" + ":\"" + Value + "\",";
  return JSONstr;
}

String addJSONjson(String JSONstr, String Name, String Value)
{
  JSONstr += "\"" + Name + "\"" + ":" + Value + ",";
  return JSONstr;
}

Ausgeführt wird er dann mit folgenden Befehlen in der Loop:

void setup() 
{
  // Set Wifi
  startWifiConnection();
  delay(250);

  // Set Server
  startServerConnection();
  delay(250);
  
  // Set MQTT 
  startMQTTconnection();
  delay(250);
}

void loop() 
{ 
  iif(RequestTimeStamp == 0)
  {
    time1 = millis();
  }
  handleWifiConnection();
  server.handleClient();
  handleMQTTconnection();
  
  if(RequestTimeStamp == 1)
  {
    RequestTimeStamp = 0;
    Serial.print("Handle TimeStamp -> [Start]: ");
    Serial.print(time1);
    Serial.print(" [End]: ");
    Serial.println(millis());
  }
}

Wenn ich nun die seite >http://"host-ip"/settings> öffne, kommt eine JSON-String, den ich auswerten kann. Über GET-Befehle kann ich auch die Werte ändern.
Dummerweise dauert das Aufrufen der Seite oft Sekunden.
Der Code selbst wird aber schnell abgearbeitet. Hab mir mal mit Serial-Print zwei Zeiten gmessen:
-> Zeit innerhalb der Settings-Request-Funktion und der gesamte Loop-Zeitraum.
Der Log sagt, die Schleife dauert insgesamt nur 8ms, d.h. der Code ist nicht träge:

Request Settings -> [Start]: 16410 [End] 16413
Handle TimeStamp -> [Start]: 16406 [End]: 16414

Der Log wird auch unmittelbar nach dem Request angezeigt, erst dann vergehen Gedenksekunden.
Wo beginne ich mit der Fehlersuche? Normal ist es denke ich nicht oder?

mach mal einen Gegencheck mit dem Beispiel aus der IDE und berichte.
Das ist die Geschwindigkeit die du auch mit deinem Code erreichen musst.

Wenn das schneller ist hast du vermutlich ein Problem in Codeteilen die du nicht zeigst.

Mehr kann man dir mit den aktuellen Daten nicht sagen.

Es könnte auch sein, dass Dein Browser bei diesem Durcheinander auf das Ende des HTML wartet, was dann nicht kommt.

server.send(200, "text/html", "Testsite");

Du kündigst text/html an und sendest text/plain.

Gruß Tommy

Danke erstmal für die Rückmeldungen.

noiasca:
mach mal einen Gegencheck mit dem Beispiel aus der IDE und berichte.
Das ist die Geschwindigkeit die du auch mit deinem Code erreichen musst.

Wenn das schneller ist hast du vermutlich ein Problem in Codeteilen die du nicht zeigst.

Mehr kann man dir mit den aktuellen Daten nicht sagen.

Bei dem Standard-Webserver Code aus den "Hello World" Beispielen ebenso das gleiche Problem (bei zwei ESP getestet). Hab zudem nun alle anderen Funktionen ausgeblendet und ausschließlich den Handle vom Webserver in der Loop.
Insgesamt braucht der Aufbau der Seite pro Abruf ca. 2 Sekunden, egal welchen Code ich verwende. Beim Shelly als Gegenbeispiel sind es 0.02s bis der Response kommt (habs nochmal per PHP timestamp überprüft).

Tommy56:
Es könnte auch sein, dass Dein Browser bei diesem Durcheinander auf das Ende des HTML wartet, was dann nicht kommt.

server.send(200, "text/html", "Testsite");

Du kündigst text/html an und sendest text/plain.

Gruß Tommy

Hab den Code-Schnipsel nun nachgebessert. Der Aufruf wird aber nie verwendet, ist nur noch aus ersten Versuchen drin geblieben. Eigentlich sende ich nur JSON-Formate.

Da der Original-Code aber ebenso langsam ist, stellt sich die Frage ob der ESP8266 hier einfach nicht mehr kann, oder ob ich noch wo anders nachbessern muss. Da in Shellies der gleiche Chip verbaut ist, kanns daran fast nicht liegen.
Übrigens es ist in meinem Aufbau ein NodeMCU V2, falls das noch irgendeine Relevanz hat.

In Deinem setup rufst Du startServerConnection(), die Funktion gibt es nicht.

Es gibt höchstens

miar90:

void ServerConnection()

{
  Serial.print("Start web-server ... ");

Gruß Tommy

zeig mal den HelloServer.ino (!) Sketch im Firefox / Chrome mit den web-Analyzetools (ich glaube bei Firefox ist es "Network") damit wir echte Antwortzeiten bei dir sehen.

Dann im Vergleich dein Sketch wie langsam das ist.

"Langsam" soll das alles nicht sein. ich sag mal 0,05 - 0,2 sec ab Request bis fertiger Response.

wegen WIFI vermutlich langsamer als LAN am UNO:

Tommy56:
In Deinem setup rufst Du startServerConnection(), die Funktion gibt es nicht.

Es gibt höchstens
Gruß Tommy

Sorry, das war ein Kopierfehler. Das "start" hab ich kurz vor dem Erstellen des Treads entfernt. Ist mir beim Kompilieren aufgefallen, dass es nicht konsequent geändert war. Ist nun korrigiert, entspricht also der angegebenen Funktion.
Folgendes fällt mir auf (unabhängig ob mein Skript oder Beispiel-Skript)

  • Firefox: Die Abfrage dauert nach längerer Wartezeit bis zu 2s. Bei kürzen Abständen in der Regel 0,15s-0,2s (mit Netzwerkanalyse-Tool). Ein Refresh mit STRG+F5 zeigt sich auch mit 0,15s-0,2s. Ist wohl hier anders als beim Edge-Browser.
  • Edge: Beim Erstaufruf der Seite dauert es knapp 2s. Beim normalen Refresh dann ca. 0,2s und bei Refresh mit STRG-F5 wiederum immer ca. 2s. Die lange Ladezeit lässt sich im Gegensatz zum Firefox immer reproduzieren.
  • PHP: Mit der Funktion "$_response = implode('', file($_url));", wobei $_url http://"IP"/settings entspricht, dauert die Abfrage ebenso immer 2s (gemessen mit "microtime(true)" timestamp for und nach dem Abruf). Zwei nacheinander folgende Request dauern aber immer 2s, hier gibts keine Verringerung.
    Dabei ist es egal, ob ich einen text/plain sende oder text/json. Reaktionszeiten sind ähnlich lang.

Ich hab nur Basis-Wissen über HTML, aber es scheint, als können die Browser die Zugriffszeit selbst optimieren, sobald diese den ersten Zugriff gemacht haben.
Und nun mein Vergleich zu den Shellies: Bei allen drei Methoden haben diese Durchweg einen Response <0,2s.

Gibts am ESP8266webserver Besonderheiten die man zur Optimierung noch einstellen muss?

eigentlich nicht,

Zeig mal den HelloServer Sketch im Firefox. Normalerweise erkennt man, ob die Seiten aus dem Cache kommen oder frisch abgeholt wurden.

Ich hab mal beides gemacht. Erstes Bild = Edge mit STRG+F5 bzw. bei längerer Pause. Zweites Bild = Firefox (hier schaff ich aktuell nur gute Zeiten). Ich sehe zwar wenige Fehler beim Edge, die aber auch bei guten Zeiten auftreten. Ist das hilfreich für Interpretation?

Hier noch ein Edge-Test. Mehrmals ohne Probleme geladen mit geringer Auslastung und kurzen Ladezeiten. (rot). Dann die Seite gewechselt und etwas anderes gemacht und danach wieder zurück auf Seite -> Die CPU-Auslastung geht bei den Langen Ladezeiten kurz auf 100% (gelb).

zweites Bild = Firefox (hier schaff ich aktuell nur gute Zeiten).

das heißt, der Beispiel Sketch läuft im Firefox performant oder? Zumindest sieht es am Bild so aus.

noiasca:
das heißt, der Beispiel Sketch läuft im Firefox performant oder? Zumindest sieht es am Bild so aus.

Ja das stimmt. Ich denke am Code selbst liegt es demnach nicht, außer ich muss noch irgendwelche Header oder ähnliches mitschicken, damit alle Browser und inkl. PHP Abfrage entsprechend schnell sind und in den Einführungsbeispielen nicht aufgeführt werden.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.