Variable in HTML Code auf SD Karte einsetzten

Guten Tag
Ich habe ein Programm geschrieben das eine HTML Seite, die Auf einer SD Karte gespeichert ist, ausgeben kann.

Nun habe ich aber noch 2 Probleme:

  1. Ich möchte eine Variable, z.B ein Messwert, in das HTML File schreiben und die Seite danach wider ausgeben. Kann mir da jemand helfen der dies vielleicht schon gemacht hat?

  2. Ich habe es zwar geschafft das auch ein Bild übergeben werden kann, es lädt aber auf der Webseite extrem langsam. An was könnte das liegen?

Hier der Arduino Code:

/*--------------------------------------------------------------
  Program:      Webseite_Umgebungstemperatur

 
    
--------------------------------------------------------------*/

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

// size of buffer used to capture HTTP requests
#define REQ_BUF_SZ   20

// MAC address from Ethernet shield sticker under board
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,14); // IP address, may need to change depending on network
EthernetServer server(80);  // create a server at port 80
File webFile;
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0;              // index into HTTP_req buffer

void setup()
{
    // disable Ethernet chip
    pinMode(10, OUTPUT);
    digitalWrite(10, HIGH);
    
    Serial.begin(9600);       // for debugging
    
    // initialize SD card
    Serial.println("Initializing SD card...");
    if (!SD.begin(4)) {
        Serial.println("ERROR - SD card initialization failed!");
        return;    // init failed
    }
    Serial.println("SUCCESS - SD card initialized.");
    // check for index.htm file
    if (!SD.exists("webpage.htm")) {
        Serial.println("ERROR - Can't find index.htm file!");
        return;  // can't find index file
    }
    Serial.println("SUCCESS - Found index.htm file.");
    
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                // buffer first part of HTTP request in HTTP_req array (string)
                // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
                if (req_index < (REQ_BUF_SZ - 1)) {
                    HTTP_req[req_index] = c;          // save HTTP request character
                    req_index++;
                }
                // print HTTP request character to serial monitor
                Serial.print(c);
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // open requested web page file
                    if (StrContains(HTTP_req, "GET / ")
                                 || StrContains(HTTP_req, "GET /webpage.htm")) {
                        client.println("HTTP/1.1 200 OK");
                        client.println("Content-Type: text/html");
                        client.println("Connnection: close");
                        client.println();
                        webFile = SD.open("webpage.htm");        // open web page file
                    }
                    else if (StrContains(HTTP_req, "GET /logo.png")) {
                        webFile = SD.open("logo.png");
                        if (webFile) {
                            client.println("HTTP/1.1 200 OK");
                            client.println();
                        }
                    }
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    // reset buffer index and all buffer elements to 0
                    req_index = 0;
                    StrClear(HTTP_req, REQ_BUF_SZ);
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(0.001);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
    for (int i = 0; i < length; i++) {
        str[i] = 0;
    }
}

// searches for the string sfind in the string str
// returns 1 if string found
// returns 0 if string not found
char StrContains(char *str, char *sfind)
{
    char found = 0;
    char index = 0;
    char len;

    len = strlen(str);
    
    if (strlen(sfind) > len) {
        return 0;
    }
    while (index < len) {
        if (str[index] == sfind[found]) {
            found++;
            if (strlen(sfind) == found) {
                return 1;
            }
        }
        else {
            found = 0;
        }
        index++;
    }

    return 0;
}

Hier der HTML Code:
Die Variable die man in das HTML File schreibt sollte dort stehen wo jetzt Messwert steht.

<!-- Der neue HTML Doctype ist der einfachste Doctype den es je gab.-->
<!DOCTYPE html>
<html lang="de">
<head>
    <!-- Auch das meta-Tag zum Zeichensatz wurde vereinfacht.-->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!--<link href="design.css" rel="stylesheet">-->


    <style>
* {
            color: #999999;
            font-size: 20px;
            font-weight: 400;
            box-sizing: border-box;
            font-family: 'Monteserat', Arial, sans-serif;
            padding: 0;
            margin: 0;
            
        }
 
        html{

            height: 100%;
        }
        

        body{
            height: 100%;
            background-repeat: no-repeat;
            background-size: cover;
            background-attachment: fixed;
            z-index: -2;
        }


        section,
        aside,
        footer {
            text-align: center;
            border-radius: 7px;
            padding: 25px;
            box-shadow: 0 6px 15px rgba(0,0,0,.08);
            color: rgb(0, 0, 0);
            font-weight: 600;
        }
        
        header {
            width: 25%;
            margin: 25px 25px 25px 25px;
            display: inline-block;
        }
 
        nav {
            text-align: left;
            border-radius: 7px;
            padding: 40px;
            font-size: 50px;
            font-weight: 600;
            color: rgb(0, 0, 0);

            width: calc(75% - 75px);
            margin: 25px 25px 25px 0px;
            float: right;
            box-shadow: 0 5px 10px rgba(0,0,0,.08);
            z-index: 1;
        }
 
        aside {
            width: 25%;
            float: left;
            min-height: 517px;
        }
 
        section {
            float: left;
            width: calc(75% - 75px);
            margin: 0 25px 25px 25px;
            font-size: 25px;
        }
 
        section header,
        section article,
        section footer {
            width: 100%;
            border-radius: 7px;
            border: 2px solid #e5e5e5;
            box-shadow: none;
            margin: 25px 0px 0px 0px;
            padding: 50px;
            color: rgb(0, 0, 0);
            font-weight: 600;
        }
 
        footer {
            width: 96.5%;
            margin: 25px 25px 0px 25px;
            clear: both;
        }

    </style>
</head>
<body>
<main>
  <header>
    <img src="logo.png" widht="160" height="90">
  </header>
 
  <nav>
    Umgebungsdaten
  </nav>
 
  <section>
    Daten <!-- Ein Abschnitt der Website -->
    <header>Temperatur: Messwert</header> <!-- Du Überschrift des Website-Abschnitts -->
    <article>Luftfeuchtigkeit: Messwert</article> <!-- Der Inhalt des Website-Abschnitts -->
    <footer>sonstiges</footer> <!-- Der Schlussteil des Website-Abschnitts -->
  </section>
 
  <aside>
    Wochenansicht: <!-- Eine Seitenleiste -->
  </aside>
 
  <footer>
    sonstiges
  </footer>
</main>   
</body>
</html>

Danke für eure Zeit.

Ich würde die Website erst mal ohne den Messwert ausliefern und dann den Browser diesen per Javascript und Fetch-API nachladen lassen.
Das ist bei Fips zwar für andere Prozessoren gezeigt, das Grundprinzip bleibt aber erhalten.

Eine andere Variante wäre, die Variable im HTML durch Sonderzeichen zu markieren (z.B. $ -> $ darf dann nicht normal vorkommen).
Alles zeichenweise aus der Datei lesen und zum Browser schicken, bis $ kommt, den nicht mit schicken, aber lesen und dort den Wert einfügen. Dann den Rest der Datei schicken. Man könnte über zeilenweises Lesen evtl. eine Optimierung vornehmen. Der $ könnte dann am Ende einer Zeile stehen.

Welcher Prozessor und welches Netzwerkmodul? Ein Microprozessor ist halt kein ausgewachsener Server.

Gruß Tommy

also ich würde auch eine statische Seite ausliefern und diese mittels JavaScript/Fetch aktualisieren.

Für eine Seite im Programmspeicher hab ich das mal beschrieben:
https://werner.rothschopf.net/microcontroller/202011_arduino_webserver_fetch_api_en.htm

das könnte man theoretisch auch anpassen und die statischen Daten von der SD Karte lesen.

Wenn ich mir aber deine "HTML" Seite ansehe ... also das bisserl CSS und noch weniger HTML würde ich im Programmspeicher halten und mir dafür den Overhead der SD Karte sparen. Wenn das jpg natürlich riesengroß ist, dann wird es wohl doch die SD Karte brauchen.

beobachte mal genau: ist nur das Bild langsam oder deine HTML Seite auch? Schau dir mal zB. im Firefox "Werkzeuge für den Webdesigner" die Netzwerkanalyse an. Da siehst du genau wie viele Bytes übertragen werden und wie lange das dauert. kannst ja mal einen Screenshot posten damit wir das sehen.

Ohne es selbst ausprobiert zu haben: du behauptest

HTTP/1.1 

zu senden, machst aber nicht weil du keine Content-Length schickst. nimm HTTP/1.0 stattdessen.
Auch hast du beim Bild keinen content type angegeben.
Das dein HTML nicht valide ist - ist wahrscheinlich auch nicht günstig.

Liest das Zeichen für Zeichen? Versuch mal einen Buffer dazwischen zu schalten.


Wie man bei dem Bild sehen kann ist es wirklich nur das Logo das so lange, 35s, braucht.

genau ich verwende den Arduino uno und der verwendbare Speicherplatz beträgt nur 32kB was bei weitem nicht ausreicht. Deswegen komme ich nicht um eine SD Karte herum.

  • deine Seite mit 3.4k ist auch schnarch langsam. Das sollte wesentlich schneller gehen.
  • ein png Logo mit 118KB? Du bist auf einem kleinen 8bitter AVR, willst dem nicht was kleineres geben?
  • 373ms für ein nicht vorhandenes favicon wäre mir auch zu langsam.

Das ist basirend auf meinen Beispielen, einige Wifi Komponenten zw. Arduino und Laptop:

wenn ich meine Webseite lokal auf meinem Rechner öffne ist es auch viel schneller.


Ich denke es liegt an meinem Arduino Code weswegen meine Seite so langsam ist. Hast du vielleicht eine Idee wie ich dies in Arduino anpassen könnte.

Und vielen Dank für deine schnellen Antworten!

ich hab kein "HTML auf SD Karte" Beispiel. Ich glaube aber trotzdem dass sich folgende Artikel für dich gut eignen:

Ein Webserver am UNO:
https://werner.rothschopf.net/202001_arduino_webserver_post.htm

Was man bezüglich Optimierungen beachten soll:

Bezüglich SD Karte habe ich u.a. das Beispiel "loggen von Daten auf eine SD Karte" und man kann dann das Logfile über http abholen. Das hat aus meiner Sicht auch mit "großen" Files funktioniert:

https://werner.rothschopf.net/microcontroller/202108_arduino_webserver_ntp_sd_en.htm
vermutlich kannst du dir das Passthrough auch für andere Fileformate ansehen.

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