mikrocontroller.net

Forum: PC-Programmierung HTML mit dynamischem Inhalt


Autor: Martin M. (martin69)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe einen Webserver mit ATmega128 gebaut (Rolladensteuerung). Der 
HTML-Code wird abhängig von diversen Parametern übertragen (Beispiel 
siehe Infoseite in der beigefügten Datei). Ich bin hierbei wie folgt 
vorgegangen:

1. "normale" HTML-Seite am PC zusammen gebastelt.
2. HTML-Datei in Einzelteile zerlegt, daß die zu ändernden Teile separat 
stehen (feste Teile im Flash, variable Texte im RAM).
3. Das Sammelsorium im AVR wieder (parameterabhängig) zusammen gebaut.

Funktioniert zwar, aber das ist ziemlich umständlich und die auch zuvor 
erforderliche Längenberechnung für den HTML-Header ist ziemlich lästig.

Besser wäre es, wenn man den String komplett im RAM zusammen bauen 
könnte, dann Länge des gesamten Strings mit strlen() herausfinden und 
dann den ganzen String senden. Dann wäre zumindest die Längenberechnung 
eine Kleinigkeit. Nachteil: ich hab nicht so viel RAM frei. Bin am 
überlegen, ob ich ein externes RAM ran mache.

Oder gibt es noch andere Tricks, wie man das machen könnte? Z.B. den 
HTML-Code komplett im Flash ablegen und an den variablen Stellen 
bestimmte Kennungen machen, die man dann während der Ausgabe auf der 
Schnittstelle modifiziert.

Bin für jeden Hinweis dankbar!

Autor: Martin M. (martin69)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
anbei noch ein Auszug aus dem Quellcode zu dieser HTML-Datei. Ziemlich 
aufwändig das Ganze....

Autor: Frank Esselbach (Firma: Q3) (qualidat)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass du HTML und HTTP durcheinander bringst?

Der HTML-Code einer Webseite benötigt keine Längenangabe und hat auch 
keinen Header, wohl aber einen Head-Bereich. Bei HTTP wird dagegen 
tatsächlich eine Längenangabe benötigt ...

Ansonsten könnte deine Idee tatsächlich funktionieren. Du baust im 
HTML-Prototyp an den entsprechenden Stellen Platzhalter ein, die dann 
bei der Auslieferung durch die zutreffenden Werte ersetzt werden. Ich 
würde dafür ASCII-Zeichen oberhalb 128 verwenden. Weil die im HTML-Code 
sonst nicht vorkommen dürfen, kann man sie einfach ausfiltern.

Wegen der Längenangabe für den HTTP-Stream könntest du das Brett an der 
dünnsten Stelle bohren: ersetze alle Platzhalter immer durch die gleiche 
Anzahl von Zeichen, z.B. Nutzzeichen plus Leerzeichen oder 
HTML-Kommentare, so dass die Länge immer gleich bleibt - das spart die 
Berechnung.

Frank

Autor: Andi ... (xaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
auch wenns jetzt böse ist und kein standart etc ist...
sende deinen http header ohne length key.
wenn du alle daten gesendet hast schließt du den stream einfach zum 
browser ;) firefox oder ie, zumindest die neuen gehen dann von einer 
broken connection aus und nehmen die bisher empfangenen daten als 
content-length..

probiers aus ;)

Autor: Martin M. (martin69)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@Frank Esselbach:

ja, da hab ich wohl HTTP und HTML etwas durcheinander gebracht. Im 
Prinzip ist es mir schon klar, ich habe mich nur etwas unglücklich 
ausgedrückt...


@Andi D:

wie schließe ich einen Stream?


@alle
Das mit dem festen HTML-Code mit den Kennungen funktioniert auch nur bei 
einfacheren Seiten. Ist vielleicht nicht so eine gute Idee...

Ich habe auch Seiten, wo die HTML-Längen auch noch von anderen 
Parametern abhängig sind. So z.B. bei der Einblendung der Statusboxen im 
Grundriss (siehe Bild). Auf diesem Stockwerk sind es 13 Rolläden. Die 
selbe Funktion verwende ich derzeit für alle Stockwerke (wird mit 
Schleifen gemacht, abhängig von der Anzahl der Rolläden auf dem 
Stockwerk). Im Dachgeschoß sind es nur 7 Rolläden und daher auch 
entsprechend weniger HTML-Code... Z.B. gibt es die folgende Zeile, je 
nach dem, wie viele Rolläden vorhanden sind:

<div style="position:absolute; left:391px; top:55px; width:20px; 
height:20px; background-color:#FFFF00; border:2px solid #000000"></div>

Ich denke die einfachste Sache wird die mit dem externen RAM sein....

Autor: oszi40 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klingt interessant, nur ist RAM bei Stromausfall ziemlich vergesslich.

Autor: Andi ... (xaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
socket.close() oder sowas in der richtung, kommt halt drauf an, was du 
als ethernet connection benutzt etc.

ich würde dir jetzt aber dazu raten, für etwas komplexere sachen solche 
spielerein mitm avr als webserver zu lassen...schön und gut für 
messwerte über ethernet etc ists ja ok aber nicht für ne GUI...
nimm am besten nen kleinen nettop oder sowas als sever mit linux, 
lighttpd, php, mysql und du wirst keinerlei probleme mehr haben, wobei 
sich gleichzeitig ganz neue welten an möglichkeiten eröffnen.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Solche Geschichten kann man einigermaßen elegant mit einer einfachen 
Substitutions-Routine machen:

An die Stellen, an denen eine Variable eingefügt werden soll, schreibt 
man z.B. '$n' - ohne Hochkomma und n steht für die einstellige 
Parameterkennung.

Die Substitutions-Routine ist im Prinzip eine Kopier-Routine, die den 
Prototyptext zeichenweise in den Ausgabepuffer überträgt.

Wenn sie ein $ findet, testet sie das nächste Zeichen:

  - wenn es $ ist, wird ein $ in den Ausgabepuffer kopiert
  - wenn es eine gültige Parameterkennung ist, wird dessen Wert kopiert
  - anderenfalls wird $ gefolgt von der ungültigen Kennung kopiert

Anschließend wird nach dem $n weiter gemacht, bis irgendwann NUL kommt - 
das wird auch in den Ausgabepuffer übertragen und beendet.

Wenn ein $ ausgegeben werden soll, muß es verdoppelt werden.

Die Länge des Resultat-Strings kann man leicht mit strlen bestimmen...

Autor: Andi ... (xaos)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uhu Uhuhu wrote:

> Die Länge des Resultat-Strings kann man leicht mit strlen bestimmen...

genau dazu brauch man viel ram , der hier nicht verfügbar ist;)

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst den Urtext im Flash ablegen - dort wirst du mit der Methode 
viel Platz gewinnen, weil du das ganze
"uiLEN_html = uiLEN_html + strlen_P(FLASH_WEB_HTML_DOCTYPE);"-Gesprattel 
nicht mehr brauchst.

Zudem kannst du die Substitutions-Routine auch so schlau machen, daß sie 
die Länge als Nebenergebnis liefert.

Falls nicht genug RAM da ist, um den Text der endgültigen HTML-Seite im 
Speicher zu halten, kann man etwas mehr Zeit spendieren und zweimal 
substituieren:

- einmal in den Müll, um die Länge zu ermitteln und
- ein zweites mal direkt in den UART.

Diese Methode hat sogar den Vorteil, daß man das Längenfeld als 
$-Variable einfügen kann - man muß nur dafür sorgen, daß die Variable 
mit so vielen Stellen vorbesetzt ist, wie für das Längenfeld gebraucht 
wird.

Und zudem hat das Substitutionsverfahren einen ganz entscheidenen 
Vorteil: Es funktioniert datenunabhängig, d.h., wenn sich deine 
HTML-Seite ändert, brauchst du nur noch die Schablone zu ändern, nicht 
den ausführbaren Code.

Deswegen lieben Profis solche Methoden...

Autor: G. O. (aminox86)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für alle, die sich mit dynamischen Webseiten herumschlagen und es ganz 
genau wissen wollen (aber nicht zu fragen wagen):
-Jeremy Bentham: TCP/IP Lean. Webservers for embedded systems. CPM Books 
1.Auflage 2000, 2.Auflage 2002
Nach einer allgemeinen Einführung in (Internet)Übertragungsprotokolle 
und die Konstruktion eines TCP/IP-Stack wird gezeigt, wie interaktive, 
dynamische Webseiten unter anderem mit einem PIC erzeugt werden können. 
Beispielhaft sind dynamischer Text (eine Temperaturanzeige, was auch 
sonst) und dynamische Graphiken (Schalter mit Kontrolleuchten) 
dargestellt. Die zweite Auflage setzt noch eins drauf: Bildübertragung 
mit PIC über Ethernet zum PC.
Die Programmbeispiele, auch für den PIC, sind in C gehalten. Daher 
sollten sie sich leicht portieren lassen.
Meiner Meinung nach genau das Buch zum Thema.
mfg

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Substitutionssache hat einen Nachteil bei dem bei kleinen 
Prozessoren benutzten Verfahren, wo immer nur ein Paket generiert und 
losgesendet wird:
Man muss diese Substitutionsroutine so schreiben, dass, wenn im 
aktuellen Paket nur noch 1 Byte frei ist, sie die restlichen Bytes beim 
nächsten mal rausschiebt. Ganz ohne extra RAM geht das also nicht.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es erfordert etwas mehr Hirnschmalz, ist aber auch machbar, wenn man die 
Substitutions-Routine so baut, daß immer maximal n Zeichen zurück gibt 
und in einer externen Variablen ihren Zustand abspeichert.

Noch speicherschonender geht es, wenn zunächst der Header von einer 
Steuerroutine auf den UART geht und dann die Substitution ihre nächsten 
n Zeichen direkt auf den UART ausgibt.

Was bleibt, ist das Substitutionsprinzip, das den Code von den Daten 
separiert.

Autor: Martin M. (martin69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für Eure Tipps!

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Falls nicht genug RAM da ist, um den Text der endgültigen HTML-Seite
> im Speicher zu halten, kann man etwas mehr Zeit spendieren und
> zweimal substituieren:
>
> - einmal in den Müll, um die Länge zu ermitteln und
> - ein zweites mal direkt in den UART.

Dann muß man aber darauf achten, daß sich zwischendrin die zu 
substituierenden Werte nicht ändern. Wenn das nicht sicher ist, muß man 
deren zugrundeliegende Daten alle als Kopie sichern, damit man auch 
wirklich zweimal hintereinander den gleichen String bekommt.

Autor: Martin M. (martin69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich werde wohl ein externes RAM auf den Webserver setzen. Am ATmega128 
kann man bis zu 60k x 8 anschließen.

1) HTML-String mit strcpy/strcat zusammen bauen und ins externe RAM 
legen
2) Länge des HTML-Strings mit strlen() bestimmen
3) HTTP-Header mit der LEN-Angabe samt HTML-String aus dem externen RAM 
senden

Fertig!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:

> Man muss diese Substitutionsroutine so schreiben, dass, wenn im
> aktuellen Paket nur noch 1 Byte frei ist, sie die restlichen Bytes beim
> nächsten mal rausschiebt. Ganz ohne extra RAM geht das also nicht.

Andersrum. Man kontrolliert vor der Substitution erst nach, ob genug 
Platz im Frame ist und schiebt den Kram erst einmal raus wenn nicht. Im 
nächsten Rutsch (Frame) hat man dann den ganzen Frame zur Verfügung.

Was HTTP angeht: Das funktioniert wie oben schon erwähnt wurde ganz gut 
auch ohne Länge.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. wrote:
> Andersrum. Man kontrolliert vor der Substitution erst nach, ob genug
> Platz im Frame ist und schiebt den Kram erst einmal raus wenn nicht. Im
> nächsten Rutsch (Frame) hat man dann den ganzen Frame zur Verfügung.

Jup, das geht natürlich auch :-)

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:
>> - einmal in den Müll, um die Länge zu ermitteln und
>> - ein zweites mal direkt in den UART.
>
> Dann muß man aber darauf achten, daß sich zwischendrin die zu
> substituierenden Werte nicht ändern. Wenn das nicht sicher ist, muß man
> deren zugrundeliegende Daten alle als Kopie sichern, damit man auch
> wirklich zweimal hintereinander den gleichen String bekommt.

Nein, man muß nur dafür sorgen, daß sich die Länge nicht ändert. Ob in 
einem Feld 0000 oder 4711 steht spielt keine Rolle.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. wrote:
> Andersrum. Man kontrolliert vor der Substitution erst nach, ob genug
> Platz im Frame ist und schiebt den Kram erst einmal raus wenn nicht. Im
> nächsten Rutsch (Frame) hat man dann den ganzen Frame zur Verfügung.

Nein. Wenn man die Protokollsteuerung von der Substitution entkoppelt 
und erstere der Substitutions-Maschine - die hat einen Zustand und weiß, 
wo sie bei jedem Aufruf weitermachen muß - sagt, wieviele Zeichen sie 
maximal in den Ausgabepuffer schreiben darf, dann kann man sich derlei 
vorausschauende Klimmzüge sparen.

Das einzige, was passieren kann, ist, daß die Substitutions-Maschine 
sagt, "es waren aber nicht 15, sondern nur noch 3 Zeichen auszugeben".

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Nein, man muß nur dafür sorgen, daß sich die Länge nicht ändert. Ob
> in einem Feld 0000 oder 4711 steht spielt keine Rolle.

Wenn sich die Länge nicht ändert, weiß man sie schon zur Compilezeit und 
braucht sie nicht nachher zur Laufzeit berechnen.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:
> Wenn sich die Länge nicht ändert, weiß man sie schon zur Compilezeit und
> braucht sie nicht nachher zur Laufzeit berechnen.

Das ist nur ein Spezialfall. Die Länge kann sich ja auch dynamisch 
ändern, aber die Größenordnung ist jeweils vorab bekannt - nicht die 
genaue Größe.

Autor: NexX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Ahnung, womit du den HTML-Code gemacht hast, aber den kann man 
schon um einiges kürzen... Damit wär dein RAM etwas entlastet...

Autor: Martin M. (martin69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@NexX:
mit Netscape Composer. jDer gibt relativ geringen HTML-Code aus (im 
Vergleich dazu, wenn man HTML mit Word erstellt).
Was will man da noch viel kürzer machen? Die Schrift möchte ich bei 
Arial lassen, denn sonst sieht die Seite nicht so schön aus... Sonst 
kann man ja quasi auf nichts verzichten...

Gruß
Martin

Autor: Tobi H. (tobi-) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
CSS könnte hier Wunder wirken. Siehe
http://de.selfhtml.org/css/eigenschaften/schrift.htm#font

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Martin M. wrote:
> @NexX:
> mit Netscape Composer. jDer gibt relativ geringen HTML-Code aus (im
> Vergleich dazu, wenn man HTML mit Word erstellt).
> Was will man da noch viel kürzer machen? Die Schrift möchte ich bei
> Arial lassen, denn sonst sieht die Seite nicht so schön aus... Sonst
> kann man ja quasi auf nichts verzichten...

Das <font face="Arial,Helvetica">-Gesprattel muß nicht für jedes Element 
wiederholt werden.

Wenn du den Inhalt des Body in <font face="Arial,Helvetica"> ... </font> 
klammerst, reicht das aus - es sei denn, du willst unterwegs die Schrift 
ändern.

CSS braucht man deswegen nicht unbedingt...

Autor: Martin M. (martin69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@uhu:
das war ein sehr guter Tipp! Vielen Dank.

Autor: Chris .. (nexx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab den Code angepasst. Sollte in etwa aussehen wie vorher, ist aber 
kürzer und übersichtlicher:
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Server-Infos</title>
<style type="text/css">
body { font-family: Arial, Helvetica; background-color: #FFFF99; }
table { border: 0; width: 340px; background-color: #CCCCCC; margin-bottom: 40px;}
td { width: 140px; }
</style>
</head>
<body>
<h1>Infos Webserver</h1>

<table cols="2">
<tr><td><b>Hardware</b></td><td></td></tr>
<tr><td>Seriennummer:</td><td>Prototyp</td></tr>

<tr><td>Prozessor:</td><td>ATmega128</td></tr>
<tr><td>LAN-Interface:</td><td>XPORT Direct+</td></tr>
<tr><td>SD-Card:</td><td>ja</td></tr>
</table>

<table cols="2">
<tr><td><b>Software</b></td><td></td></tr>
<tr><td>Version:</td><td>001</td></tr>

<tr><td>Compiled:</td><td>Dec 26 2008 / 22:28:10</td></tr>
<tr><td>RS485-Adresse:</td><td>W30</td></tr>
</table>

<table cols="2">
<tr><td><b>Bautrate</b></td><td></td></tr>
<tr><td>RS485-Bus:</td><td>9600</td></tr>
<tr><td>AVR <=> XPort:</td><td>57600</td></tr>

</table>

<hr />
</body>
</html>

Autor: Martin M. (martin69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Chris H.

oh ja, sieht im Internetexplorer aus wie meine Seite, im Quellcode aber 
übersichtlicher. Auch Dir vielen Dank!

Gruß
Martin

Autor: NexX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann den Code noch weiter kürzen, aber dann ist er nicht mehr 
übersichtlich... Man würde nochmal ca 200 Byte sparen...
also alle zeilenumbrüche raus und noch einige andere änderungen im 
code...

Autor: Martin M. (martin69)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
die Zeilenumbrüche lasse ich lieber drin. Sonst blickt man nichts mehr, 
wenn man einen Fehler im HTML-Code sucht...

Autor: NexX (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wenn der Code einmal kontrolliert ist und man danach die leerzeichen 
entfernt, und dann nur noch ersetzt, passiert nix...
selbst mit leerzeichen kann man noch ca 180 Byte einsparen..

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Such mal auf dem Web, da gibt es etliche HTML-komprimierende Programme - 
denen gibt man eine schön strukturierte Datei zu fressen und hinten raus 
kommt eine möglichst kurze, unschöne, die aber im Browser denselben 
Effekt hat.

Wenn du sowas in dein Buildscript einbaust, dann hast du als Quelltext 
deine übersichtliche Version und der Compiler büchst trotzdem die 
minimale ein.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder die Webseite als gz bereitstellen. Dann kannste aber nachher nur 
noch ganz schwer etwas einfügen ;)

Autor: Nexx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wenn du sowas in dein Buildscript einbaust, dann hast du als Quelltext
> deine übersichtliche Version und der Compiler büchst trotzdem die
> minimale ein.

dann ist aber immernoch die große version im speicher

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nexx wrote:

> dann ist aber immernoch die große version im speicher

Wieso? Wenn das Packtool aus dem schon strukturieren Text einen 
Headerfile erzeugt, in dem der gepackte Text steht und der Quellmodul 
von diesem generierten Header abhängig ist, dann kommt hinten aus der 
Toolchain der Code mit dem gepackten HTML raus.

Ein make-Skript muß man dafür schon bauen...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.