Jython

9. Webserver


Auf dem zusätzlich eingebauten LinkUp (mit dem ESP32 als Coprozessor) kann ein Webserver und sogar ein eigener Accesspoint eingerichtet werden.  Loggt sich der LinkUp über das  WLAN bei einem Accesspoint ein, der mit dem Internet verbunden ist, wird der  micro:bit zu einem vernetzen IoT-Gerät, das beispielsweise Messdaten in einer Clound speichern oder von einem Smartphone Steuerbefehle erhalten kann.

Die Kommunikation zwischen dem micro:bit und dem ESP32 erfolgt mit I2C, wobei der ESP32 sich wie ein I2C-Slave verhält. Die notwendigen Funktionen werden über das Moduls linkup zur Verfügung gestellt.

Für die WLAN-Kommunikation gibt es grundsätzliche zwei Verbindungsmöglichkeiten:

Verwendung eines vorhandenen Accesspoints
Der mbRobot und die anderen Geräte (Smartphone, PC) loggen sich auf dem gleichen Accesspoint (mit SSID, Password) ein


Der mbRobot als Accesspoint

Auf dem mbRobot wird eine Accesspoint mit eigner SSID (und eventuell einem Passwort) gestartet und die anderen Geräte loggen sich über WLAN auf diesem Accesspoint ein.

 

Beispiel 1: Webserver einrichten und eine statische Webseite zur Verfügung stellen

Schritt 1: Webseite hochladen
Mit der Ausführung des untenstehenden Programms SaveHTMLWeb1.py auf dem micro:bit wird der HTML-Code einer einfachen Webseite auf den LinkUp hochgeladen und dort gespeichert. Dazu verwendet man den Befehl saveHTML() aus dem Modul linkup.

# SaveHTMLWeb1.py
from linkup import *

html = """<!DOCTYPE html>
<html>
  <head> 
     <meta name="viewport" content="width=device-width, initial-scale=1">
   </head>
   <body> 
     <h2>Welcome to the mbRobot</h2>
     <p>My first homepage</p>     
  </body>
</html>
"""

print("Saving HTML...")
saveHTML(html)
print("Done")
► In Zwischenablage kopieren  

Schritt 2: Webserver starten
Je nachdem, ob man die Verbindung über einen bestehenden Accesspoint oder einen Accesspoint auf dem Roboter erstellt, wird auf dem micro:bit das Programm WebServer1.py oder WebServer1a.py ausgeführt. Die beiden Programme unterscheiden sich nur in zwei Zeilen:

Im ersten Programm muss man die SSID und Passwort des bestehenden Accesspoint im Programm angeben. Damit man mit einem Smartphone- bzw. PC-Browser zugreifen kann, muss man die IP Adresse, die der mbRobot vom Accesspoint erhält, kennen. Diese wird mit der Zeile ipAdress = connectAP() ermittelt und mit der nächten Zeile auf dem LED-Display des micro:.bit mit Laufschrift ausgeschrieben.

Beim zweiten Programm erzeugt man mit dem Befehl createAP() einen Accesspoint mit der SSID mbRobot und Passwort leer. Für eine Verbindung mit dem Webserver, muss sich ein Gerät auf dieser SSID einloggen und dann im Browser die fixe URL 192.168.4.1 verwenden.

Der Webserver wird gestartet und kann die Client-HTTP-Requests, die mit Wahlt der IP-Adresse im Browser des Smartphones ausgelöst werden, empfangen. Jeder Requests wird auf dem micro:bit als eine Ereignis aufgefasst, und das System ruft die Callbackfunktion onRequest() auf, welche die Information des Requests enthält (die IP Adresse des Clients, die eingegebene URL-Ressource (filename) und eventuelle URL-Parameter.

Da hier onRequest() ohne weitere Aktionen mit return zurückkehrt, wird nur die vorher gespeicherte HTML-Seite an den Client zurückgesendet.

Verbindung über bestehenden Accesspoint   Accesspoint auf dem mbRobot
# WebServer1.py
from linkup import *
from mbrobot import *

def onRequest(clientIP, filename, params):   
    return

ipAddress = connectAP(ssid="xx", password="yy")
display.scroll(ipAddress, wait = False)
startHTTPServer(onRequest) 
► In Zwischenablage kopieren
 
# WebServer1a.py
from linkup import *
from mbrobot import *

def onRequest(clientIP, filename, params):   
    return

createAP(ssid="mbRobot", password="")

startHTTPServer(onRequest) 
► In Zwischenablage kopieren

 

Schritt 3: Webseite anzeigen
Im Browser die IP-Adresse, die auf dem LED-Display angezeigt wird eingeben (z.B. 192.168.0.24).

 

 


Im Browser die IP-Adresse 192.168.4.1 eingeben.


Erklärungen zum Programmcode:

viewport: Die Webseite wird an die Device-Breite angepasst. Damit wird sie auch auf einem Smartphone richtig angezeigt
def onRequest(): Callbackfunktion. Definiert, wie der mbRobot auf die HTTP-Requests reagieren soll. Hier wird nur eine statische Webseite angezeigt

IPAdress: Ermittelt die vom Accesspoint zugeteilte IP-Adresse

createAP(): Erzeugt einen Accesspoint auf dem ESP32 Microkontroller des Roboters
startHTTPServer: Startet den Webserver. Der Aufruf ist blockierend, d.h. der LinkUp muss für einen neuen Programm-Lauf resettet (oder aus-/eingeschaltet) werden

 

Beispiel 2: Interaktive Webseite zur Verfügung stellen
Die Webseite, die auf dem mbRobot-Webserver zur Verfügung gestellt wird, enthält zwei Links. Mit Klick auf diese Links kann man dem Roboter ferngesteuert Befehle erteilen. Der Webserver funktioniert eventgesteuert mit der Callbackfunktion onRequest(clientIP, filename, params), die beim eingehenden GET-Request aufgerufen wird. Über den Parameter fiiename wird die Benutzeraktion, hier das Klicken eines Links, zurückgemeldet. Je nachdem, welcher Link gedrückt wurde, werden die Melodien JUMP_UP bzw. JUNP_DOWN abgespielt.

Mit dem ersten Programm SaveHTMLWeb2.py wird der HTML-Code hochgeladen.

# SaveHTMLWeb2.py
from linkup import *

html = """<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body> 
    <h2>Welcome to the mbRobot</H2>
     <p><a href="jump_up">Play JUMP_UP </a></p>
     <p><a href="jump_down">Play JUMP_DOWN</a></p>
</body>
</html>
"""   

print("Saving HTML...")
saveHTML(html)
► In Zwischenablage kopieren
 

Programm für für den mbRobot:

# WebServer2.py
from linkup import *
from mbrobot import *
from music import *

def onRequest(clientIP, filename, params):
    if filename == "/jump_up":
        play(JUMP_UP)      
    elif filename == "/jump_down":
        play(JUMP_DOWN)

ipAddress = connectAP(ssid = "xxx", password = "yyy")
display.scroll(ipAddress, wait = False)
startHTTPServer(onRequest)  
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:

filename == "/jump_up": Der Requestparameter filename erhält den Wert jump_up, wenn der Benutzer auf den Link JUMP_UP klickt
from music import * Das Modul music muss importiert werden. Einige Sonst sind integriert und können direkt verwendet werden



Beispiel 3:
Mit einer interaktiven Webseite die LEDs des mbRobot ferngesteuert ein- und ausschalten

   

Der Webserver funktioniert eventgesteuert mit der Callbackfunktion onRequest(clientIP, filename, params), die beim eingehenden GET-Request aufgerufen wird. Die Benutzerinteraktion wird über den Parameter filename zurückgemeldet, der die Werte "on" bzw. "off" annehmen kann. Man kann in der URL-Adresszeile des Browsers beobachten, wie die Werte ON/OFF als Request-Parameter gesendet werden. Im HTML-Code könnte man die Werte ON/OFF mit gewöhnlichen Links übergeben, eleganter ist es aber mit HTML-Buttons.

So wie in den vorhergehenden Beispielen muss zuerst der HTML-Code auf dem Server gespeichert werden.

# SaveHTMLWeb3.py
from linkup import *

html = """<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body> 
    <h2>Welcome to the mbRobot</H2>
    <button style="font-size:22px; height:50px;width:130px" 
            onclick="window.location.href='on'">Light ON</button>&nbsp;&nbsp;
    <button style="font-size:22px; height:50px;width:130px" 
            onclick="window.location.href='off'">Light OFF</button>
</body>
</html>
"""   

print("Saving HTML...")
saveHTML(html)
print("Done")
► In Zwischenablage kopieren
 

 

Die Callbackfunktion onRequest() im Programm WebServer3.py, das danach ausgeführt wird, legt die Aktion nach dem Klick der Buttons fest.

# WebServer3.py
from linkup import *
from mbrobot import *

def onRequest(clientIP, filename, params):
    if filename == "/on":
        ledLeft.write_digital(1)
        ledRight.write_digital(1)
    elif filename == "/off":
        ledLeft.write_digital(0)
        ledRight.write_digital(0)

print("Waiting for LinkUp...")
wait(10)
ipAddress = connectAP(ssid = "xx", password = "yy")
display.scroll(ipAddress, wait = False)
startHTTPServer(onRequest)
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:

if filename == "/on": Wenn der Parameter filename "/on" ist, werden beide LEDs eingeschaltet


Beispiel 4: Roboter mit Smartphone steuern

Unter der Verwendung des Webservers und Accesspoints auf dem mbRobot ist es einfach, eine Fernsteuerung zu realisieren, ohne eine spezielle Smartphone-App zu installieren. Dazu wird auf dem mbRobot wird zuerst ein Accesspoint und dann ein Webserver gestartet den man mit der URL 191.168.4.1 erreicht Die Webseite zeigt 5 Buttons: forward, backward, left, right und stop zur Steuerung des Roboters.

Im HTML-Code wird ein Formular mit Submit-Buttons und eine Tabelle für die Positionierung der Buttons verwendet. Die name und value-Werte gelangen als HTTP-Request-Parameter an die Callbackfunktion onRequest(), und zwar in Form eines Dictionary {key:value,...}.

# SaveHTMLWeb4.py (RemoteRover)
from linkup import *

html = """<!DOCTYPE html>
<html>
  <head> <title>MicroBit Rover</title> 
  <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body> 
    <h1>MicroBit Rover</h1>
    <form method="get">
    <table>
    <tr>
      <td></td>
      <td><input type="submit" style="font-size:22px; height:50px; 
           width:110px" name="btn" value="Forward"/></td>
      <td></td>
    </tr>
    <tr>
      <td><input type="submit" style="font-size:22px; height:50px;
           width:110px" name="btn" value="Left"/></td>
      <td><input type="submit" style="font-size:22px; height:50px;
           width:110px" name="btn" value="Stop"/></td>
      <td><input type="submit" style="font-size:22px; height:50px;
           width:110px" name="btn" value="Right"/></td>
    </tr>
    <tr>
      <td></td>
      <td><input type="submit" style="font-size:22px; height:50px;
           width:110px" name="btn" value="Back"/></td>
      <td></td>
    </tr>
    </table>
    </form><br>
    Current state: %s<br>
  </body>
</html>
"""

print("Saving HTML...")
saveHTML(html)
print("Done")
► In Zwischenablage kopieren
 

In der Callbackfunktion wird der Parameter params verwendet. Es handelt sich um ein Dictionary mit key-value-Werten. Der aktuelle Wert des Keys "btn" wird in der Variablen state gespeichert. Es ist ein typisches Beispiel der Zustandsprogrammierung. Der Roboter wird dadurch jeweils in einen Bewegungszustand versetzt, der andauert, bis er mit einem erneuten Request geändert wird.

# WebServerWeb4.py (RemoteRoverAP)
from linkup import *
from mbrobot import *

def onRequest(clientIP, filename, params):
    if 'btn' in params:
        state = params['btn']
        if state == 'Left':
            leftArc(10) 
        elif state == 'Right':
            rightArc(10) 
        elif state == 'Forward':
            forward()    
        elif state == 'Back':
            backward()    
        elif state == 'Stop':
            stop()    
    else:
        state = 'Stop' # also with favicon request
    display.show(state[0])
    return [state]

stop()
createAP(ssid = "mbRobot", password = "")
startHTTPServer(onRequest)
      
                
► In Zwischenablage kopieren
 

 

Erklärungen zum Programmcode:

display.show(state[0]) : Der erste Buchstabe von state wird auf dem LED-Display angezeigt
return [state] : Der Rückgabewert ist hier eine Liste mit Werten, die als Formatparameter der gespiecherten bei Current State: %s eingesetzt werden