Materialien zum Unterricht

RGB-LED über eine Website ansteuern

Bistabiler Button

Ähnlich wie auf der Seite bistabiler Schalter beim Calliope mini wird ein Button (monostabil) genutzt, um einen runden Bereich abwechselnd in Schwarz oder Grün einzufärben (bistabil).

Im Schript-Teil wird eine Variable led_an auf 0 gesetzt und dann bei jedem Klick auf den Button in den anderen Zustand (0 oder 1) gesetzt. Gleichzeitig wird die Hintergrundfarbe des Bereichens kreis geändert.

Der HTML-Code ersetzt den Code in der bisherigen index.html. Sie wird dann wieder auf den ESP32 geladen und dann kann man nach dem Aufruf der Seite über den Button die LED ein- und ausschalten.

Ist das nicht toll?



<!DOCTYPE html>
<html>
  <head>
    <title>LED</title>
    <style>
      #kreis {
        width: 50px;
        height: 50px;
        border-radius: 50%;
        background-color:#000;
      }
     .button {
        width: 100px;
        height: 100px;
    </style>
    </head>
    <body>
      <h1>LED-Steuerung</h1>
       <button class="button" onclick="farbe_aendern()">Klick mich!</button>
       <div id="kreis">
       </div>

     <script>
      let led_an=0;
      const kreis = document.getElementById("kreis");
      function farbe_aendern() {
        if (led_an==0) {
          kreis.style.backgroundColor="#0f0";
          led_an=1;
        } else {
          kreis.style.backgroundColor="#000";
          led_an=0;
        }
     }
    </script>
  </body>
</html>:

Klick auf Button zum Webserver senden

Die Website soll als nächstes an den Webserver melden, wenn der Button gedrückt wurde. Wenn man auf den Button "Klick mich!" klickt, wird eine GET-Anfrage an die Webseite gesendet, also an die Adresse "/", also die Startseite. Dabei wird ein Parameter namens "button" mit dem Wert "pressed" übermittelt. Das bedeutet, dass die Webseite erkennen kann, dass der Button gedrückt wurde, und entsprechend darauf reagieren kann. 


<form method="get" action="/">
    <button type="submit" class="button" name="button" value="pressed" onClick="farbe_aendern()">Klick mich!</button>
</form>

Im Python-Programm wird in den empfangenen Daten r nach  'GET /?button=pressed' gesucht und eine entsprechende Meldung angezeigt.


print('Empfangene Daten:', r.decode()) #und in einer lesbaren Form angezeigt
    if 'GET /?button=pressed' in r:
        print("Button wurde gedrückt!")

In Thonny sollte jetzt nach jedem Klick auf den Button eine solche Meldung erscheinen. In Zeile 2 erkennt man die Daten, die von der Seite gesendet worden. Es wird der Wert des Attributs name des Button und dahinter der Wert des Attributs value gesendet: button=pressed.

Das wird gleich ausgenutzt, um den Inhalt der Variablen led_an zu übertragen.

Status der LED senden

Es soll nun der Zustand der Variablen led_an an den Webserver übermittelt werden. Dazu wird der name des Button in led_an geändert und dem Button zum direkten ansprechen ein Attribut id gegeben.


<form method="get" action="/">
   <button type="submit" class="button" id="led_an" name="led_an" onClick="farbe_aendern()">Klick mich!</button>
</form>

Das Attribut value wird mit dem Inhalt der Variablen gefüllt. Diese Programmzeile muss in der Funktion nach der Entscheidung eingefügt werden.


document.getElementById('led_an').setAttribute("value", led_an);

Beobachtet man die Meldung des Clients an den Server und die Reaktion der "LED" auf der Website, stellt man fest, das das ganz und gar nicht unseren Erwartungen entspricht.

Beim Server kommt als Rückmeldung immer nur eine 1 an (?led_an=1) und die LED auf der Website ist immer aus. Was ist der Grund?

Beim Aufruf der Seite ist led_an gleich 0, die LED ist schwarz. Beim Klick auf den Button wird die Variable auf 1 gesetzt, die LED eingeschaltet, der Wert von led_an in den Button geschrieben und die Daten an den Server geschickt. Bis hier hin ist alles prima.

Die Reaktion des Webservers auf den Empfang der Daten ist aber für unsere Vorstellungen nicht so gut: er schickt die komplette index.html an den Client, der sie neu anzeigt. Damit ist die LED wieder aus und die Variable led_an auf 0 gesetzt. Alles fängt von vor an, der Client kann sich nichts merken!

Um das Problem zu lösen, muss der Zustand der LED, also der Inhalt der Variablen led_an irgendwo gespeichert werden, wo der Client herankommt. Wir verwenden von den verschiedenen Möglichkeiten hier die Web Storage API, da sie sehr einfach zu handhaben ist.

Aufgaben:

  • Informiere dich über die Web Storage API.
  • Erkläre jede Zeile des Programms.

Wenn alles richtig läuft, wechselt bei jedem Klick auf den Button in der Thonny-Anzeige der Wert hinter led zwischen 0 und 1.


<script>
   const kreis = document.getElementById("kreis");
   if (sessionStorage.getItem('led')==null) {
     sessionStorage.setItem('led',0);
     led_an=0;
   } else {
     led_an=sessionStorage.getItem('led');
     if (led_an==0) {
         kreis.style.backgroundColor="#000";
     } else {
         kreis.style.backgroundColor="#0f0";
     }
   }
   function farbe_aendern() {
     if (led_an==0) {
       led_an=1;
     } else {
       led_an=0;
     }
     document.getElementById('led_an').setAttribute("value", led_an);
     sessionStorage.setItem('led', led_an);
   }
	</script>

Die LED ein- und ausschalten

Jetzt muss der Webserver noch erkennen, ob hinter led_an eine 0 oder eine 1 steht und die LED in einer Farbe ein- oder ausschalten. Dazu wird hier eine sehr einfache Variante gewählt. Später kommen zur detailierten Suche reguläre Ausdrücke zum Einsatz.

Das Schalten der LED wurde in den Vorbereitungen beschrieben. Welche Farbe benutzt wird, ist egal. Hier ist es Blau.


if 'GET /?led_an=1' in r:
        print("An")
        led_blau.value(0)
    else:
        print("Aus")
        led_blau.value(1)

zurück