Source code for pylibftdi.examples.bit_server
"""
bit_server.py - remote HTTP interface to bit-bangged FTDI port
This runs as a web server, connect to port 8008
Change HTTP_PORT for different port number or supply alternate as args[1]
Requires:
- pylibftdi
"""
import sys
import threading
import time
import webbrowser
from http.server import BaseHTTPRequestHandler, HTTPServer
from io import BytesIO
from socketserver import ThreadingMixIn
from pylibftdi import BitBangDevice
HTTP_PORT = 8008
[docs]
class ThreadingServer(ThreadingMixIn, HTTPServer):
pass
[docs]
def get_page():
port = switch.port
page = f"""
<!DOCTYPE html>
<html>
<head>
<title>{port} - pylibftdi</title>
</head>
<body>
<div>
"""
for idx in range(8):
bit = 7 - idx
is_on = port & (1 << bit)
color = "#00FF00" if is_on else "#FF0000"
page += f"""
<fieldset style="background-color: { color }; display: inline-block;
margin:0px; padding: 3px;">
<form action="" method="post">
<input type="checkbox"
onchange="document.querySelector('[name=bit{ bit }]').value=this.checked;
document.forms[{idx}].submit()" { 'checked="checked"' if is_on else "" } />
<input type="hidden" name="bit{bit}" />
</form>
</fieldset>"""
page += f"""
</div>
DATA={port}
</body>
</html>
"""
return page
[docs]
class ReqHandler(BaseHTTPRequestHandler):
[docs]
def do_GET(self):
f = self.send_head()
if f:
self.wfile.write(f.read())
f.close()
[docs]
def do_POST(self):
length = self.headers["content-length"]
nbytes = int(length)
query = self.rfile.read(nbytes).decode()
# this is lazy and fragile - assumes only a single
# query parameter XXX
if query.startswith("bit"):
bit = int(query[3])
value = 1 if query.rsplit("=", 1)[-1] == "true" else 0
if value:
switch.port |= 1 << bit
else:
switch.port &= 255 ^ (1 << bit)
f = self.send_head()
if f:
self.wfile.write(f.read())
f.close()
[docs]
def send_head(self):
f = BytesIO()
f.write(get_page().encode())
length = f.tell()
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(length))
self.end_headers()
return f
[docs]
def runserver(port=HTTP_PORT):
serveraddr = ("", port)
srvr = ThreadingServer(serveraddr, ReqHandler)
srvr.serve_forever()
if __name__ == "__main__":
switch = BitBangDevice()
try:
HTTP_PORT = int(sys.argv[1])
except (ValueError, TypeError):
print("Usage: FtdiWebServer [portnumber]")
except IndexError:
pass
t = threading.Thread(target=runserver, args=(HTTP_PORT,))
t.setDaemon(True)
t.start()
print("Webserver running on localhost port %d" % HTTP_PORT)
time.sleep(0.5)
retry = 10
while retry:
try:
webbrowser.open("http://localhost:%d" % HTTP_PORT)
except OSError:
time.sleep(1)
retry -= 1
else:
break
# wait for Ctrl-C
try:
while 1:
time.sleep(100)
except KeyboardInterrupt:
pass