diff --git a/main.py b/main.py index 6b021ad060fe12053f7b2d5d08b18aa39a3da437..a5681d99ea72cc05cbd4e3e494fe36457677508a 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,9 @@ -import json import threading import time import queue -import os import pygame -from flask import request, Flask, Response +from flask import request, Flask, Response, Request import ledpatterns from absled import ILedString @@ -37,9 +35,29 @@ with open("module_config.json", "w") as f: json.dump(module_config, f, indent=4) mainthread_queue = queue.Queue() -api_queue = queue.Queue() +display_queue = queue.Queue() led_queue = queue.Queue() +def json_response(data, status=200): + return Response(json.dumps(data), status=status, mimetype="application/json") + +def verify_json_request(req: Request, required_fields=None): + if required_fields is None: + required_fields = [] + + if not req.is_json: + return False, json_response({ + "error": "Request is not JSON. Please make sure mimetype is set to application/json." + }, 400) + + for field in required_fields: + if field not in req.json: + return False, json_response({ + "error": f"Missing field {field}" + }, 400) + + return True, None + @app.route("/") def wr_index(): return f""" @@ -51,49 +69,75 @@ def wr_index(): @app.route("/api/available_fonts") def wr_available_fonts(): - return Response(json.dumps(pygame.font.get_fonts()), mimetype="application/json") + return json_response(pygame.font.get_fonts()) @app.route("/api/available_widgets") def wr_available_widgets(): - return Response(json.dumps(PROP_AVAILABLE_WIDGETS), mimetype="application/json") + return json_response(PROP_AVAILABLE_WIDGETS) @app.route("/api/available_patterns") def wr_available_patterns(): - return Response(json.dumps(PROP_AVAILABLE_PATTERNS), mimetype="application/json") + return json_response(PROP_AVAILABLE_PATTERNS) @app.route("/api/set_widget", methods=["POST"]) def wr_set_widget(): - widget_name = request.args.get("widget") + # Make sure the request is valid + valid, validation_response = verify_json_request(request, ["widget"]) + if not valid: + return validation_response + + # Verify pattern is valid and available + widget_name = request.json.get("widget") if widget_name is None: - return "No widget provided", 400 + return json_response({ + "error": "No widget provided" + }, 400) - if widget_name not in PROP_AVAILABLE_WIDGETS: - return f"Widget {widget_name} is not available", 400 + if widget_name not in PROP_AVAILABLE_PATTERNS: + return json_response({ + "error": f"Widget {widget_name} is not available" + }, 400) - api_queue.put("SET_WIDGET:" + widget_name) + # Send the pattern to the LED thread + display_queue.put("SET_WIDGET:" + widget_name) - return "OK" + # Return success + return json_response({ + "status": "OK", + "pattern": widget_name + }) @app.route("/api/set_pattern", methods=["POST"]) def wr_set_pattern(): - pattern_name = request.args.get("pattern") + # Make sure the request is valid + valid, validation_response = verify_json_request(request, ["pattern"]) + if not valid: + return validation_response + + # Verify pattern is valid and available + pattern_name = request.json.get("pattern") if pattern_name is None: - return "No pattern provided", 400 + return json_response({ + "error": "No pattern provided" + }, 400) if pattern_name not in PROP_AVAILABLE_PATTERNS: - return f"Pattern {pattern_name} is not available", 400 + return json_response({ + "error": f"Pattern {pattern_name} is not available" + }, 400) + # Send the pattern to the LED thread led_queue.put("SET_PATTERN:" + pattern_name) - return "OK" + # Return success + return json_response({ + "status": "OK", + "pattern": pattern_name + }) @app.route("/api/get_config") def wr_get_config(): - return Response(json.dumps(module_config), mimetype="application/json") - -@app.route("/api/test") -def wr_test(): - print(request.json) + return json_response(module_config) def load_widget(widget_name: str): # Get the widget properties from the config file @@ -145,7 +189,7 @@ def run_screen(): # Check for messages try: - message = api_queue.get_nowait() + message = display_queue.get_nowait() if message.startswith("SET_WIDGET:"): widget_to_load = message.removeprefix("SET_WIDGET:") if widget_to_load in PROP_AVAILABLE_WIDGETS: # Check input validity @@ -220,7 +264,7 @@ if __name__ == "__main__": try: message = mainthread_queue.get_nowait() if message == "EXIT": - api_queue.put("EXIT") + display_queue.put("EXIT") led_queue.put("EXIT") break except queue.Empty: