+
Skip to content

Conversation

caco3
Copy link
Collaborator

@caco3 caco3 commented Feb 16, 2025

This is a continuation of #3538

  • compress all html, css, js, jpg, png, svg and map files in the html folder. This speeds the Web UI serving up.
  • The pipeline will only include the compressed files.

@caco3 caco3 marked this pull request as ready for review February 16, 2025 16:32
@caco3
Copy link
Collaborator Author

caco3 commented Feb 16, 2025

@SybexX Macht das für dich so Sinn?

@caco3 caco3 linked an issue Feb 16, 2025 that may be closed by this pull request
@caco3 caco3 requested a review from SybexX February 16, 2025 16:33
@SybexX
Copy link
Collaborator

SybexX commented Feb 16, 2025

Habe es gerade mit firefox und Microsoft Edge ausprobiert, alles läuft top. Das Update hat etwa 2 Minuten gedauert, vorher waren es immer über 3 Minuten.

@caco3 caco3 merged commit 6b672ff into main Feb 16, 2025
12 checks passed
@SybexX
Copy link
Collaborator

SybexX commented Feb 18, 2025

@caco3 Da das Update die normalen Dateien von der SD nicht löscht, habe ich beim Testen leider einige Konflikte nicht bemerkt.
Zwei davon habe ich bereits gefixt: 68a262e und f2b6b4f
Ein weiteres ist, das der ESP32 auf die file_server.html zugreift und daher darf sie nicht als .gz gepackt sein.
Wenn ich Zeit habe, versuche ich dieses Problem auch zu lösen. Mal sehen, ob ich dafür auch eine schnelle und einfache Möglichkeit finde.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 18, 2025

oh, danke, daran habe ich nicht gedacht.

wir könnren die html files auch drin lassen, dann hätten wir auch einen fallback, wenn ein browser zickt. dafür wäre halt das update wieder grösser/langsamer

@SybexX
Copy link
Collaborator

SybexX commented Feb 18, 2025

@caco3 Das war auch mein Gedanke, jedoch hat es auch Nachteile, wie man sieht^^
Zudem habe ich festgestellt, das je weniger Dateien sich auf der SD befinden, desto stabiler/flüssiger läuft das System.
Wenn es keinen großen Aufwand macht, würde ich nur die Hauptdateien(index.html, overview.html, file_server.html und eventuell noch die edit_config.html) als html und .gz verwenden.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 18, 2025

Hier ein Vergleich:
grafik

Bei vielen Dateien lohnt sich die Komprimierung gar nicht resp. ist sogar eine Verschlechterung.

Bei edit_config_template.html ist es nicht representativ, da die Tooltips noch fehlen.

@SybexX
Copy link
Collaborator

SybexX commented Feb 19, 2025

Das Problem mit file_server.html habe ich folgend gelöst:

- <style></style> >>> file_server.css
- <script type="text/javascript"></script> >>> file_server.js
- <body></ body> >>> firmware

somit wird file_server.html gar nicht mehr gebraucht

https://github.com/jomjol/AI-on-the-edge-device/actions/runs/13462525449/artifacts/2632027390

@caco3
Copy link
Collaborator Author

caco3 commented Feb 23, 2025

Ich sehe noch ein weiteres Problem:
Haben wir sichergestellt, dass die gz-Datei Vorrang hat? Denn wenn wir in Zukunft nur noch die gz-Dateien aktualisieren, werden die html-Dateien nicht mehr weiter aktualisiert.
Ev. macht es auch Sinn, den html-Ordner bei einem update zu löschen, denn da sollten ja keine Anwender-Dateien liegen.

@SybexX
Copy link
Collaborator

SybexX commented Feb 23, 2025

Es wird immer überprüft, ob eine .gz Datei vorhanden ist, wenn nicht, wird die normale verwendet.

@SybexX
Copy link
Collaborator

SybexX commented Feb 23, 2025

@caco3 Wie wollen wir da weiter vorgehen?
Mit den Branch ein PR erstellen und dann mergen oder willst du auch die normalen html Dateien drinlassen?
https://github.com/jomjol/AI-on-the-edge-device/tree/gz-html-files-fix-missing-file_server.html

@caco3
Copy link
Collaborator Author

caco3 commented Feb 23, 2025

Ich wäre dafür, dass wir das html-Verzeichnis beim Update löschen, dann haben wir sicher keine alten Daten.
Idealerweise brauchen wir nur die gz files.

Wenn es Ausnahmen braucht, sollten wir verstehen, wieso sie nötig sind.

Es gibt bereits eine funktion, um das Verzeichnis zu löschen, aber ich habe noch nicht geschaut, wann der aufgerufen wird:

@SybexX
Copy link
Collaborator

SybexX commented Feb 23, 2025

Ich glaube Sie wird nie ausgeführt, es wird immer nur die davor ("update") verwendet.

@caco3 caco3 deleted the gz-html-files branch February 24, 2025 21:00
@caco3
Copy link
Collaborator Author

caco3 commented Feb 24, 2025

@SybexX Ich habe deinen branch (gz-html-files-fix-missing-file_server) via #3582 gemerged.

In #3583 habe ich mal aktiviert, dass bei einem Update das HTML-Verzeichnis gelöscht wird. Soweit ich sehen kann, brauchen wir nun nur noch die gz files.
Allerdings habe ich dadurch ein neues Problem eingeführt:
Wenn das Update abgebrochen wird, kann es sein, dass man kein UI mehr hat. Insb. wenn die ota_page fehlt, ist ein normaler Anwender aufgeschmissen.
Bin daher nicht sicher, ob das sinnvoll ist.

@SybexX
Copy link
Collaborator

SybexX commented Feb 24, 2025

um das ausschließen zu können, müsste man das löschen dann eventuell hier einfügen https://github.com/jomjol/AI-on-the-edge-device/blob/main/code/components/jomjol_fileserver_ota/server_file.cpp#L1028

zB. so eine Funktion noch hinzufügen:

bool DeleteFileNormalAndGzip(std::string filepath)
{
	std::string filepath_zw = filepath;

	if (toUpper(getFileType(filepath)) == "GZ")
	{
		filepath_zw = filepath.substr(0, filepath.find_last_of('.'));
	}
	else
	{
		filepath_zw = filepath + ".gz";
	}

	/* Delete file */
	FILE *fpSourceFile;
	if ((fpSourceFile = fopen(filepath.c_str(), "rb")) != NULL)
	{
		fclose(fpSourceFile);
		unlink(filepath.c_str());
	}

	/* Delete file */
	FILE *fzSourceFile;
	if ((fzSourceFile = fopen(filepath_zw.c_str(), "rb")) != NULL)
	{
		fclose(fzSourceFile);
		unlink(filepath_zw.c_str());
	}

	return true;
}

und dann DeleteFile(zw); durch DeleteFileNormalAndGzip(zw); ersetzen

@caco3
Copy link
Collaborator Author

caco3 commented Feb 24, 2025

das würde aber auch nur einfach die HTML-Dateien löschen, für die es eine ZIP-Datei gibt!
Du hast aber mal den verdacht geäussert, dass das System instabiler wird, wenn mehr Dateien vorhanden sind. Macht für mich keinen Sinn, aber dennoch dachte ich, das HTML-Verzeichnis aufzuräumen wäre nicht falsch. Sicher gibt es Anwender, die da einiges an alten Dateien herumliegen haben.

@SybexX
Copy link
Collaborator

SybexX commented Feb 24, 2025

die html.zip werden eigentlich mit der anderen Funktion Kopiert/Entpackt https://github.com/jomjol/AI-on-the-edge-device/blob/main/code/components/jomjol_fileserver_ota/server_file.cpp#L1054

die https://github.com/jomjol/AI-on-the-edge-device/blob/main/code/components/jomjol_fileserver_ota/server_file.cpp#L914 macht glabe ich nur die update.zip (eine Datei die eine firmware beinhaltet)

@caco3
Copy link
Collaborator Author

caco3 commented Feb 24, 2025

Neuer Ansatz:

  1. Die Dateien aus dem html folder im zip file werden in den Ordner html_tmp extrahiert (bisher html).
  2. Anschliessend wird der html folder zu html_old umbenannt
  3. und der html_tmp zu html umbenannt
  4. zuletzt wird html_old gelöscht.
    dadurch ist die kritische Zeit nur während punkt 2 und 3. Passiert etwas während punkt 1, wird einfach wie bisher das alte UI verwendet.

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Was sagst du zu:

  • html zu html_old umbenennen
  • zip in html entpacken
  • neustarten und gucken ob das System normal startet
    • wenn ja, html_old löschen
    • wenn nein, html löschen und html_old zu html umbennenen

oder

  • html zu html_old umbenennen
  • zip in html entpacken
  • wenn alles fehrerfrei abgelaufen ist, html_old löschen, ansonsten die html löschen und html_old zu html umbenennen

@caco3
Copy link
Collaborator Author

caco3 commented Feb 25, 2025

Was ist der Vorteil von deinem Ansatz?

Bei deinem ersten Ansatz sehe ich die Schwierigkeit feststellen zu können, ob das System normal startet. Das macht es ja auch mit fehlendem html Verzeichnis.

Das Ziel sollte zu sein, die heisse Phase so kurz zu halten wie möglich. Die heisse Phase ist diejenige, in welcher ein Crash/Neustart zu einem nicht-funktionierenden Gerät führt.
Diese Phase ist in deinem Ansatz deutlich länger (umbenennen, entpacken, umbenennen). Das Bei mir ist es nur 2x umbenennen. Das Entpacken geht deutlich länger als das umbenennen. Im Beispiel unten total 9000ms für den html-Teil, das Umbenennen ist <10ms:

I (6800) OTA: Extracting ZIP file /sdcard/firmware/AI-on-the-edge-device__update__test_(a413d02).zip...
I (6830) OTA FILE: Files to be extracted: 95
I (7120) OTA FILE: File to extract: /sdcard/config/ana-cont_1300_s2.tflite, Temp. Filename: /sdcard/config/ana-cont_1300_s2.tflite_tmp
[..]
I (13510) OTA FILE: File to extract: /sdcard/demo/530.07077.jpg, Temp. Filename: /sdcard/demo/530.07077.jpg_tmp
[..]
I (14990) OTA FILE: File to extract: /sdcard/html_tmp/ChangeRateThreshold.png.gz, Temp. Filename: /sdcard/html_tmp/ChangeRateThreshold.png.gz_tmp
[..]
I (23820) OTA FILE: File to extract: /sdcard/html_tmp/wlan_config.html.gz, Temp. Filename: /sdcard/html_tmp/wlan_config.html.gz_tmp
I (23880) OTA: Files unzipped.
I (23890) OTA: Renaming folder /sdcard/html to /sdcard/html_old...
I (23900) OTA: Renaming folder /sdcard/html_tmp to /sdcard/html...
I (23900) OTA: Deleting folder /sdcard/html_old...
I (24370) OTA: Found firmware.bin

Versuch doch bitte mal meinen Ansatz, ich habs bereits implementiert.

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Das Ziel sollte sein, die heisse Phase so kurz zu halten wie möglich. Die heisse Phase ist diejenige, in welcher ein Crash/Neustart zu einem nicht-funktionierenden Gerät führt.
Diese Phase ist in deinem Ansatz deutlich länger (umbenennen, entpacken, umbenennen). Das Bei mir ist es nur 2x umbenennen. Das Entpacken geht deutlich länger als das umbenennen. Im Beispiel unten total 9000ms für den html-Teil, das Umbenennen ist <10ms:

ja, hast Recht.

Mein Gedanke, mit dem späteren Löschen der alten html Dateien war, dass ja bei einigen Leuten, aus welchen Grund auch immer, beim Kopieren was schief gelaufen ist und sie ja dadurch boot loops bekommen haben. Und da war ja das Problem nicht, dass die Datei/Dateien fehlte/n, sondern das sie falsch Kopiert wurde/n (korrupt war).
Daher dachte ich mir, wenn das System normal startet, die alten Dateien dann zu löschen(wenn vorhanden) und wenn es zu einem boot loop kommt, die alten Dateien(wenn vorhanden) wiederherzustellen.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 25, 2025

Versuch doch bitte mal meinen Ansatz, ich habs bereits implementiert.

Sry, habs vergessen zu puschen, ist jetzt in #3584

@caco3
Copy link
Collaborator Author

caco3 commented Feb 25, 2025

Mein Gedanke, mit dem späteren Löschen der alten html Dateien war, dass ja bei einigen Leuten, aus welchen Grund auch immer, beim Kopieren was schief gelaufen ist und sie ja dadurch boot loops bekommen haben.

Liegt das nicht eher an einem Problem mit der SD-Karte?
Und bootloops sollte es eigentlich nicht geben, da wir beim start des updates die Datei /sdcard/update.txt erstellen und beim nächsten Start gleich wieder löschen. Dadurch wird ein bootloop unterbunden (sofern die SD-Karte mitmacht. Siehe

DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!!

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Ich vermutte, dass dies auftritt, wenn der ESP32 zB. während des Updates ein Bild macht oder anderweitig noch auf die SD zugreift. Deshalb habe ich in meinen privaten fork den Aufruf der Updatefunktion direkt nach den Initialisieren der SD und des PSRAMs gepackt und erst dann wird die Kamera, Wlan und co. Initialisiert.

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Zudem müsste man eventuell noch den normalen Ablauf vor dem Update beenden/stoppen, um sicherzustellen, dass beim Kopieren der zip, keine anderweitigen Zugegriffe auf die SD stattfinden.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 25, 2025

Das Update wird doch ganz früh im main durchgeführt: https://github.com/jomjol/AI-on-the-edge-device/blob/main/code/main/main.cpp#L394
Und der flow task wird erst viel weiter unten gestartet: https://github.com/jomjol/AI-on-the-edge-device/blob/main/code/main/main.cpp#L550

Somit ist gewährleistet, dass der flow erst nach dem update durchgeführt wird.

Aber ich gebe dir recht, es würde Sinn machen, das Update so früh wie möglich zu machen. Falls wir dazu kein PSRAM brauchen (bi nicht sicher), könnten wir es hier machen: https://github.com/jomjol/AI-on-the-edge-device/blob/main/code/main/main.cpp#L257

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Ich glaube PSRAM wird nicht benötigt, die SD verwendet ja nvs_flash und miniz den ROM, daher müsste es keine Probleme geben.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 25, 2025

Scheint zu klappen. Schaus dir doch bitte auch mal noch an: #3584

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

bei mir hat er die htmls nicht gelöscht, zudem hat die Kamera während des Updates ein Bild gemacht und nach dem Neustart kam ein boot loop mit dem Fehler "I BOD: Brownout detector was triggered" (AI-on-the-edge-device__update__3584_merge_(1c8fd54).zip). Nach dem ich den ESP32 dann kurzeitig stromlos machte, startete er wieder normal.
Habe direkt danach das Update nochmal gemacht(nachdem er mit der Runde fertig war), diesmal gabs keine Probleme, jedoch wurden die htmls wieder nicht gelöscht.

Unbenannt

@caco3
Copy link
Collaborator Author

caco3 commented Feb 25, 2025

Hmm, das ist merkwürdig. Hattest Du das vorher noch nie?

Komisch ist auch, dass der erwähnte commit (1c8fd54) gar nicht Teil des branches (https://github.com/jomjol/AI-on-the-edge-device/tree/refs/heads/remove-HTML-directory-on-update2) ist...

Ich habe gerade jeweils 2 updates auf meinen produktiven devices gemacht mit 57d1f7b. Lief jeweils ohne sichtbare Probleme und der Ordner wurde sauber ersetzt.

Hinweis: Die Änderungen kommen erst nachdem zweiten update zum zug (das update erfolgt mit der alten firmware).

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Dies Probleme habe ich ab und an, wenn während des Updates die Runde startet, meistens findet er jedoch dann die SD(0x00000008) oder Kamera(0x00000004) nicht mehr.

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

Beim dritten Versuch kam "I (6446) MAIN: Reset reason: Brownout", selbst das stromlos machen hat nichts gebracht.
Dann habe ich ihm in den boot loop gelassen und nach ca. 20x boot loops hat er normal gestartet (mit OV5640).
Die htmls wurden jedoch gelöscht.

@SybexX
Copy link
Collaborator

SybexX commented Feb 25, 2025

vieleicht liegt es an diesen zwei Stellen:

::rename(outHtml.c_str(), outHtmlOld.c_str());

::rename(outHtmlTmp.c_str(), outHtml.c_str());

ändere es mal in:
RenameFile(outHtml.c_str(), outHtmlOld.c_str());
RenameFile(outHtmlTmp.c_str(), outHtml.c_str());

AI-on-the-edge-device/code/components/jomjol_helper/Helper.h

bool RenameFile(std::string from, std::string to)
{
	/* Delete file */
	FILE *fpSourceFile = fopen(from.c_str(), "rb");

	// Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
	if (!fpSourceFile)
	{
		ESP_LOGE(TAG, "DeleteFile: File %s existiert nicht!", from.c_str());
		return false;
	}

	fclose(fpSourceFile);
	rename(from.c_str(), to.c_str());

	return true;
}

@SybexX
Copy link
Collaborator

SybexX commented Feb 26, 2025

Habe die Änderungen mal gemacht und gemerkt das RenameFile() ja nur für Dateien(Ordner werden nicht berücksichtigt^^) ist. Daher habe ich jetzt eine neue Funktion "RenameFolder()" hinzugefügt, damit funktioniert es bei mir ohne boot loops. Habe zig mal die Firmware hin und her geflasht, ohne Probleme, jedoch habe ich immer drauf geachtet, dass der Start einer Runde nicht in die Update Phase fällt.

bool RenameFolder(string from, string to)
{
	// ESP_LOGI(logTag, "Renaming Folder: %s", from.c_str());
	DIR *fpSourceFolder = opendir(from.c_str());

	// Sourcefolder does not exist otherwise there is a mistake when renaming!
	if (!fpSourceFolder)
	{
		ESP_LOGE(TAG, "RenameFolder: Folder %s does not exist!", from.c_str());
		return false;
	}

	closedir(fpSourceFolder);
	rename(from.c_str(), to.c_str());

	return true;
}

@caco3
Copy link
Collaborator Author

caco3 commented Feb 26, 2025

gemerkt das RenameFile() ja nur für Dateien(Ordner werden nicht berücksichtigt^^) ist

Jep, fopen() und Verzeichnisse vertragen sich nicht so gut.

damit funktioniert es bei mir ohne boot loops.

cool!

jedoch habe ich immer drauf geachtet, dass der Start einer Runde nicht in die Update Phase fällt.

Bist Du dir wirklich sicher, dass die Runde mal während dem Update gestartet hat?
So wie ich den Code verstehe, kann das gar nicht sein:

Zuerst kommt (via CheckUpdate()):

    xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
    while(1) { // wait until reboot within task_do_Update_ZIP
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }

Er bleibt also nach dem Task-Start im while(1) und geht nicht weiter.

Und erst viel später in main(), sofern kein Update gestartet wurde, wird der Flow-Task gestartet (via InitializeFlowTask():

xTaskCreatePinnedToCore(&task_autodoFlow,...);

@SybexX
Copy link
Collaborator

SybexX commented Feb 26, 2025

Ich meine die Phase währen des Hochladens der zip Datei, da wird die Runde ganz normal durchgeführt und natürlich zeitgleich auf die SD zugegriffen, um das Bild darauf zu speichern. Und ab und an entsteht da ein Fehler, der zu boot loops führt.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 26, 2025

D.h., Du hast crashes während dem Upload?
Das habe ich glaub noch nie beobachtet.

Grundsätzlich greift die Runde ja nur lesend auf die SD-Karte zu, da wird kein Bild gespeichert (ausser Du hast das Speichern der ROIs aktiviert).

Du hast von Brownouts gesprochen. Könnte es sein, dass deine Speisung ungenügend ist? Wenn auf die SD-Karte geschrieben wird und gleichzeitig die Kamera angesteuert wird, braucht das vermutlich eher mehr Strom als normal.

Die Runde während dem Upload zu unterbrechen ist wohl eher schwierig. Bei einer laufenden Runde müsste der Upload verzögert werden. Das müssten wir am ehesten in Javascript machen, indem wir den status abfragen (polling) und erst nach Ende der Runde den Upload starten.

@SybexX
Copy link
Collaborator

SybexX commented Feb 26, 2025

Ich würde sagen, die zip wird falsch auf die SD gepackt(korrupt) und dann passiert ein Fehler beim entpacken, der zu boot loops führt. Ich werde das nächste mal, wenn es passiert(eigentlich sehr sehr selten), die zip auf der SD mal am PC prüfen. Zumindest muß ich dann die Firmware nochmal mit Platformio auf den ESP32 neu drauf flaschen, damit er wieder funktioniert.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 26, 2025

ja, teste das doch mal. Ich habe so wirklich noch nie ein Gerät gebrickt.
Wir könnten das ZIP mit einem CRC oder MD5 schützen. Das geht problemlos in der pipeline. Und der ESP könnte das dann vor dem entpacken validieren.

@SybexX
Copy link
Collaborator

SybexX commented Feb 26, 2025

könnte aber etwas dauern, den wie gesagt, es passiert zum Glück nur äußerst selten.
Zudem werde ich auch noch drauf achten, ob es nur den ESP32 mit der OV5640 oder auch den mit der OV2640 betrifft. Denn ich gehe mal von aus, dass die OV5640 etwas mehr Strom verbraucht als die OV2640, da sie auch etwas heißer wird.

@caco3
Copy link
Collaborator Author

caco3 commented Feb 26, 2025

Sollen wir es mal so mergen?
Ich denke, die Probleme, die Du siehst, kommen nicht von diesen Änderungen.

Ich habe eine funktionierende Library gefunden, um die MD5-summe einer Datei zu berechnen. Nun müsste das nur noch sinnvoll eingebaut werden. Wir sollten das aber in einem separaten PR machen.

@SybexX
Copy link
Collaborator

SybexX commented Feb 26, 2025

Es funktioniert ja bei dir und auch bei mir, so wie es soll, daher spricht ja eigentlich nichts dagegen es zu mergen.

@SybexX
Copy link
Collaborator

SybexX commented Feb 26, 2025

eventuell könnte man auch die Funktion die bei miniz verfügbar ist verwenden "mzip_ulong mzip_crc32(mzip_ulong crc, const mzip_uint8 *ptr, size_t buf_len)"

@caco3
Copy link
Collaborator Author

caco3 commented Feb 27, 2025

Serverseitig ist es bereits implementiert: #3590
Nun müssen wir noch es auf browser-seite auch MD5 berechnen und vergleichen.

@SybexX
Copy link
Collaborator

SybexX commented Mar 7, 2025

#3568 (comment)

ich habe mal die setup.html überarbeitet, damit man die kleinen Dateien (explain_1.html bis explain_7.html) nicht mehr braucht.

https://github.com/jomjol/AI-on-the-edge-device/tree/rework_setup_html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compress generated HTML files

2 participants

点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载