Last active
September 28, 2021 21:33
-
-
Save evindunn/1734d841e183dfb250ca4a367ca089db to your computer and use it in GitHub Desktop.
Raspberry Pi i2C LCD Server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
from RPLCD.i2c import CharLCD | |
from argparse import ArgumentParser | |
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler | |
from json import dumps as json_dumps | |
from sys import stderr | |
from threading import Lock | |
from board import I2C | |
I2C_ADDR_DEFAULT = "0x27" | |
I2C_TYPE_DEFAULT = "PCF8574" | |
I2C_ROWS = 2 | |
I2C_COLS = 16 | |
class Handler(BaseHTTPRequestHandler): | |
CODE_BAD_REQUEST = 400 | |
CODE_NO_CONTENT = 204 | |
CODE_INTERNAL_SERVER_ERROR = 500 | |
protocol_version = "HTTP/1.1" | |
error_content_type = "application/json;charset=utf-8" | |
error_message_format = json_dumps({"message": "%(explain)s"}) | |
@property | |
def content_length(self): | |
if self.headers["Content-Length"] is None: | |
return None | |
return int(self.headers["Content-Length"]) | |
def do_POST(self): | |
try: | |
if not self.content_length: | |
self.send_error(Handler.CODE_BAD_REQUEST, explain="Content-Length is not set") | |
elif not "Content-Type" in self.headers.keys() or not self.headers["Content-Type"].startswith("text/plain"): | |
self.send_error(Handler.CODE_BAD_REQUEST, explain="Plaintext should be sent") | |
else: | |
with self.server.lcd_lock: | |
#self.server.lcd.clear() | |
self.server.lcd.cursor_pos = (0, 0) | |
self.server.lcd.write_string(self.rfile.read(self.content_length).decode("utf-8")) | |
self.send_response(Handler.CODE_NO_CONTENT) | |
except Exception as e: | |
self.log_error(str(e)) | |
self.send_response(Handler.CODE_INTERNAL_SERVER_ERROR) | |
self.end_headers() | |
class Server(ThreadingHTTPServer): | |
allow_reuse_address = True | |
def __init__(self, address, handler, lcd_i2c, lcd_address, lcd_rows, lcd_cols): | |
super().__init__(address, handler) | |
self.lcd = CharLCD(lcd_i2c, lcd_address, rows=lcd_rows, cols=lcd_cols) | |
self.lcd_lock = Lock() | |
self.lcd.clear() | |
if __name__ == "__main__": | |
parser = ArgumentParser(description="LCD Server") | |
parser.add_argument("port", type=int, help="The port to the the server on") | |
parser.add_argument("--lcd-address", type=str, help="The i2c address of the LCD", default=I2C_ADDR_DEFAULT) | |
parser.add_argument("--lcd-i2c", choices=("PCF8574", "MCP23008", "MCP23017"), help="The i2c backpack type for the LCD", default=I2C_TYPE_DEFAULT) | |
parser.add_argument("--lcd-rows", type=int, help="The number of rows on the LCD", default=I2C_ROWS) | |
parser.add_argument("--lcd-cols", type=int, help="The number of columns on the LCD", default=I2C_COLS) | |
args = parser.parse_args() | |
try: | |
lcd_address = int(args.lcd_address, 16) | |
except: | |
print("Invalid LCD address, this should be a hexidecimal number (e.g. '0x27')", file=stderr) | |
exit(1) | |
with Server(("0.0.0.0", args.port), Handler, args.lcd_i2c, lcd_address, args.lcd_rows, args.lcd_cols) as httpd: | |
print("Server running on port {}...".format(args.port)) | |
try: | |
httpd.serve_forever() | |
except KeyboardInterrupt: | |
httpd.shutdown() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment