Moinsen,
ich komme ja aus der embedded-Ecke, probiere mich aber trotzdem gerne
mal an anderen Themen.
Folgende Situation habe ich grad:
Ich habe ein Python-Skript verbrochen welches sich aus verschiedenen
Quellen diverse Daten abholt und diese sammelt. Das Skript läuft dabei
dauerhaft als daemon.
Nun möchte ich per Flask dem Skript ein Webinterface anflanschen, bzw.
das läuft bereits. Mein Skript ist in der Lage, eine html-Seite
auszuliefern. In diesem Webinterface sollen die angesammelten Daten
visualisiert werden. Zu Beginn würde ich das erstmal in eine simple
html-Tabelle packen.
Nun stellt sich mir aber die Frage wie ich die Webseite regelmäßig
aktualisiere.
Nicht nur dass sich die Daten im Laufe der Zeit ändern, es können auch
Einträge dazu kommen (sprich: die Tabelle kriegt mehr Zeilen und
Spalten).
Ich könnte jetzt den html-Code der Seite bereits serverseitig, also im
Pythonskript, mit den Daten befüllen. Der Browser würde dann nur eine
simple, statische Seite geliefert bekommen.
Methode 2 wäre, ein paar Javaskripte in die Seite einzubetten. Per
REST-Api könnte die Seite dann die dynamischen Inhalte nachladen (als
JSON-Struktur) und dann per jquery die Seite laufend aktualisieren.
Methode 1 wäre simpler, hat aber den Nachteil dass der Server nicht nur
Daten ausliefert sondern sich auch um so Details wie die graphische
Aufbereitung derselbigen kümmern muss.
Methode 2 ist etwas aufwendiger, dafür sind Datenschnittstelle und die
Anzeige der Daten sauber getrennt. Es wären sogar verschiedene
Visualisierungen denkbar.
Ich brauch ein paar Denkanstöße.
Wie würdet ihr das lösen?
Die Lösung heißt WebSocket, kannst du in deinem Flask auch einbauen.
Wenn ein Client deine Seite aufruft, wird zusätzlich eine WS Verbindung
aufgebaut. Immer wenn du neue Daten Hast, kannst du diese als Broadcast
an deine Clients sicken und dann auf Clientseite mit JavaScript
auswerten.
M. M. schrieb:> Nun stellt sich mir aber die Frage wie ich die Webseite regelmäßig> aktualisiere.
Eine gängige Methode ist AJAX.
Du kannst allen dynamischen Elementen eine eindeutige ID geben. Ein
Javascript ruft dann zyklisch Updates vom Server ab. In jedem Update
benennt der Server die des zu ändernden Elementes, sowie dessen Inhalt.
Tipp: Du kannst das Javascript so schreiben, dass es den Server in einer
Endlosschleife abfragt. Der Server muss nicht unbedingt sofort
antworten, sondern kann den Browser ruhig warten lassen, bis wirklich
neue Daten vorliegen. Das reduziert die CPU Auslastung und Stromaufnahme
beim Browser.
Ob deine Updates im HTML Format sind (also server-seitig aufbereitet)
oder im JSON Format (also browser-seitig aufbereitet) ist dann
hauptsächlich eine Geschmacksfrage. Kommt drauf an, auf welcher Seite du
lieber den dazu nötigen Strom verbrauchen willst.
M. M. schrieb:> Wie würdet ihr das lösen?
Ja, es gibt viele Wege.
Eine einfache HTML Seite (mit Auto-Refresh) kann nicht nur jeder Browser
anzeigen, man kann sie auch einfach (z.B. per Python) auf Empfängerseite
auseinandernehmen und ihren Inhalt analysieren.
Man könnte sie auch in PDF verwandeln und auf eBookReadern anzeigen.
Den Zugriff verbaust du dir mit komplexen Skriptingseiten.
Eine einfache Skripting-Seite holt sich den Rahmen, der erhalten bleibt,
und updated durch ihren Skrip nur die enthaltene Tabelle. Der Skript
braucht nur die Daten zu übertragen, und hält die Füsse still wenn sich
nichts verändert hat damit es nicht flackert.
Wer in seinem Browser Javascript deaktiviert, ist selber Schuld bzw.
kann das selber umstellen. Ich denke, man muss für diese Leute keine
Sonderlocke mehr vorsehen, das ist nicht mehr zeitgemäß.
Hier ein altes Beispiel, mit dem ich die "Navigationsleiste" auf meiner
Hompepage nachlade:
1
<html>
2
<body>
3
<divid="navi"></div>
4
5
<script type="text/javascript">
6
ajax_load("navi","navigation.html");
7
</script>
8
9
Hier kommt der eigentliche statische Inhalt der Seite
Dieses Beispiel kommt ohne Endlosschleife aus, weil die Navigation nur
einmal geladen werden muss. Aber ich denke, du kannst trotzdem davon
abgucken. Ich wollte damit nur zeigen, dass AJAX ganz einfach ist.
Steve van de Grens schrieb:> Eine gängige Methode ist AJAX.
"AJAX" ist ein Buzzword aus den 1990ern und 2000ern. Auch wenn das
Grundkonzept in etwa gleichgeblieben ist, sollte man das heute nicht
mehr so nennen.
Dazu ist die Abkürzung zu stark mit den damals üblichen&nötigen
Flash-Player-Active-X-XMLHttpRequest-würgarounds verknüpft.
Wenn man nach "AJAX" sucht, wird man von veraltetem JS-Code erschlagen,
üblicherweise mit XMLHttpRequest & Callback-Hölle, obwohl heute die
Browser alle "echtes" asynchrones Javascript (async/await) unterstützen
würden...
Steve van de Grens schrieb:> Der Server muss nicht unbedingt sofort> antworten, sondern kann den Browser ruhig warten lassen, bis wirklich> neue Daten vorliegen.
das sogenannte "longpolling" ist ähnlich alt, inzwischen als
ServerSentEvents aber formalisiert und mit einfacher API im Browser zu
handhaben.
https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
Oder gleich Websockets...
Ja, die ganzen Webtechniken aus den 1990ern funktionieren auch heute
noch. Aber wenn jemand was Neues entwickeln will, kann er auch aktuelle
Techniken einsetzen.
Muss ja nicht gleich eine React-Webapp werden.
Steve van de Grens schrieb:> Ich wollte damit nur zeigen, dass AJAX ganz einfach ist.Steve van de Grens schrieb:> function ajax_load(id,url) {
Achtung: Dein try-catch ist unvollständig. Exceptions, die aus dem
onreadystatechange-Handler geworfen werden, fängt das catch nicht.
um dein Beispiel zu aktualisieren:
Zunächst AJAX und jQuery sind out 🫣
Ob dir der Server statische HTML seiten generiert oder du die Daten
mittels JavaScript nachlädst, ist erstmal egal.
Meine Kriterien wären UX, DX und SEO.
UX - User experience
Werden die Daten via JavaScript geladen ist das navigieren, sortieren
oder filtern meist flüssiger als bei auf dem server generierten seiten.
DX - Developer experience
Was entspricht ehr deinen Fähigkeiten?
Eine brauchbare Lösung gut umgesetzt ist meist besser, als die beste
Lösung stümperhaft programmiert.
SEO - Search engine optimization
Wenn der Inhalt von Suchmaschinen leicht indiziert werden soll, sind
statische bzw servergenerierte Seiten besser, da der Bot kein JS
ausführen muss um an den Inhalt zu kommen.
Die eierlegenden Wollmilchsau:
Der Server liefert bei der ersten Anfrage statischen Inhalt und
aktualisiert diesen bei Bedarf dynamisch.
Eine Bibliothek, die das recht simple umsetzt ist: HTMX
Dann muss die REST API aber HTML liefern und kein JSON.
M. M. schrieb:> Folgende Situation habe ich grad:> Ich habe ein Python-Skript verbrochen welches sich aus verschiedenen> Quellen diverse Daten abholt und diese sammelt. Das Skript läuft dabei> dauerhaft als daemon.>> Nun möchte ich per Flask dem Skript ein Webinterface anflanschen, bzw.> das läuft bereits. Mein Skript ist in der Lage, eine html-Seite> auszuliefern. In diesem Webinterface sollen die angesammelten Daten> visualisiert werden. Zu Beginn würde ich das erstmal in eine simple> html-Tabelle packen.
Das würde ich persönlich nicht machen, sondern die beiden Komponenten je
das tun lassen, was sie am Besten können: das Datensammelskript kümmert
sich um Deine Daten, das WSGI-Skript (Flask) kümmert sich darum, die
Daten fürs Web aufzubereiten. Die beiden Komponenten können dann
entweder direkt miteinander kommunizieren, oder -- je nachdem -- kann es
auch sinnvoller sein, noch eine Infrastrukturkomponente dazwischen zu
platzieren.
Zunächst einmal ist die Frage, was Du mit Deinen Daten nach deren
Sammlung zuerst machen möchtest. Sollen Deine Daten verarbeitet, also
zum Beispiel umgerechnet oder aggregiert werden? Sollen die Daten in
irgendeiner Weise persistiert, also gespeichert werden, und wenn ja:
wie?
Für sinnvolle Ratschläge wäre es sicherlich sinnvoll, wenn Du etwas zu
den Daten sagen könntest, vor allem zu Umfang, Quellen und Struktur,
dann etwas dazu sagen könntest, ob und wie sie verarbeitet und ob, wie
und wie lange sie gespeichert werden sollen, und wie Du sie am Ende
darstellen möchtest, also beispielsweise in Balken- oder
Liniendiagrammen, nur in Tabellen, oder... richitg, da gibt es drölfzig
Möglichkeiten, statische, interaktive, und so weiter, und so fort. Diese
Aspekte erscheinen mir nach der Lektüre Deines Eröffnungsbeitrages noch
zu diffus, um etwas Kluges dazu zu sagen.
Alex Z. schrieb:> Die Lösung heißt WebSocket, kannst du in deinem Flask auch einbauen.
Ja, also, äh... ja, das kann man machen. Aber dann würde ich eher über
das Modul Flask-SocketIO von Miguel Grinberg (ja, der mit den
Flask-Tutorials) nachdenken, das auf Websockets aufbaut, aber viele
nützliche zusätzliche Features der JavaScript-Bibliothek SocketIO
nutzbar macht.
Am einfachsten ist es nur die zu erneuernden Daten als
Varieablendeklaration (vorzugsweise als Arrays) in eine JS-Datei zu
schreiben. Das ist sehr viel kompakter als Daten in HTML-Form.
Im Init-Skript wird ein Timer installiert, der in Abständen die Daten
neu anfordert und einige Sekunden danach die Darstellung aktualisiert.
Das Anfordern der Daten geschieht durch die Neuerstellung eines
<Script>-Elements. Ein schon bestehendes Elelement mit gleicher ID wird
vorher entfernt.
Jobst Q. schrieb:> Am einfachsten
Und dann lieferst du so einen umständlichen und veralteten code?
Wo hast du den ausgegraben, stammt wohl noch aus der Zeit vor JSON?
Steve van de Grens schrieb:> Wer in seinem Browser Javascript deaktiviert, ist selber Schuld bzw.
Der schont den Akku seines Laptops oder Tabletts und bekommt
regelmässig keine Werbung zu sehen.
> kann das selber umstellen. Ich denke, man muss für diese Leute keine
> Sonderlocke mehr vorsehen, das ist nicht mehr zeitgemäß.
Was zeitgemäß ist, bestimmt wohl immer noch der Nutzer.
> Hier ein altes Beispiel, mit dem ich die "Navigationsleiste" auf meiner> Hompepage nachlade:
Eine von den kaputten Webseiten, die als HTML-Version keine Navigation
haben?
Der besondere Lacher: Eine Kommerzseite, deren Javascriptnavigation
bei einem Zoomfaktor von 150 % einfach vom Bildschirm verschwand,
und dann navigationslos daherkam?
Was für ein Dreck.
Genau wie die "Neue und dynamische" Seite der Fahrplanauskunft
der Deutschen Bahn.
Εrnst B. schrieb:> Jobst Q. schrieb:>> Am einfachsten>> Und dann lieferst du so einen umständlichen und veralteten code?> Wo hast du den ausgegraben, stammt wohl noch aus der Zeit vor JSON?>>
1
>setInterval(async()=>{
2
>data=await(awaitfetch("update.json")).json();
3
>},1000);
4
>
Ich habe ihn nicht ausgegraben, sondern aus einfachen
Javascript-Funktionen entwickelt. Die Umständlichkeit deines Codes ist
nur versteckt, wenn man ihn verstehen will, ist nichts mehr einfach. Nur
weil es etwas wie JSON gibt, muss man es nicht verwenden, wenn es ohne
besser geht.
Es geht um die Einfachheit der Bereitstellung der Daten im Server, was
gerade im Embedded-Bereich von Bedeutung ist. Und
JS-Variablenzuweisungen sind deutlich einfacher als das JSON-Format. Zum
Beispiel:
Keiner von euch Spezies kennt die genauen Anforderungen an das
Datenformat und ihr kloppt euch...
Btw, der TO hat sich noch nie zu irgendeiner Antwort geäußert. Selbst
wenn er nochmal wieder hier aufschlägt sind solche DetailKriege doch
nichts was ihm (derzeit) weiterhilft.
Ich beobachte weiter, warte auf den TO und hoffe auf nicht zu viel
vorrauseilende Antworten.
Kolja L. schrieb:> Btw, der TO hat sich noch nie zu irgendeiner Antwort geäußert. Selbst> wenn er nochmal wieder hier aufschlägt sind solche DetailKriege doch> nichts was ihm (derzeit) weiterhilft.
Genau, der TO ist nämlich etwas irritiert von den Antworten und musste
erst abwägen ob es noch zielführend ist diesen Thread fortzusetzen.
Vor allem bin ich aber irritiert dass hier Code gepostet, JSON und
Javascript in Frage gestellt und Buzzwörter wie UX, DX und SEO
eingesträut werden.
Die technische Umsetzung krieg ich hin, bzw. habe ich bereits
hinbekommen, sowohl Methode 1 (Server liefert bettet Daten in ein
template ein und liefert statisches html) als auch Methode 2 (Browser
lädt zyklisch Daten per REST/JSON nach und aktualisiert den html-Code).
Ich werde Lösung 2 behalten weil sich die Seite dort selber partiell
aktualisieren kann (ja, würde mit Websockets auch gehen) und
Datensammlung und deren Darstellung im Frontend sauber getrennt sind.
Außerdem kann die REST-Api auch anderweitig (Script, Logger) genutzt
werden.
Die Frage war wirklich nur zu welcher Methode ihr tendiert und wieso,
welche Vor- und Nachteile diese noch haben die ich evtl. nicht sehe.
M. M. schrieb:> Buzzwörter wie UX, DX und SEO eingesträut werden.
Da ich nicht weiß, wissen kann, wer die Seite programmiert und wer sie
nutzen soll, hab ich es halt allgemein formuliert 😉
So hatte ich deine Frage auch verstanden.
Den Punkt, den du noch genannt hast, habe ich allerdings vergessen. Mit
einer API bist du natürlich flexibler was die Ausgabe der Daten angeht.
Dann noch viel Erfolg
Im gesamten Thread sehe ich nichts zum Thema Aktualisierungs-Frequenz,
was aber m.E. entscheidend für die Wahl der Mittel wäre. Sollen die
fremden Daten jedesmal aktualisiert werden, sobald jemand die HTML-Seite
aufrufen wird? Sicher nicht, oder?
Mein Vorschlag: Der Sammler-Daemon aktualisiert autonm in einer
angemessenen Frequenz die Daten in eine Datenbank hinein. Entweder
überschreibt er die alten mit den aktuellen Daten oder er legt jedesmal
neue Datensätze an. Dann könnte man im Web-Interface eventuell auch die
Historie betrachten oder Diagramme daraus machen ...
Die Webseite ist ebenfalls autonom und ezeugt bei Aufruf aus der
Datenbank heraus jeweils eine (momentan) statische Ansicht. Das könnte
man mit Apache/PHP oder node.js machen.
WebSocket oder Ajax/Promises usw. sind m.E. nur sinnvoll, wenn die
Aktualiserungsfrequenz sehr hoch ist, während man auf der Webseite
verweilt. Aber zur Frequenz wurde ja bisher nichts mitgeteilt.