Jython
Deutsch   English 

9. Web Server


On the integrated LinkUp (with a ESP32 as coprocessor) a Web server and even an WLAN access point can be set up.  If the LinkUp connects to an external access point that is linked to the Internet, the micro:bit becomes a fully functional networked IoT device. As such it can store measurement data in a cloud or receive control commands from a smartphone.

The communication between the micro:bit and the ESP32 is accomplished with I2C, whereby the ESP32 behaves like an I2C- slave. The necessary functions are provided in the module linkup.

There are two basic connection options for WLAN communication:

Use of an existing access point
The mbRobot and the other devices (Smartphone, PC) log in on the same access point (with SSID, password).


The mbRobot as access point

On the mbRobot, an access point with its own SSID (and possibly a password) is started and the other devices log in via WLAN on this access point.

 

Example 1: Setting up a web server and providing a static Web page

Step 1: Upload Web page
By executing the following program on micro:bit, the content of a simple web page is uploaded to the LinkUp and stored there.

# 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")
► Copy to clipboard  

Step 2: Start the Web server
Depending on whether the connection is established via an existing access point or an access point on the robot, the program WebServer1.py or WebServer1a.py is executed on the micro:bit. The two programs only differ in two lines:

In WebServer1.py you must enter the SSID and password of the existing access point. In order to access the server with a smartphone or PC browser, you have to know the IP address the mbRobot gets (with DHCP) from the access point. The address is returned from connectAP() and shown on the LED display using  scrolling text
WebServer2.py creates an access point with the SSID mbRobot and an empty password. For a connection with the Web server, a device must use this SSID and then enter the predefined URL 192.168.4.1 in the browser.

After the Web server is started, and it is ready to receive HTTP GET requests on port 80 from any client. Each request is considered as an event and the system automatically invokes the callback function onRequest(), which contains the information of the request (client's IP address, URL resource (filename) and possible URL parameters).
Since in these programs onRequest() returns no values, just the previously saved HTML page is sent back to the client.

Link via external  access point:   Access point running on 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) 
► Copy to clipboard
 
# WebServer1a.py
from linkup import *
from mbrobot import *

def onRequest(clientIP, filename, params):   
    return

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

startHTTPServer(onRequest) 
► Copy to clipboard

 

Step 3: Show website
In the browser, enter the IP address shown on the LED display (e.g. 192.168.0.24).

 

 


In the browser enter IP address 192.168.4.1.


Explanations of the program code:

viewport: The web page is adapted to the device width, for instance  for a smartphone
def onRequest():Callback function. Defines how the mbRobot should react to HTTP requests. A simple static web page is returned to the client here
createAP(): Creates an access point on the ESP32 microcontroller
startHTTPServer: Starts the Web server. The request is blocking, i.e. the LinkUp must be reset (or switched off/on) for a new program run.

 

Example 2: : Interactive website
The website provided on the mbRobot web server contains two links. By clicking on these links the information sent to the Web server is used to control the robot. The incoming GET request triggers the callback function onRequest(clientIP, filename, params) and the parameter filename contains the href parameter of the HTML <a> tag. Depending on which link was pressed, the melodies JUMP_UP or JUMP_DOWN are played.
SaveHTMLWeb2.py uploads the HTML code.

# 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)
► Copy to clipboard
 

WebServer2.py starts the Web server:

# 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)  
► Copy to clipboard
 

 

Explanations of the program code:

filename == "/jump_up": The parameter filename contains the value jump_up when the user clicks on the link JUMP_UP



Example 3:
Using a interactive website to remotely switch mbRobot LEDs on and off

   

As shown in the previous example, the callback function onRequest(clientIP, filename, params) is triggered by an incoming GET requests. Instead of a HTML <a> tag, buttons are used here that provides a more pleasant view. The parameter filename contains the values "on" or "off", depending on which button was clicked.

As in the previous examples, the HTML code must first be stored on the server.

# 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")
► Copy to clipboard
 

 

WebServer3.py starts the Web server:

# 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...")
ipAddress = connectAP(ssid = "xx", password = "yy")
display.scroll(ipAddress, wait = False)
startHTTPServer(onRequest)
► Copy to clipboard
 

 

Explanations of the program code:

if filename == "/on": If the parameter filename is "/on", both LEDs are switched on


Example 4: Remote control robots with a smartphone

Using the Web server and access points on the mbRobot, it is easy to implement remote control without writing or using a special smartphone app. To do this, the mbRobot first starts an access point and then a Web server which can be reached via the URL 191.168.4.1. The website shows 5 buttons: forward, backward, left, right and stop to control the robot.

The HTML code uses a form containing submit buttons and a table for positioning the buttons. The name and value values are sent as HTTP GET request parameters.

To give a feedback to the user, the HTML page contains a format parameter %s (see "Current state:") This will to be replaced with a string by the Web server. To achieve this, the callback onRequest() must return a list with the values of all  format parameters.

Again, the HTML code must first be stored on the ESP.

# 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")
► Copy to clipboard
 

The HTML form element contains input fields with name and value. When the form is submitted, the information is packed into the URL as ?name=value pairs and the callback onRequest(clientIP, filename, params) is triggered. The information can be retrieved from params as dictionary key-value pairs
The program uses state programming. On reception of a command, the robot is put into a certain state of motion, which remains until it is changed with a new command.

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

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

stop()
createAP(ssid = "mbRobot", password = "")
startHTTPServer(onRequest)
      
                
► Copy to clipboard
 

 

Explanations of the program code:

display.show(state[0]) : The first letter of the state is shown on the LED display.
return [state] : The return value is a list of values which are used as format parameters (here only one value at Current State: %s)