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!
anbei noch ein Auszug aus dem Quellcode zu dieser HTML-Datei. Ziemlich aufwändig das Ganze....
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
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 ;)
@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....
Klingt interessant, nur ist RAM bei Stromausfall ziemlich vergesslich.
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.
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...
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;)
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...
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
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.
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.
> 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.
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!
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.
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 :-)
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.
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".
> 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.
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.
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...
@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
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...
Ich hab den Code angepasst. Sollte in etwa aussehen wie vorher, ist aber kürzer und übersichtlicher:
1 | <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
2 | <html>
|
3 | <head>
|
4 | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
5 | <title>Server-Infos</title> |
6 | <style type="text/css"> |
7 | body { font-family: Arial, Helvetica; background-color: #FFFF99; } |
8 | table { border: 0; width: 340px; background-color: #CCCCCC; margin-bottom: 40px;} |
9 | td { width: 140px; } |
10 | </style>
|
11 | </head>
|
12 | <body>
|
13 | <h1>Infos Webserver</h1> |
14 | |
15 | <table cols="2"> |
16 | <tr><td><b>Hardware</b></td><td></td></tr> |
17 | <tr><td>Seriennummer:</td><td>Prototyp</td></tr> |
18 | |
19 | <tr><td>Prozessor:</td><td>ATmega128</td></tr> |
20 | <tr><td>LAN-Interface:</td><td>XPORT Direct+</td></tr> |
21 | <tr><td>SD-Card:</td><td>ja</td></tr> |
22 | </table>
|
23 | |
24 | <table cols="2"> |
25 | <tr><td><b>Software</b></td><td></td></tr> |
26 | <tr><td>Version:</td><td>001</td></tr> |
27 | |
28 | <tr><td>Compiled:</td><td>Dec 26 2008 / 22:28:10</td></tr> |
29 | <tr><td>RS485-Adresse:</td><td>W30</td></tr> |
30 | </table>
|
31 | |
32 | <table cols="2"> |
33 | <tr><td><b>Bautrate</b></td><td></td></tr> |
34 | <tr><td>RS485-Bus:</td><td>9600</td></tr> |
35 | <tr><td>AVR <=> XPort:</td><td>57600</td></tr> |
36 | |
37 | </table>
|
38 | |
39 | <hr /> |
40 | </body>
|
41 | </html>
|
@Chris H. oh ja, sieht im Internetexplorer aus wie meine Seite, im Quellcode aber übersichtlicher. Auch Dir vielen Dank! Gruß Martin
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...
die Zeilenumbrüche lasse ich lieber drin. Sonst blickt man nichts mehr, wenn man einen Fehler im HTML-Code sucht...
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..
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.
Oder die Webseite als gz bereitstellen. Dann kannste aber nachher nur noch ganz schwer etwas einfügen ;)
> 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
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...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.