Cutipy Web Browser

From wiki.emacinc.com
Revision as of 10:23, 10 January 2020 by Kyoungmeyer (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This page outlines a basic guide to getting starting serving web pages from a Cutipy.

Required Equipment

  1. One CutiPy Board

  2. One microUSB cable

  3. One MicroSD Card

  4. A Desktop/Laptop running Linux or Windows

General Information

Running a web browser on the Cutipy is fairly simple, and can be accomplished by using the PicoWebSrv project. This project is primarily aimed at the EMAC CutiPy board with the RS9116 module onboard. PicoWebSrv allows serving of standard webpages (html, css, javascript), as well as hosting a simple REST API implementation.

With only one required file, it is very easy to integrate with new or existing projects.

  • picoWebSrv.py - The Actual Web server
  • picoMimetypes.py - (Optional) Full list of mimetypes for the Content-Type: header line

Currently the server only has support for GET and POST requests.

Developing with the Cutipy Web Server

PicoWebSrv has just one external MicroPython library requirement:

  • logging.py - Note: This will be included in all standard EMAC MicroPython builds, starting with the next major release.

Basic Web Server

To run a basic web server from the Cutipy, use the following instructions. These instructions assume that you are storing your webpage files on an SD card attached to the Cutipy.

  1. Remove the SD card from the Cutipy, if already inserted.

  2. Connect the SD card to the host PC.

  3. Place web page files on the SD card in the www directory (The can be downloade HERE.)

  4. Connect the Cutipy to the host PC via a USB cable. See The getting started page.

  5. Create an empty file (NO FILE EXTENSION) called SKIPSD CutiPy's flash memory (appears as flash drive device PYBFLASH on your PC)

  6. Edit boot.py in the flash memory and add the following lines.



    NOTE
    To prevent file corruption, it is recommended that all edits occur outside of the CutiPy's flash memory. For example when editing boot.py, first copy the file to your desktop, make the edits to the desktop copy and then copy the file back to CutiPy flash memory
    import uos
    try:
        uos.mount(pyb.SDCard(), '/sd')
    except Exception:
        pass
    
  7. Place the PicoWebSrv files (picoWebSrv.py and Optionally picoMimetypes.py) flash memory as well as logging.py .

    When it's all said and done, you CutiPy's drive contents (PYBFLASH) should look similar to the following (note logging.py may not be required in future CutiPy firmware releases):
    PYBFLASH.PNG

    And your SD cards contents should only contain the the www directory:
    MicroSD.PNG

  8. Disconnect the Cutipy, insert the SD card, then reconnect the Cutipy.

  9. Run the following commands to start the server.

    import network
    import picoWebSrv
    
    nic = network.RS9116()
    nic.init()
    nic.connect('SSID', 'PASSWORD')
    
    host_ip = nic.ifconfig()[0]
    pws = picoWebSrv.PicoWebSrv(host_ip, 80, file_location='/sd/www/')
    pws.start()
    

The web pages placed on the SD card will now be served at the IP of the Cutipy. The IP will be displayed on the Cutipy LCD if populated, it will also be printed on the REPL as follows

>>> INFO:picoWebSrv:Simple Webserver Running at: 10.0.6.153:80

Where in this case 10.0.6.153 is the IP address (Your IP address may be different). Copy and paste this IP address into your web-browser's address bar to view the webpage.

REST (Representational State Transfer) Server

To start a server with some REST API calls, preform the same steps as with the Basic Web Server, but stop before the last step. You will need to register some functions and endpoints for the API calls before starting the server. This process is illustrated below.

import network
import picoWebServer
import pyb
import ujson

def get_switch(var_list):
    if var_list:
        switch_num = var_list[0]  # (e.g. '/get_switch/1')
    else:
        switch_num = 1  

    sw = pyb.Switch(switch_num)

    if sw():
        response_data = ujson.dumps({'status': 'pressed'})
    else:
        response_data = ujson.dumps({'status': 'not_pressed'})

    return response_data.encode('utf-8')

def led_control(json_dict):
    try:
        led_num = json_dict['number']
    except KeyError:
        led_num = 1
    led = pyb.LED(led_num)
    try:
        led_action = json_dict['action']
    except KeyError:
        led.toggle()
    else:
        if led_action == 'on':
            led.on()
        elif led_action == 'off':
            led.off()
        elif led_action == 'toggle':
            led.toggle()
        else:
            raise ValueError
    if led.intensity() == 255:  # CutiPy reports 255 as off. LED pins sink current, instead of source.
        response_data = ujson.dumps({'status': 'off'})
    else:
        response_data = ujson.dumps({'status': 'on'})

    return response_data.encode('utf-8')

nic = network.RS9116()
nic.init()
nic.connect('SSID', 'PASSWORD')

host_ip = nic.ifconfig()[0]
pws = picoWebSrv(host_ip, 80, file_location='/sd/www/')
pws.add_rest_function('GET', '/get_sw', get_switch)
pws.add_rest_function('POST', 'led_ctrl', led_control)
pws.start()

This will start a server with an API call listening for GET at /get_sw and a call listening for POST at led_ctrl. For more information about these calls, see the library documentation here.

You can find a file with the above REST function definitions (plus additional functions), here. This file just needs to be imported, then the included functions can be set as REST API calls.

Integration with Existing Project

This webserver can easily be integrated with existing projects, that need a REST API endpoint. The only extra code that would need written is some wrapper functions (that call existing functions) that take and return the correct parameters expected by the webserver's REST parsing. The restAPIFuncts.py file should provide a good example of this, the functions wrap calls to the various 'pyb.' functions.

Real World Example

The following is an example of how to set up a webserver instance on a CutiPy, that will restart itself if someone manages to crash the server. Pressing <Ctrl-C> on the REPL terminal will stop the server (you may need to press it more than once). The following is two separate files, the names are indicated by the comment at the top of the block. In webserver.py, replace 'SSID' and 'PASSWORD' with the SSID and PASSWORD of your WiFi network, respectively.

Place these two files, the PicoWebSrv files, and the restAPIFuncts.py file on the CutiPy's flash memory (appears as flash drive device PYBFLASH on your PC). Download and place the www/ directory from this zip file onto the SD card (as show in the above sections). After editing the main.py file, reset the CutiPy, and the websever will be running. The IP address will be printed on the REPL.

# webserver.py

import pyb
import network
import logging
import picoWebSrv
import restAPIFuncts


def webserver():
    nic = network.RS9116()
    nic.init()
    nic.connect('SSID', 'PASSWORD')

    host_ip = nic.ifconfig()[0]
    pws = picoWebSrv.PicoWebSrv(host_ip, 80, file_location='/sd/www/')
    pws.add_rest_function('POST', 'led_control', restAPIFuncts.led_control)
    pws.add_rest_function('GET', 'get_switch', restAPIFuncts.get_switch)
    pws.add_rest_function('GET', 'get_led', restAPIFuncts.get_led)
    pws.start()

def run():
    while True:
        try:
            webserver()
        except KeyboardInterrupt:
            break
        except Exception as e:
            print(e)
            continue
# main.py

import webserver

webserver.run()

The restAPIFuncts.py file can be edited to include additional functions of your choosing, and additional REST endpoints can be added with more calls to .add_rest_function().


Pages with Related Content

CutiPy Micropython Documentation

Cutipy Test Software

Cutipy-MicroPython Bluetooth LE demo

Micropython

CutiPy-Installing Micropython Firmware