Forum: Mikrocontroller und Digitale Elektronik AVR Webseite mit externem Javascript


von Frank W. (skyifx)


Angehängte Dateien:

Lesenswert?

Hallo

Ich weiss nicht, ob folgende Problematik hier schon einmal diskutiert 
wurde, aber auch auf die Gefahr hin, Schelte zu ernten, will ich das 
Thema einmal ansprechen.

Folgende Problematik...
Ich betreibe aktuell zwei AVR-NET-IO von Pollin für verschiedene 
Aufgaben (S0-Zähler und IO-Board). Im Code (eine Mischung auch eigenem 
Code, dem von U.Radig und Robue) befinden sich natürlich auch Webpages. 
Jetzt war es mir zu wider, bei jeder kleinen Änderung des Web-Layouts 
den Code neu zu schreiben und im Microcontroller neu einzuspielen. Daher 
entschied ich mich irgendwann, das ganze in Javascript "auszulagern". 
Der Webcode im AVR ist so geschrieben, das die entscheidenten 
Bestandteile ein "body onload" und ein "div" Areal sind. Im "body 
onload" weden die Parameter an das Javascript übergeben und im "div" 
Areal, welches eine "ansprechbare" ID besitz, die Darstellung der Seite 
vorgenommen. Ganz wichtig ist natürlich noch die Einbindung des 
Javascripts im Header (<script type="text/javascript" 
src="http://ip_zu_server/avr.js"></script>;)

Einfaches Beispiel der <body> Zeile...
<body 
onload="avr_load('hz_view','d1:\'1\',d2:\'0\',d3:\'1\',d4:\'0\',a1:\'723 
\',a2:\'0\',a3:\'0\',ow1:\'31.3\',ow2:\'17.1\',ow3:\'20.1\'')">
Hier wird jetzt ein Parameter (s0_view) übergeben, damit ich im 
Javascript auch weiss, welcher Code genutzt werden soll. Des weiteren 
befinden sich dann einzelne Werte in dieser Zeile... etwas 
"menschlicher" geschrieben, sieht das Ganze so aus: 
("hz_view","d1:'1',d2:'0',d3:'1',d4:'0',a1:'723',a2:'0',a3:'0',ow1:'31.3 
',ow2:'17.1',ow3:'20.1'")  <- letzendlich besteht dieser Inhalt aus zwei 
Teilen. Diese Zeile wird im Javascript dann in ein Object gewandelt (im 
PHP würde man das evtl. als Array bezeichnen). Somit erhalten wir immer 
einen Namen und einen Wert (z.B. ow1 => 31.3)... somit können wir mit 
diesen Werten im Javascript jetzt alles mögliche anfangen und uns eine 
Darstellung aufbauen, die wir dann im entprechenden DIV-Container (<div 
id="view"></div>) ausgeben.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Beispiel: HTML-Code, den das AVR liefert...
1
<!DOCTYPE html>
2
<html lang="de">
3
<head>
4
<meta http-equiv="cache-control" content="no-cache">
5
<meta http-equiv="pragma" content="no-cache">
6
<meta charset="UTF-8">
7
<script type="text/javascript" src="http://ip_zum_externen_server/avr.js"></script>
8
</head>
9
<body onload="avr_load('hz_view','d1:\'1\',d2:\'0\',d3:\'1\',d4:\'0\',a1:\'723\',a2:\'0\',a3:\'0\',ow1:\'31.3\',ow2:\'17.1\',ow3:\'20.1\'')">
10
<div id="view"></div>
11
</body>
12
</html>

Beispiel: Javascript-Code (avr.js) zum Darstellen der Seite...
1
function avr_load(avr, werte) {
2
3
  werte = eval('({' + werte + '})');
4
5
  var str_out = '';
6
  if (avr == 'hz_view') {
7
    mytitle = 'HZ-AVR';
8
    str_out += 'AVR - Heizung\n\n';
9
    str_out += 'Digital IN: ' + werte['d1'] + '\nDigital IN: ' + werte['d2'] + '\nDigital IN: ' + werte['d3'] + '\nDigital IN: ' + werte['d4'] + '\n\n';
10
    str_out += 'ADC1: ' + werte['a1'] + '\nADC2: ' + werte['a2'] + '\nADC3: ' + werte['a3'] + '\n\n';
11
    str_out += 'Temp. OW 1: ' + werte['ow1'] + '\nTemp. OW 2: ' + werte['ow2'] + '\nTemp. OW 3: ' + werte['ow3'] + '\n\n';
12
  }
13
  document.getElementById('view').style.font = 'normal normal 9.5pt monospace';
14
  document.getElementById('view').style.whiteSpace = 'pre';
15
  document.getElementById('view').innerHTML = str_out;
16
}

-> Bild im Anhang "AVR_Seite1.png"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Duch den Javascript-Code sind die Möglichkeiten "fast" unbegrenz und 
auch JEDERZEIT änderbar! Darüber hinaus ist es auch möglich, 
Setup-Seiten darzustellen, also Seiten, in denen im AVR einige Werte 
geändert werden müssen.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Beispiel: HTML-Code, den das AVR liefert (Setup-Seite)...
1
<!DOCTYPE html>
2
<html lang="de">
3
<head>
4
<meta http-equiv="cache-control" content="no-cache">
5
<meta http-equiv="pragma" content="no-cache">
6
<meta charset="UTF-8">
7
<script type="text/javascript" src="http://ip_zum_externen_server/avr.js"></script>
8
</head>
9
<body onload="avr_load('hz_setup','INVA2:10')">
10
<div id="view"></div>
11
</body>
12
</html>

Beispiel: Javascript-Code (avr.js) zum Darstellen der Seite...
1
function avr_load(avr, werte) {
2
  werte = eval('({' + werte + '})');
3
  var str_out = '';
4
  if (avr == 'hz_setup') {
5
    var inva_name = 'INVA2';
6
    var adc_count = werte[inva_name];
7
    str_out += 'Hier wird der Parameter &quot;' + inva_name + '&quot; eingestellt\n\n';
8
    var counts = [0,1,10,20,40,50,60];
9
    str_out += '<select size="1" id="' + inva_name + '">';
10
    for(var key in counts) {
11
      var value = ('0' + counts[key]).slice(-2);
12
      if (adc_count == counts[key]) {
13
        str_out += '<option value="' + value + '" selected>' + counts[key] + '</option>';
14
      }
15
      else {
16
        str_out += '<option value="' + value + '">' + counts[key] + '</option>';
17
      }
18
    }
19
    str_out += '</select>';
20
    str_out += '&nbsp;<button onclick="send_post(\'' + inva_name + '\')">Setzen</button>';
21
  }
22
  document.getElementById('view').style.font = 'normal normal 9.5pt monospace';
23
  document.getElementById('view').style.whiteSpace = 'pre';
24
  document.getElementById('view').innerHTML = str_out;
25
}
26
function send_post(id) {
27
  var werte = new Object();
28
  werte[id] = document.getElementById(id).value;
29
  werte['SUB'] = 'ok';
30
  var userform = document.createElement('form');
31
  userform.method = 'post';
32
  for(var key in werte) {
33
    if(werte.hasOwnProperty(key)) {
34
      var hiddenField = document.createElement('input');
35
      hiddenField.type = 'hidden';
36
      hiddenField.name = key;
37
      hiddenField.value = werte[key];
38
      userform.appendChild(hiddenField);
39
    }
40
  }
41
  document.body.appendChild(userform);
42
  userform.submit();
43
  return;
44
}

-> Bild im Anhang "AVR_Seite2.png"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Meiner Meinung nach, hat diese Art der Darstellung einer Webpage vom AVR 
einige entscheidende Vorteile...
1. spar ich mir unnötigen Code im Microcontroller
2. wird der AVR beim darstellen der Seite entlastet, da hier weniger 
Daten geliefert werden müssen
3. Javascript wird IMMER Client-Seitig ausgeführt, also übernimmt die 
eigentliche Berechnung der Werte und Darstellung der Seite der Client 
(Webbrowser)
4. ich bin damit absolut flexibel und kann die Seite jederzeit anpassen, 
ohne auch nur den Code im AVR "anzufassen"



So... möglicherweise konnte ich damit einigen einen kleinen 
(um)denkanstoß geben. :-)

Gruß Sky

(Wie kann man denn hier Bilder wieder löschen??)

: Bearbeitet durch User
von Nuun. (Gast)


Lesenswert?

Naja,

so macht man's eigentlich nicht.

Wenn Du schon einen Weiteren Webserver am Start hast, der Content 
zuliefert, kann der Auch gleich die komplette Anwendung hosten. Deine 
AVR Boards bindest Du dann z.B. über REST-Services ein.
Das ergibt eine klare Architektur.

von Frank W. (skyifx)


Lesenswert?

Hi Nuun ;-)

Sicher kann ein externer Webserver die Werte z.B. als csv String vom AVR 
holen (mach ich auch so für Auswertungen), aber viele wollen direkt auf 
dem AVR eine Seite haben, vor allem, wenn es einige Parameter gibt, die 
dann dort eingestellt werden können/müssen... und sicher ließe sich auch 
das per POST vom externen Webserver schicken, aber direkt auf dem AVR 
ist es einfach angenehmer.

Schlussletzendlich ist es nur EINE der vielen Möglichkeiten, die es 
gibt. :-)

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Frank W. schrieb:
> Duch den Javacode

Javascript ist nicht Java.

von Frank W. (skyifx)


Lesenswert?

Ja... habe es geändert.

Ich dachte, das ginge aber aus der Überschrift eindeutig hervor. ;-)

von Stefan F. (Gast)


Lesenswert?

Kriegst du kein Problem mit Security Beschränkungen? Ich dachte, 
Webbrowser verweigern das Ausführen von Javascript, wenn es von einer 
anderen Domäne kommt.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Stefan U. schrieb:
> Ich dachte, Webbrowser verweigern das Ausführen von Javascript, wenn es
> von einer anderen Domäne kommt.

Schön wäre es, aber ... dann würde z.B. Google-Analytics und all' das 
Tracking nicht funktionieren.

von Frank W. (skyifx)


Lesenswert?

Hi Stefan

Das holen des Scriptes und das Ausführen des Codes in dieser Seite 
stellt keine Probleme dar.
Schwieriger wird es, wenn man einen "XMLHttpRequest" durch Javascript 
auf eine fremde Adresse machen will... das ist aber eine völlig andere 
Geschichte. ;-)

von Frank W. (skyifx)


Lesenswert?

Da hier auch ein Moderator anwesend ist...
Wie bekommt man denn angehängte Bilder wieder gelöscht??

Leider hatte das Forum vorhin einen "Hänger", somit konnte ich auch 
nicht genau schauen, wie die korrekte Formatierung der Code-Abschnitte 
erfolgen muss... ich hätte statt (code) lieber (pre) genommen. ;-)

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

Ich finde die Lösung auch eher unsinning.

Für mich gibt es zwei sinnvolle Möglichkeiten:
(a) Der AVR ist selbstständig. Dann muss er die gesamte Seite (mit 
Content) passend ausliefern. Wenn die Auswertung zu kompliziert ist, 
kann er die aber per Javascript gleich mitliefern und im Client-Browser 
erledigen lassen. Die Parametrierung ist per Webbrowser problemlos 
möglich.

(b) Der AVR ist nicht selbstständig. Dann liefert er keine fertige 
Seite, sondern die Rohdaten (oder einen Teil davon) per HTTP, z.B. als 
XML oder JSON. Auf dem PC/Smartphone läuft dann eine App (oder eine 
entsprechend präparierte HTML-Datei, auch mit Javascript), die diese 
Rohdaten so aufbereitet, wie du es gerne hättest. Die Parametrierung ist 
per Webbrowser problemlos möglich.

Den Ansatz, dass du eine HTML-Seite von deinem lokalen AVR aufrufst, die 
dich erstmal ins Internet leitet, um ein paar Werte anzuzeigen, passt 
allerdings wunderbar in die moderne vollüberwachte IoT-Welt. Moderne 
Leuchtmittel sind ja auch gerne dauerhaft mit einem chinesischen 
Webserver verbunden. Und wenn der Webserver weg ist, weil er gehackt 
wurde oder die Firma pleite ist, ist die Hausautomatisierung kaputt. Nee 
du, das Konzept ist in sich kaputt.

von Frank W. (skyifx)


Lesenswert?

Wenn Du das so siehst... ich dachte mit "ip_zum_externen_server" eher an 
einen Raspi oder Ähnliches, welchen die Meißten eh zu Hause (wohl 
gemerkt: zu Hause) noch am Laufen haben. Ich rede jetzt nicht davon, 
sein eigenes Netz nach aussen für jeden offen zu haben.

Der Content der Geschichte ist ja aber auch der, den AVR-Code nicht 
jedes mal ändern zu müssen, nur weil ich ein anderes Layout der Seite 
haben möchte oder weil ich die Werte der Parameter ändern möchte (siehe: 
var counts = [0,1,10,20,40,50,60];)... somit bin ich schnell mal mit 
Änderungen.

Aber gut sei es drum... jeder wie er es gern möchte. ;-)

: Bearbeitet durch User
von S. R. (svenska)


Lesenswert?

Frank W. schrieb:
> Wenn Du das so siehst... ich dachte mit "ip_zum_externen_server"
> eher an einen Raspi oder Ähnliches, welchen die Meißten eh zu
> Hause (wohl gemerkt: zu Hause) noch am Laufen haben.

Erstens: Warum muss ich für eine Heizungssteuerung via AVR einen 
zusätzlichen Raspi am Laufen haben?

Zweitens: Warum muss der AVR die IP-Adresse (oder den Hostnamen) des 
Raspis kennen? Ändert sich was am Netzwerk, musst du den AVR neu flashen 
- doof.

Drittens: Was hat der AVR mit der Darstellung zu tun? Der soll Daten 
liefern und Parameter entgegennehmen, mehr nicht. Der muss nicht wissen, 
wer die Daten darstellt.

> Der Content der Geschichte ist ja aber auch der, den AVR-Code nicht
> jedes mal ändern zu müssen, nur weil ich ein anderes Layout der Seite
> haben möchte oder weil ich die Werte der Parameter ändern möchte (siehe:
> var counts = [0,1,10,20,40,50,60];)... somit bin ich schnell mal mit
> Änderungen.

Auf dem Raspi läuft die Webseite, die die Daten vom AVR (oder sogar 
mehreren AVRs!) abfragt und wie gewünscht aufbereitet. Auf dem Raspi 
kannst du dein Layout schnell ändern und auch die Adresse des AVRs 
anpassen.

Und wenn du kurz darüber nachdenkst, dann stellst du fest, dass das 
eigentlich auch dein Endgerät machen kann - im Zeitalter des IoT wäre 
das dann eine App. Oder du hast auf deinem Computer eine HTML-Datei. 
Oder - wenn du 20 Computer hast - du hast die Datei trotzdem auf deinem 
Raspi. Dann kannst du deine Steuerungen sogar noch hinter eine 
Extra-Firewall legen.

Außerdem kann der AVR trotzdem eine einfache Webseite bereithalten, für 
den Fall dass dein Raspi gerade kaputt ist. Dann kannst du im Notfall 
trotzdem deine Heizung einschalten. Und wenn der AVR einfach JSON (oder 
XML) ausgibt, ist das ohnehin besser als dein handgeknüppeltes CSV.

Das sind alles praktische Vorteile, die deine Lösung nicht ohne weiteres 
bieten kann. Ja, sie funktioniert. Nein, das macht sie nicht zu einer 
guten Lösung.

von Chris R. (hownottobeseen)


Lesenswert?

Hi,

auf den Sinn- oder Unsinn deines Vorhabens möchte ich nicht näher 
eingehen. Deine Entscheidung und du musst damit glücklich werden ;)

Unabhängig davon: eval is evil. Wenn du JSON entpacken willst (das 
willst du glaube ich!?), verwende bitte die dafür vorgesehenen 
Funktionen.

Aber zum Thema: du suchst den Access-Control-Allow-Origin-Header.

Dieser muss von der abgerufenen Datei kommen - also die Datei, die du in 
deine angezeigte Website einbindest.

Wenn sich die Adresse deines Servers ändern kann, kommst du um den 
Header
1
Access-Control-Allow-Origin: *

wahrscheinlich nicht herum. Nicht schön, aber funktioniert.

HTH

Chris

von дампфтроль (Gast)


Lesenswert?

Ich hab auch mal einen Webserver auf einem AVR laufen gehabt. Mit 
statischer Seite, in einem externen Flash. Ich hab dazu ein AT45DB041D 
in einem SO8 Gehause ueber ein SPI angebunden. Der AVR konnte die Seite 
auch neu laden.
Variablen wurden per JSON gelesen und geschrieben. Allerdings waeren 
auch GET parameter drin gewesen.

Der AVR war natuerlich kein Mega8, sondern ein Mega324 oder Mega644

Die Schnittstelle zum Netzwerk war aber kein Ethernet sondern die 
serielle Schnittstalle.

von Frank W. (skyifx)


Lesenswert?

Für Alle, die jetzt weiter über Sinn oder Unsinn dieser Sache 
diskutieren wollen... diese hier dargestellte Lösung ist nur EINE 
Möglichkeit, eine Webseite auf einem AVR variabel über externen Code 
anzuzeigen, ohne den AVR-Code selbst jedes mal ändern zu müssen!!

Mir geht es dabei nicht um irgendwelche Automatisierungsgeschichten, 
oder darum, wie mein Homeserver mit meinem AVR kommuniziert und in 
welcher Form die beiden dann irgendwelche Daten austauschen noch wie 
diese dann in einer entsprechenden GUI aufbereit dargestellt weden!

Ich habe schon genug SBC's und AVR's programmiert... von automatisierter 
Raumbeheizung über PV-Überwachung bis hin zur kompletten 
Heizungssteuerung, aber das ist hier nicht Gegenstand der Sache!

Ich hoffe, ich habe mich jetzt soweit verständlich ausgedrückt???

: Bearbeitet durch User
von Pandur S. (jetztnicht)


Lesenswert?

Ja, sagte ich doch. Die Seite extern zu haben ist keine gute Idee.
Wenn man die Seite, als Javascript extern lagert, ist das System 
engverzahnt und nicht mehr transportiert bar, und auch nicht wartbar.
Besser ist es die Seite in einem externen Flash lagern, und dem 
Controller die Moeglichkeit geben die Seite auch neu in dieses Flash zu 
schreiben.

von S. R. (svenska)


Lesenswert?

Oder umgekehrt nicht den AVR auf die externe Seite zu linken, sondern 
eine externe Seite auf den AVR zu linken.

von Frank W. (skyifx)


Lesenswert?

Sollte ich eine Heimautomatisierung aufbauen mit AVR's, Sensoren, etc. 
und evtl. als Zentrale einen SBC, dann ist immer alles eng miteinander 
verzahnt! Und wenn jemand solch ein Netz aufbaut, kommt auch niemand auf 
die Idee, mal eben den Adressbereich seines Netzwerkes zu ändern (wie 
oben von jemandem bemängelt), denn dann fängt man an, alle Geräte im 
Netzwerk neu einzustellen, da man in den seltensten Fällen mit DHCP 
arbeitet.

von Pandur S. (jetztnicht)


Lesenswert?

Ich wuerde keine zu enge Verzahnung wollen. Es geht nicht um morgen. 
Sondern um in 5, 10 Jahren. Steigst du dann noch durch ? Dann moechtest 
du moeglichst unabhaengige Funktionalitaeten haben. Zudem solltest du 
beachten, dass du dann nicht mehr unendlich viel Zeit dafuer hat. Eine 
fachfremde Person, wie zB die Frau, hat sehr schnell kein Verstaendnis 
mehr weshalb etwas nicht geht. Eigentlich betraegt die Goodwill Spanne 
dann nur noch 5 Minuten, wenn du lieb bist..
Und du meochtest dann erst mal den alten Rechner, der das Projekt drauf 
hat zum Laufen kriegen, musst ihn aber erst neu Aufsetzen. Leider geht 
das Licht nicht denn das haengt auch am Haussystem... Du, willst dann 
etwas mit der Stirnlampe am Rechner sitzen, mit der Frau hintendran ?

Ist aber egal, mach einfach.

: Bearbeitet durch User
von Lidwig (Gast)


Lesenswert?

Oh D. schrieb:

> Du, willst dann etwas mit der Stirnlampe am Rechner sitzen, mit der Frau
> hintendran ?

Was ist denn das für ein Müll?

Was soll die Frauenfeindlichkeit in deinem "Beitrag"?

von Stefan F. (Gast)


Lesenswert?

Ersetze Frau durch beliebige Familienangehörige oder Nachmieter.

Es geht einfach darum, dass auch andere Leute mit solchen Installationen 
zurecht kommen sollten. Wenn ich wegziehe oder sterbe, soll irgendein 
Elektriker die Anlage weiter pflegen können.

von Pandur S. (jetztnicht)


Lesenswert?

> Was ist denn das für ein Müll?
> Was soll die Frauenfeindlichkeit in deinem "Beitrag"?

Das ist Realismus, guter Mann, ich kenn's.

Kinder wuerde nie an der Arbeit vom Vater zweifeln.

Ein Nachmieter wuerd wiederkommen, wenn's wieder laeuft.
Verzug und Hotel zu deinen Lasten.

Ein Hausmann wuerde in Bett warten gehen, waehrend
dieser Zeit waere er von der Hausarbeit entschuldigt.

: Bearbeitet durch User
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
Noch kein Account? Hier anmelden.