Web-Based Control in Micropython

Step 1: Create a Form that posts to URL

Good resources

Step 2: Back-end python code that can parse the input form data.

  • https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data

  • using post method allows us to enter data from the form rather than the url bar. keeps the address bar clean

  • using the GET method allows us ot enter commands directly from address bar

    • however the method includes the referal url which has the old data in it, so you must do a better job of parsing the request string.
  • or you can use microdot as seen below

Some resources

Implementation of Step 1 & 2

# import libraries
import os
import time
import ubinascii
import machine
import micropython
import esp
esp.osdebug(None)
import gc
gc.collect()
import upip
from machine import Pin


try:
  import usocket as socket
except:
  import socket

import network

import esp
esp.osdebug(None)

import gc
gc.collect()


import network
# set wifi information
ssid     = '<enter-ssid-here>'
wifi_password  = '<enter-password-here>'

#create station instance
station = network.WLAN(network.STA_IF)

#set active
station.active(True)

# if the station is not connected,
if not station.isconnected():
    # connect the station with ssid and password
    station.connect(ssid, wifi_password)

# wait until the station is connected
while station.isconnected() == False:
  pass


# print connection successful
print('Connection successful')

# print full connection information 
print(station.ifconfig())


# import upip

# if 'lib' in os.listdir('./'):
#     if 'microdot' not in os.listdir('lib/'):
#     # install the micropython logging library
#         upip.install('microdot')
#         os.rename('lib/src','lib/microdot')
#         with open('lib/microdot/__init__.py','w') as f:
#            f.write('')


led = Pin(2, Pin.OUT)


template = '''
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>URL Encoded Forms</title>
  </head>
  <body>
    <form
      method="POST"
      enctype="application/x-www-form-urlencoded">
      <input type="text" name="led" value="{led_value}" />
      <input type="text" name="password" value="GFG@123" />
      <input type="submit" value="Submit" />
    </form>
  </body>
</html>
'''

def web_page(led_value = ""):
  if led.value() == 1:
    gpio_state="ON"
  else:
    gpio_state="OFF"
  html = template.format(led_value=led_value)
  return html

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(5)

while True:
  conn, addr = s.accept()
  print('Got a connection from %s' % str(addr))
  request = conn.recv(1024)
  request = str(request)
  print('Content = %s' % request)
  if request.find('led=1') > -1:
    print('LED ON')
    led.value(1)
  if request.find('led=0') > -1:
    print('LED OFF')
    led.value(0)
  response = web_page(led_value=str(led.value()))
  conn.send('HTTP/1.1 200 OK\n')
  conn.send('Content-Type: text/html\n')
  conn.send('Connection: close\n\n')
  conn.sendall(response)
  conn.close()

Step 3: alternatively Microdot based api can be used to create quick apps

https://bhave.sh/micropython-microdot/ https://github.com/bhavesh-k/micropython-bamboo/blob/main/main.py

I used this approach to create this simpmle script:

import network
# set wifi information
ssid     = '<enter-ssid-here>'
wifi_password  = '<enter-password-here>'

#create station instance
station = network.WLAN(network.STA_IF)

#set active
station.active(True)

# if the station is not connected,
if not station.isconnected():
    # connect the station with ssid and password
    station.connect(ssid, wifi_password)

# wait until the station is connected
while station.isconnected() == False:
  pass


# print connection successful
print('Connection successful')

# print full connection information 
print(station.ifconfig())


import uasyncio
from microdot_asyncio import Microdot


# setup webserver
app = Microdot()

@app.route('/')
async def hello(request):
	return 'Hello world'


from machine import Pin
led = Pin(2, Pin.OUT)

def set_servo(value):
    led.value(int(value))

    print('setting servo value: ',value)

@app.get('/servo')
async def servo(request):
    set_servo((int(request.args['v'])))
    return 'OK'


def start_server():
    print('Starting microdot app')
    try:
        app.run(port=80)
    except:
        app.shutdown()

start_server()

External resources

Other microdot info

Fetch API

Asyncio info