diff --git a/.idea/cs-fancy-clock.iml b/.idea/cs-fancy-clock.iml index 2c80e1269497d12e018fd6afa29982e56b0fb70d..53e113651728f0424d584ea209a227a3957db8e4 100644 --- a/.idea/cs-fancy-clock.iml +++ b/.idea/cs-fancy-clock.iml @@ -4,7 +4,7 @@ <content url="file://$MODULE_DIR$"> <excludeFolder url="file://$MODULE_DIR$/.venv" /> </content> - <orderEntry type="inheritedJdk" /> + <orderEntry type="jdk" jdkName="Python 3.10 (cs-fancy-clock)" jdkType="Python SDK" /> <orderEntry type="sourceFolder" forTests="false" /> </component> </module> \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index aa1a89dc11e565177fd80429d6bae9a90894896b..49a77e5b0d7f3bb03aea4f068954a0350ccff68e 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ <component name="Black"> <option name="sdkName" value="Python 3.10 (cs-fancy-clock)" /> </component> - <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (cs-fancy-clock)" project-jdk-type="Python SDK" /> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (cs-fancy-clock)" project-jdk-type="Python SDK" /> </project> \ No newline at end of file diff --git a/main.py b/main.py index 0e605cbfc7155b0f0221f8e183cf0693e4b68ad1..4f34567a5ea9302416fb895a8f1cc3bc13211c8a 100644 --- a/main.py +++ b/main.py @@ -95,30 +95,68 @@ def wr_index(): @app.route("/api/available_fonts") def wr_available_fonts(): + """ + Returns a list of available fonts on the system. + :return: A JSON response with a list of available fonts. + """ + return json_response(pygame.font.get_fonts()) @app.route("/api/available_widgets") def wr_available_widgets(): + """ + Returns a list of available widgets. + :return: A JSON response with a list of available widgets. + """ + return json_response(PROP_AVAILABLE_WIDGETS) @app.route("/api/get_state") def wr_get_state(): - return json_response({}) # TODO + return json_response({ + + }) # TODO @app.route("/api/toggle_screen_state", methods=["POST"]) def wr_toggle_state(): - mainthread_queue.put("TOGGLE_SCREEN_STATE") - return json_response({ - "status": "OK" - }) + """ + Toggles the screen state between widget cycle and single widget. + :return: A JSON response with the status of the request. + """ + + global screen_state, screen_state_lock + + with screen_state_lock: + if screen_state == ScreenState.WIDGET_CYCLE: + screen_state = ScreenState.WIDGET_SINGLE + elif screen_state == ScreenState.WIDGET_SINGLE: + screen_state = ScreenState.WIDGET_CYCLE + + return json_response({ + "status": "OK", + "state": screen_state.name + }) @app.route("/api/available_patterns") def wr_available_patterns(): + """ + Queries available patterns from the server. + :return: A JSON response with a list of available patterns. + """ + return json_response(PROP_AVAILABLE_PATTERNS) @app.route("/api/set_widget", methods=["POST"]) def wr_set_widget(): + """ + Sets the widget configuration for the screen temporarily (does not write to the config). + + Will only really work if the screen mode is set to single rather than cycle, + but it doesn't prevent you from setting it. + + :return: A JSON response with the status of the request. + """ # Make sure the request is valid valid, validation_response = verify_json_request(request, ["widget"]) if not valid: @@ -152,6 +190,15 @@ def wr_set_widget(): @app.route("/api/set_pattern", methods=["POST"]) def wr_set_pattern(): + """ + Sets the pattern configuration for the LEDs temporarily (does not write to the config). + + Will only really work if the screen mode is set to single rather than cycle, + but it doesn't prevent you from setting it. + + :return: A JSON response with the status of the request. + """ + # Make sure the request is valid valid, validation_response = verify_json_request(request, ["pattern"]) if not valid: @@ -185,6 +232,12 @@ def wr_set_pattern(): @app.route("/api/set_sequence", methods=["POST"]) def wr_set_sequence(): + """ + Sets the sequence configuration for the widgets and patterns. + Uses the request json "widget" and "pattern" to set the sequence. + :return: A JSON response with the status of the request. + """ + # Make sure the request is valid valid, validation_response = verify_json_request(request, ["widget", "pattern"]) if not valid: @@ -395,6 +448,8 @@ if __name__ == "__main__": raise ValueError("No patterns in sequence") screen_state = ScreenState.WIDGET_CYCLE + screen_state_lock = threading.Lock() + screen_state_event = threading.Event() initial_widget = widget_sequence[0] initial_pattern = pattern_sequence[0] @@ -457,48 +512,42 @@ if __name__ == "__main__": force_change_widget = True elif message == "CYCLE_PATTERN": force_change_pattern = True - elif message == "TOGGLE_SCREEN_STATE": - if screen_state == ScreenState.WIDGET_CYCLE: - screen_state = ScreenState.WIDGET_SINGLE - elif screen_state == ScreenState.WIDGET_SINGLE: - screen_state = ScreenState.WIDGET_CYCLE - else: - pass - except queue.Empty: pass - # Check if time delta has passed - if screen_state == ScreenState.WIDGET_CYCLE: - # For Widgets - curr_widget = widget_sequence[current_widget_index] - if curr_widget.get("duration", -1) != -1 or force_change_widget: - # Check if the widget has existed for too long - if curr_widget.get("duration") * 1000 <= current_widget_delta or force_change_widget: - # Set the widget to the next widget - current_widget_index += 1 - if current_widget_index >= len(widget_sequence): - current_widget_index = 0 - display_queue.put("SET_WIDGET:" + - widget_sequence[current_widget_index].get("type") + ":" + - encode_dict(widget_sequence[current_widget_index].get("config_override", {})) + + # Widget cycle after time delta + with screen_state_lock: + if screen_state == ScreenState.WIDGET_CYCLE: + # For Widgets + curr_widget = widget_sequence[current_widget_index] + if curr_widget.get("duration", -1) != -1 or force_change_widget: + # Check if the widget has existed for too long + if curr_widget.get("duration") * 1000 <= current_widget_delta or force_change_widget: + # Set the widget to the next widget + current_widget_index += 1 + if current_widget_index >= len(widget_sequence): + current_widget_index = 0 + display_queue.put("SET_WIDGET:" + + widget_sequence[current_widget_index].get("type") + ":" + + encode_dict(widget_sequence[current_widget_index].get("config_override", {})) + ) + current_widget_delta = 0 + force_change_widget = False + # For patterns + curr_pattern = pattern_sequence[current_pattern_index] + if curr_pattern.get("duration", -1) != -1 or force_change_pattern: + # Check if the pattern has existed for too long + if curr_pattern.get("duration") * 1000 <= current_pattern_delta or force_change_pattern: + # Set the pattern to the next pattern + current_pattern_index += 1 + if current_pattern_index >= len(pattern_sequence): + current_pattern_index = 0 + led_queue.put("SET_PATTERN:" + + pattern_sequence[current_pattern_index].get("type") + ":" + + encode_dict(pattern_sequence[current_pattern_index].get("config_override", {})) ) - current_widget_delta = 0 - force_change_widget = False - # For patterns - curr_pattern = pattern_sequence[current_pattern_index] - if curr_pattern.get("duration", -1) != -1 or force_change_pattern: - # Check if the pattern has existed for too long - if curr_pattern.get("duration") * 1000 <= current_pattern_delta or force_change_pattern: - # Set the pattern to the next pattern - current_pattern_index += 1 - if current_pattern_index >= len(pattern_sequence): - current_pattern_index = 0 - led_queue.put("SET_PATTERN:" + - pattern_sequence[current_pattern_index].get("type") + ":" + - encode_dict(pattern_sequence[current_pattern_index].get("config_override", {})) - ) - current_pattern_delta = 0 - force_change_pattern = False + current_pattern_delta = 0 + force_change_pattern = False # Keep main thread alive current_widget_delta += hw_config["main_update_frequency"]