Skip to content
/ uWeb Public

super simple web server for wifi-based micro-controllers running MicroPython

License

Notifications You must be signed in to change notification settings

petabite/uWeb

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

36 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

μWeb (a.k.a microWeb)

Super simple web server for wifi-based micro-controllers that support MicroPython (ie. NodeMCU ESP8266)

Table of Contents

Features

  • Simple URL routing to actions
  • Render templates with layouts to the client
  • Super simple HTML templating
  • HTTP request parsing
  • Send files and json to client
  • Parse headers and body from client
  • Optional asynchronous version (based on uasyncio)

Changelog

uWeb

v1.1 - 5/19/20

  • layout rendering
  • send appropriate Content-Type headers when sending files
  • version attribute

v1.0 - 7/6/19

  • First release!

uWeb-uasyncio

v1.0 - 5/20/20

  • First release!

Requirements

  • Microcontroller that supports micropython(such as NodeMCU ESP8266)
  • USB cable(possibly)
  • Wi-Fi connection

MicroPython Libraries:

  • ujson
  • usocket
  • uasyncio(for uasyncio version)

μWeb vs. μWeb-uasyncio

This repo contains both uWeb and uWeb-uasyncio. Both versions have their own use cases

;-; μWeb μWeb-uasyncio
concurrency synchronous, uses usocket(blocking sockets) asynchronous, uses uasyncio(non-blocking sockets)
when to use when you need a simple web server to serve HTML or send data when endpoints call functions that take time to run and having the server still be able to respond to requests is important
use cases simple API that serves static files or sends some JSON data(concurrency not required) app where a request to an endpoint invokes a function that sleeps for some time but still needs to respond to incoming requests

TLDR; uWeb can be used when concurrency is not important. uWeb-uasyncio can be used when concurrency is important

Installation

  1. Install micropython on your board of choice(ESP8266 installation)
  2. Copy the μWeb project files to your board over the web using MicroPython's WebREPL or through a serial connection with Adafruit's ampy
    • chose either uWeb.py or uWeb_uasyncio.py depending on your needs
  3. If your version of MicroPython does not come with ujson, usocket or uasyncio(if needed) precompiled, copy them from micropython-lib
  4. Along with the μWeb project files, make sure you have a boot.py for the initial setup of your board(ie: connecting to wifi) and main.py for the main μWeb code.
  5. Power up your board and enjoy!

No MicroPython board? No problem!

You can run uWeb with the MicroPython unix port

  1. Build the unix MicroPython port (here) or get the prebuild executable (here)
  2. Run micropython uWeb_example.py or micropython uWeb_uasyncio_example.py in your console.

Quick Start

Example application using μWeb

from uWeb import uWeb, loadJSON

server = uWeb("0.0.0.0", 8000)  #init uWeb object

def home(): #render HTML page
    vars = {
        'name': 'MicroPython',
        'answer': (1+1)
    }
    server.render('content.html', variables=vars)

def header(): #send headers to client
    server.sendStatus(server.OK)
    server.sendHeaders({
        'header1': 'one',
        'header2': 'two',
        'header3': 'three',
    })

def post(): #print JSON body from client
    print(loadJSON(server.request_body).items())

def jsonn(): #send JSON to client
    server.sendJSON({'status':'okkk'})

#configure routes
server.routes(({
    (uWeb.GET, "/"): home,
    (uWeb.POST, "/post"): post,
    (uWeb.GET, "/json"): jsonn,
    (uWeb.GET, "/header"): header
}))

#start server
server.start()

Example application using μWeb-uasyncio

import uasyncio
from uWeb_uasyncio import uWeb_uasyncio as uWeb
from uWeb_uasyncio import loadJSON

server = uWeb("0.0.0.0", 8000)  #init uWeb object

def home(): #render HTML page
    vars = {
        'name': 'MicroPython',
        'answer': (1+1)
    }
    await server.render('content.html', variables=vars)

def printTen(): # counts to ten while still accepting incoming requests
    await server.sendStatus(server.OK)
    for i in range(10):
        print(i)
        await uasyncio.sleep(1)

def header(): #send headers to client
    await server.sendStatus(server.OK)
    await server.sendHeaders({
        'header1': 'one',
        'header2': 'two',
        'header3': 'three',
    })

def post(): #print JSON body from client
    print('Payload: ', loadJSON(server.request_body))
    await uasyncio.sleep(0)

def jsonn(): #send JSON to client
    await server.sendJSON({'status':'okkk'})

#configure routes
server.routes(({
    (uWeb.GET, "/"): home,
    (uWeb.GET, "/ten"): printTen,
    (uWeb.POST, "/post"): post,
    (uWeb.GET, "/json"): jsonn,
    (uWeb.GET, "/header"): header
}))

#start server
server.start()

Using uWeb-uasyncio

  • when configuring routes, endpoint functions are treated as asynchronous so they must have an await statement in its body
  • uWeb class methods can be preceded with await
  • when using other functions that aren't awaitable, await uasyncio.sleep(0) can be used (as seen in the example)
  • more info about using uasyncio: uasyncio docs

Template Rendering

  • μWeb comes loaded with a simple template rendering system that can render HTML with python variables.
  • To replace a variable in the HTML template, surround the variable name with {{ }}. Then, render the template with the variables argument.

Example:

content.html

<h1>Hello from {{name}}!</h1>
<h3>1 + 1 = {{answer}}</h3>

example.py

vars = {
      'name': 'MicroPython',
      'answer': (1+1)
}
server.render('content.html', variables=vars)

will render as:

<h1>Hello from MicroPython!</h1>
<h3>1 + 1 = 2</h3>

Layout Rendering

  • Template rendering can be combined with layout rendering so that templates can share the same layout
  • The default layout is layout.html
  • Specify a specific layout to render your template with using the layout argument in the render function
  • Use {{yield}} to specify where in the layout you want the content to render

Using the example from above:

content.html

<h1>Hello from {{name}}!</h1>
<h3>1 + 1 = {{answer}}</h3>

cool-layout.html

<head>
  <title>cool site</title>
</head>
<body>
  <h1>this is a cool layout dude</h1>
  {{yield}}
</body>

example.py

vars = {
      'name': 'MicroPython',
      'answer': (1+1)
}
server.render('content.html', layout='cool-layout.html', variables=vars) # if you are using layout.html, the layout argument may be left out

will render as:

<head>
  <title>cool site</title>
</head>
<body>
  <h1>this is a cool layout dude</h1>
  <h1>Hello from MicroPython!</h1>
  <h3>1 + 1 = 2</h3>
</body>

Documentation