Javascript und HTML in C von ESP32

OP #8017364
Lesenswert?

Wenn ihr sowas wie JS, CSS oder HTML in euren Embedd-Projekten mit integriertem Webserver verwendet, baut ihr das dann als static const char JS[] Array ein? Welche Methoden nutzt ihr dafür?

Ich mache das aktuell noch als ein Array, aber teilweise sind das 200-300 Zeilen und man muss höllisch aufpassen keinen Escape- oder Comment-Fehler zu machen. Ganz davon ab ist der Code nicht mehr lesbar...

: Bearbeitet durch User
#8017381
Lesenswert?

Entweder Du baust die automatische Datei-Konvertierung in Deinen Build-Prozess ein oder aber, da Du ja einen ESP32 nutzt, Du legst die Dateien auf einer eigenen Partition in einem Dateisystem im Flash ab und liest die Dateien dann per Storage API ein. Das Kopieren der Dateien in die Partition geschieht automatisch beim Build im esp-idf.

#8017396
Lesenswert?

Definitiv Files, keine C-Strings. Ansonsten bist du nur noch am kopieren. Und unübersichtlich ist es auch. Wenn du noch Platz und Ladezeit sparen willst lässt du dir die großen Files noch in einem Prebuild step in einen neuen Ordner zippen.

Dann installierst du dir noch sowas wie den Live Server in VSC und kannst auch gleich noch vernünftig die Website anschauen und debuggen.

#8023203
Lesenswert?

ich verwende einen Raw-String:

1
const String htmlHeader = R"---(<!DOCTYPE HTML>
2
<head>
3
<meta charset="utf-8">
4
<meta name="viewport" content="width=device-width, initial-scale=1">
5
</head>
6
)---";

Die Strings lassen sich mit += leicht konkatenieren und JavaScript code kann man einfach so runterschreiben.

#8023208
Lesenswert?

Claus P. schrieb:

ich verwende einen Raw-String: Die Strings lassen sich mit += leicht konkatenieren

Das klappt halt nur bei kleinen Webseiten gut, weswegen es viele ESP-Beispiele nach dem Schema gibt.

Aber sobald die Seite komplizierter wird, kann das zu schwer zu debuggenden Fehlern führen, weil der Speicher ausgeht oder zu stark fragmentiert.

Dein HTML-Code liegt einmal im Flash, wird dann beim String-anlegen in den RAM kopiert, und jedes "+=" legt potentiell nochmal eine Kopie vom gesamten String im RAM an.

Und die Antwort wird erst gesendet, wenn der ganze HTML-String fertig ist.

Bei der Lösung als Dateien im LittleFS mit dem AsyncWebserver entfallen diese Probleme. Große Dateien werden Blockweise gestreamt, es ist immer nur der gerade versendete Chunk im RAM, der HTTP-Antwort-Header und die Ersten Daten wandern schon zum Webbrowser, bevor die ganze Datei überhaupt gelesen ist.

Über die Template-Engine kannst du auch da dynamisch Werte/Texte einsetzen.

=> Für kleine Demo-Projekte kann man das mit den Strings machen, wenn absehbar ist dass es evtl. etwas umfangreicher wird, würde ich gleich auf eine skalierbare Lösung setzen, und mir das Umbauen später sparen.

(Firma: Funkenflug Industries) #8025904
Lesenswert?

Also bei mir schwankt das. Die meisten Webseiten bastle ich mir sowieso außerhalb des ESP, dann muss ich sie nur einmal in den Quellcode kopieren und kann sie anschließend "vergessen". Geschmackssache, ich habe am Ende gerne alles in einer einzigen Datei.

#8027369
Lesenswert?

Pandur S. schrieb:

Weshalb sollte man sich Strings vom flash ins Ram kopieren

Copy&Paste-Geschichte. Es gibt Berge an Arduino-Beispielen nach dem Schema

1
String response="<html>";
2
response += "<head>";
3
...

Viele Leute übernehmen das ohne Nachzudenken, und schon existiert ein weiteres Beispiel nach dem Schema.

Jetzt kommt noch die KI dazu, die mit all diesem Code trainiert wurde, und logischerweise wird die dann auch sowas ausspucken...

Aus dem Teufelskreis werden wir nicht mehr herauskommen, fürchte ich.

Aber egal, die nächste µC-Generation hat wieder mehr RAM und Rechenleistung, das ist sicher alles fein.

#8027504
Lesenswert?

String ist nicht für statische Daten gedacht und legt bestimmt auch ein Objekt im Speicher an. Da ist dann echt das olle Array of Char passender.

Wenn man das im make Prozess mit generieren kann, gibt es auch keine Probleme mit Zeichen, die vergessen wurden beim Escapes einfügen. Gibt es xxd auch für Windows (oder noch DOS) ? Ich habe unter Windows dafür HxD benutzt. Allerdings leider nicht aus dem Makefile, sondern im Handbetrieb.

Könnte man statische Dateien nicht auch auf einen potenteren Server, der im Internet hängt auslagern und von da einbinden ? Oder blockt da der Browser aus Sicherheitsbedenken ?

Den Kram gepackt im Speicher abzulegen bringt doch erst was, wenn die Platzersparnis den Platzbedarf der Entpackroutine übersteigt. Und zeitlich dürfte das Entpacken so gut wie immer verlieren.

Was hier wunderbar funktioniert hat, ist die .html Dateien in dem Sinne zu packen, dass man alle Zeichen rauswirft, die nichts an der Darstellung im Browser ändern. Also auf Gliederungen durch Einrückungen und Zeilenumbrüche im Quelltext verzichtet und dem Browser gleich sagt, hier kommt UTF8, das kannst Du Punkt und dafür keine Umschreibungen wie

1
&auml;

mehr braucht. Auch dafür gibt es Software, die Dateien entsprechend tuned.

Ehrlich gesagt, habe ich mir dieses Filesystem im ESP32 noch nicht angeschaut. Im Endeffekt, legt das doch bestimmt auch die Datem mit ein paar Verwaltungsdaten im Flash ab, oder ? Den Vorteil sehe ich dann, wenn ich öfter mal meine Software updaten muss, aber die riesigen Daten gleich bleiben, dann geht das flashen schneller. Die liegen doch bestimmt auch im Flash, oder ? Bzw. kann ich den Bereich für das Filesystem auf nahezu null schrauben, um den Platz dann für Daten, die sich in meinem Programmcode verstecken, frei zu machen ?

Der ESP32 hat doch keine Harvard Architektur, bei dem die Daten mühsam vom Programmspeicher in den Datenspeicher geschafft werden müssten.

#8027514
Lesenswert?

Flunder schrieb:

Könnte man statische Dateien nicht auch auf einen potenteren Server, der im Internet hängt auslagern und von da einbinden ?

Könnte man machen. Dann verliert man aber meiner Meinung nach genau den Vorteil eines solchen Systems. Alles Lokal und unabhängig von anderen Systemen zu haben. Du willst das Webinterface deiner Heizung ja evtl noch aufrufen wenn das Internet gerade nicht geht oder der externe Server gerade nicht erreichbar ist.

Flunder schrieb:

Oder blockt da der Browser aus Sicherheitsbedenken ?

Lies mal zu CORS (Cross-Origin Resource Sharing) nach. Geht schon.

Flunder schrieb:

Den Kram gepackt im Speicher abzulegen bringt doch erst was, wenn die Platzersparnis den Platzbedarf der Entpackroutine übersteigt. Und zeitlich dürfte das Entpacken so gut wie immer verlieren.

Entpackt wird ja nicht auf deinem uC. Sondern im Browser. Du sparst so auf 2 weisen. Der Controller braucht nicht so viel Speicher und du kannst es deutlich schneller übertragen. Geht wirklich verdammt schnell das entpacken. So hab ich schon mehr als 4MB Daten und viele JS Libraries in einem 2MB Controller abgelegt. Und da war noch das eigentliche Programm (Webserver,Applikation,...) dabei.

Flunder schrieb:

Was hier wunderbar funktioniert hat, ist die .html Dateien in dem Sinne zu packen, dass man alle Zeichen rauswirft,

Ist verschwendete Liebesmühe. Wenn du die Datei komprimierst macht das so gut wie keinen Unterschied. Der HTML/JS Code schrumpft ziemlich extrem zusammen durch die Komprimierung.

Flunder schrieb:

Ehrlich gesagt, habe ich mir dieses Filesystem im ESP32 noch nicht angeschaut. Im Endeffekt, legt das doch bestimmt auch die Datem mit ein paar Verwaltungsdaten im Flash ab, oder ?

Ja klar. Ist ja nach System einfach ein FAT. Halt nicht auf SD Card sondern im Flash.

Flunder schrieb:

Den Vorteil sehe ich dann, wenn ich öfter mal meine Software updaten muss,

Du kannst dadurch aussehen und Funktion komplett trennen. Ein Update des Webinterface bedingt dann kein neues Kompilieren. Du kannst einfach die neuen Dateien hochladen. Funktionserweiterungen die in Webinterface genauso. Nur Änderungen im CPP Programm musst du dann anders updaten. Wobei das auch über OTA möglich ist.

Außerdem macht es das Handling während der Entwicklung deutlich komfortabler.

Die ganzen Webfiles liegen einfach als normale Dateien im Projekt ohne etwas konvertieren oder Kompilieren zu müssen. Wenn man dann noch irgendein Webserver Plugin für seine IDE verwendet (z.B. Liveserver o.ä) kann man den ganzen Webcode sehr komfortabel entwickeln. Und wenn man fertig ist läd man nur die neuen Dateien hoch.

#8027518
Lesenswert?

Das Problem an den ganzen Dateisystem Lösungen des ESP-IDF is, dass die alle globale Critical Sections haben. Sprich die würgen einfach mal so sämtliche User-Level Interrupts ab. Damit eignen sie sich nur für sehr zeitunkritische Anwendungen.

Für die objcopy Variante bietet Espressif eine CMake Funktion namens "target_add_binary_data", siehe: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/storage/index.html

Das is zwar performanter, bringt aber eine ganz andere Reihe an Problemen mit sich...

Ich selbst hab eine Web-Anwendung die ich via CMake auf einen ESP32S3 packe und dafür sind folgende Schritte notwendig:

  • Clonen des Releases
  • Ordner Struktur abflachen
  • gzippen aller Datein (optional)
  • Code Generierung eines constexpr LUT der die Datein in ihre ursprünglichen Pfade mapped

Das is schon alles ziemlich PITA...

#8027520
Lesenswert?

Flunder schrieb:

Ehrlich gesagt, habe ich mir dieses Filesystem im ESP32 noch nicht angeschaut.

Dann mach das mal.

Flunder schrieb:

Bzw. kann ich den Bereich für das Filesystem auf nahezu null schrauben, um den Platz dann für Daten, die sich in meinem Programmcode verstecken, frei zu machen?

In Arduino gibt's da Vorschläge für Partitionsschemata zur Auswahl über das Menü, z.B. huge_app.csv man kann aber auch eine custom partitions.csv im Sketch Ordner ablegen.

https://github.com/espressif/arduino-esp32/tree/master/tools/partitions

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren