|
| 1 | +# SPDX-FileCopyrightText: 2021 Patrick Van Oosterwijck @ Silicognition LLC |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | +# |
| 5 | +# This demo was tested with the PoE-FeatherWing, which contains a 24AA02E48 |
| 6 | +# chip to provide a globally unique MAC address, but can also work without |
| 7 | +# this chip for testing purposes by using a hard coded MAC. |
| 8 | +# |
| 9 | +# It also contains a `get_static_file` function that demonstrates how to |
| 10 | +# use a generator to serve large static files without using up too much |
| 11 | +# memory. To avoid having to put extra files in the repo, it just serves |
| 12 | +# `code.py` which isn't very large, but to properly test it, adjust the code |
| 13 | +# to serve an image of several 100 kB to see how it works. |
| 14 | +# |
| 15 | +# There's also an endpoint that demonstrates that `requests` can be used to |
| 16 | +# get data from another socket and serve it. |
| 17 | +# |
| 18 | + |
| 19 | +import board |
| 20 | +import busio |
| 21 | +import digitalio |
| 22 | +import neopixel |
| 23 | +import time |
| 24 | + |
| 25 | +import adafruit_requests as requests |
| 26 | +from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K |
| 27 | +import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket |
| 28 | +import adafruit_wiznet5k.adafruit_wiznet5k_wsgiserver as server |
| 29 | +from adafruit_wsgi.wsgi_app import WSGIApp |
| 30 | + |
| 31 | + |
| 32 | +print("Wiznet5k Web Server Test") |
| 33 | + |
| 34 | + |
| 35 | +def get_mac(i2c): |
| 36 | + "Read MAC from 24AA02E48 chip and return it" |
| 37 | + mac = bytearray(6) |
| 38 | + while not i2c.try_lock(): |
| 39 | + pass |
| 40 | + i2c.writeto(0x50, bytearray((0xFA,))) |
| 41 | + i2c.readfrom_into(0x50, mac, start=0, end=6) |
| 42 | + i2c.unlock() |
| 43 | + return mac |
| 44 | + |
| 45 | + |
| 46 | +def get_static_file(filename): |
| 47 | + "Static file generator" |
| 48 | + with open(filename, "rb") as f: |
| 49 | + bytes = None |
| 50 | + while bytes is None or len(bytes) == 2048: |
| 51 | + bytes = f.read(2048) |
| 52 | + yield bytes |
| 53 | + |
| 54 | + |
| 55 | +# Status LED |
| 56 | +led = neopixel.NeoPixel(board.NEOPIXEL, 1) |
| 57 | +led.brightness = 0.3 |
| 58 | +led[0] = (255, 0, 0) |
| 59 | + |
| 60 | +# PoE-FeatherWing connections |
| 61 | +cs = digitalio.DigitalInOut(board.D10) |
| 62 | +spi_bus = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) |
| 63 | +i2c = busio.I2C(board.SCL, board.SDA) |
| 64 | + |
| 65 | +try: |
| 66 | + # Read the MAC from the 24AA02E48 chip |
| 67 | + mac = get_mac(i2c) |
| 68 | +except OSError: |
| 69 | + mac = b"\xFE\xED\xDE\xAD\xBE\xEF" |
| 70 | + |
| 71 | +# Initialize Ethernet interface with DHCP |
| 72 | +eth = WIZNET5K(spi_bus, cs, mac=mac) |
| 73 | + |
| 74 | +# Initialize a requests object with a socket and ethernet interface |
| 75 | +requests.set_socket(socket, eth) |
| 76 | + |
| 77 | + |
| 78 | +# Here we create our application, registering the |
| 79 | +# following functions to be called on specific HTTP GET requests routes |
| 80 | + |
| 81 | +web_app = WSGIApp() |
| 82 | + |
| 83 | + |
| 84 | +@web_app.route("/led/<r>/<g>/<b>") |
| 85 | +def led_on(request, r, g, b): # pylint: disable=unused-argument |
| 86 | + print("LED handler") |
| 87 | + led.fill((int(r), int(g), int(b))) |
| 88 | + return ("200 OK", [], ["LED set!"]) |
| 89 | + |
| 90 | + |
| 91 | +@web_app.route("/") |
| 92 | +def root(request): # pylint: disable=unused-argument |
| 93 | + print("Root WSGI handler") |
| 94 | + return ("200 OK", [], ["Root document"]) |
| 95 | + |
| 96 | + |
| 97 | +@web_app.route("/large") |
| 98 | +def large(request): # pylint: disable=unused-argument |
| 99 | + print("Large pattern handler") |
| 100 | + return ("200 OK", [], ["*-.-" * 2000]) |
| 101 | + |
| 102 | + |
| 103 | +@web_app.route("/code") |
| 104 | +def large(request): # pylint: disable=unused-argument |
| 105 | + print("Static file code.py handler") |
| 106 | + return ("200 OK", [], get_static_file("code.py")) |
| 107 | + |
| 108 | + |
| 109 | +@web_app.route("/btc") |
| 110 | +def btc(request): |
| 111 | + print("BTC handler") |
| 112 | + r = requests.get("http://api.coindesk.com/v1/bpi/currentprice/USD.json") |
| 113 | + result = r.text |
| 114 | + r.close() |
| 115 | + return ("200 OK", [], [result]) |
| 116 | + |
| 117 | + |
| 118 | +# Here we setup our server, passing in our web_app as the application |
| 119 | +server.set_interface(eth) |
| 120 | +wsgiServer = server.WSGIServer(80, application=web_app) |
| 121 | + |
| 122 | +print("Open this IP in your browser: ", eth.pretty_ip(eth.ip_address)) |
| 123 | + |
| 124 | +# Start the server |
| 125 | +wsgiServer.start() |
| 126 | +led[0] = (0, 0, 255) |
| 127 | + |
| 128 | +while True: |
| 129 | + # Our main loop where we have the server poll for incoming requests |
| 130 | + wsgiServer.update_poll() |
| 131 | + # Maintain DHCP lease |
| 132 | + eth.maintain_dhcp_lease() |
| 133 | + # Could do any other background tasks here, like reading sensors |
0 commit comments