From 96a85271c018726248cfb53d2825ef78ac8112b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Bedn=C3=A1rik?= Date: Sun, 22 Dec 2024 23:32:58 +0100 Subject: [PATCH] Bugfix: External spool Improvement: Use fragments in templates Features: Manual fill of empty tray Bump version to 0.1.3 --- README.md | 7 +- __version__.py | 2 +- app.py | 103 ++++++++++++++++++--------- templates/assign_tag.html | 67 +---------------- templates/fill.html | 7 ++ templates/fragments/list_spools.html | 51 +++++++++++++ templates/fragments/tray.html | 57 +++++++++++++++ templates/index.html | 80 +-------------------- templates/issue.html | 6 ++ templates/spool_info.html | 75 +------------------ 10 files changed, 203 insertions(+), 252 deletions(-) create mode 100644 templates/fill.html create mode 100644 templates/fragments/list_spools.html create mode 100644 templates/fragments/tray.html create mode 100644 templates/issue.html diff --git a/README.md b/README.md index 1fb1876..5a997ca 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,9 @@ Similar functionality to https://github.com/spuder/OpenSpool using only your pho Everything works locally without cloud access, you can use scripts/init_bambulab.py script to access your PRINTER_ID and PRINTER_CODE if it is not available on your printer. +### News +0.1.3 - 22.12.2024 - Added manual assignment for empty slots + ### Main features @@ -113,7 +116,9 @@ This feature has currently following issues/drawbacks: - Logs - TODOs - Click to resolve issue - - More template components / less copy&paste - Better Tray naming - Reduce the amount of files in docker container - Cloud service for controlled redirect so you don't have to reconfigure NFC tags + - Handle printer offline + - QR codes + - Add search to list of spools diff --git a/__version__.py b/__version__.py index 0a5be70..1682803 100644 --- a/__version__.py +++ b/__version__.py @@ -1 +1 @@ -__version__ = '0.1.2' +__version__ = '0.1.3' diff --git a/app.py b/app.py index 561369f..69feb0c 100644 --- a/app.py +++ b/app.py @@ -14,9 +14,32 @@ from spoolman_service import augmentTrayDataWithSpoolMan, trayUid app = Flask(__name__) +EXTERNAL_SPOOL_AMS_ID = 255 + @app.context_processor def fronted_utilities(): - return dict(SPOOLMAN_BASE_URL=SPOOLMAN_BASE_URL, AUTO_SPEND=AUTO_SPEND, color_is_dark=color_is_dark, BASE_URL=BASE_URL) + return dict(SPOOLMAN_BASE_URL=SPOOLMAN_BASE_URL, AUTO_SPEND=AUTO_SPEND, color_is_dark=color_is_dark, BASE_URL=BASE_URL, EXTERNAL_SPOOL_AMS_ID=EXTERNAL_SPOOL_AMS_ID) + +@app.route("/issue") +def issue(): + return render_template('issue.html') + +@app.route("/fill") +def fill(): + ams_id = request.args.get("ams") + tray_id = request.args.get("tray") + if not all([ams_id, tray_id]): + return "Missing AMS ID, or Tray ID." + + spool_id = request.args.get("spool_id") + if spool_id: + spool_data = getSpoolById(spool_id) + setActiveTray(spool_id, spool_data["extra"], ams_id, tray_id) + setActiveSpool(ams_id, tray_id, spool_data) + return redirect(url_for('home', success_message=f"Updated Spool ID {spool_id} to AMS {ams_id}, Tray {tray_id}.")) + else: + spools = fetchSpools() + return render_template('fill.html', spools=spools, ams_id=ams_id, tray_id=tray_id) @app.route("/spool_info") def spool_info(): @@ -63,43 +86,43 @@ def tray_load(): try: # Update Spoolman with the selected tray spool_data = getSpoolById(spool_id) - setActiveTray(spool_id, spool_data["extra"], ams_id, tray_id) - - ams_message = AMS_FILAMENT_SETTING - ams_message["print"]["sequence_id"] = 0 - ams_message["print"]["ams_id"] = int(ams_id) - ams_message["print"]["tray_id"] = int(tray_id) - ams_message["print"]["tray_color"] = spool_data["filament"]["color_hex"].upper() + "FF" - - if "nozzle_temperature" in spool_data["filament"]["extra"]: - nozzle_temperature_range = spool_data["filament"]["extra"]["nozzle_temperature"].strip("[]").split(",") - ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range[0]) - ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range[1]) - else: - nozzle_temperature_range_obj = generate_filament_temperatures(spool_data["filament"]["material"], - spool_data["filament"]["vendor"]["name"]) - ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range_obj["filament_min_temp"]) - ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range_obj["filament_max_temp"]) - - ams_message["print"]["tray_type"] = spool_data["filament"]["material"] - filament_brand_code = generate_filament_brand_code(spool_data["filament"]["material"], - spool_data["filament"]["vendor"]["name"], - spool_data["filament"]["extra"].get("type", "")) - ams_message["print"]["tray_info_idx"] = filament_brand_code["brand_code"] - - # TODO: test sub_brand_code - # ams_message["print"]["tray_sub_brands"] = filament_brand_code["sub_brand_code"] - ams_message["print"]["tray_sub_brands"] = "" - - print(ams_message) - publish(getMqttClient(), ams_message) + setActiveSpool(ams_id, tray_id, spool_data) return redirect(url_for('home', success_message=f"Updated Spool ID {spool_id} with TAG id {tag_id} to AMS {ams_id}, Tray {tray_id}.")) except Exception as e: traceback.print_exc() return render_template('error.html', exception=str(e)) +def setActiveSpool(ams_id, tray_id, spool_data): + ams_message = AMS_FILAMENT_SETTING + ams_message["print"]["sequence_id"] = 0 + ams_message["print"]["ams_id"] = int(ams_id) + ams_message["print"]["tray_id"] = int(tray_id) + ams_message["print"]["tray_color"] = spool_data["filament"]["color_hex"].upper() + "FF" + + if "nozzle_temperature" in spool_data["filament"]["extra"]: + nozzle_temperature_range = spool_data["filament"]["extra"]["nozzle_temperature"].strip("[]").split(",") + ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range[0]) + ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range[1]) + else: + nozzle_temperature_range_obj = generate_filament_temperatures(spool_data["filament"]["material"], + spool_data["filament"]["vendor"]["name"]) + ams_message["print"]["nozzle_temp_min"] = int(nozzle_temperature_range_obj["filament_min_temp"]) + ams_message["print"]["nozzle_temp_max"] = int(nozzle_temperature_range_obj["filament_max_temp"]) + + ams_message["print"]["tray_type"] = spool_data["filament"]["material"] + filament_brand_code = generate_filament_brand_code(spool_data["filament"]["material"], + spool_data["filament"]["vendor"]["name"], + spool_data["filament"]["extra"].get("type", "")) + ams_message["print"]["tray_info_idx"] = filament_brand_code["brand_code"] + + # TODO: test sub_brand_code + # ams_message["print"]["tray_sub_brands"] = filament_brand_code["sub_brand_code"] + ams_message["print"]["tray_sub_brands"] = "" + + print(ams_message) + publish(getMqttClient(), ams_message) @app.route("/") def home(): @@ -111,8 +134,8 @@ def home(): success_message = request.args.get("success_message") issue = False - #TODO: recheck tray ID and external spool ID and extract it to constant - augmentTrayDataWithSpoolMan(spool_list, vt_tray_data, trayUid(vt_tray_data["id"], 255)) + #TODO: Fix issue when external spool info is reset via bambulab interface + augmentTrayDataWithSpoolMan(spool_list, vt_tray_data, trayUid(EXTERNAL_SPOOL_AMS_ID, vt_tray_data["id"])) issue |= vt_tray_data["issue"] for ams in ams_data: @@ -125,10 +148,22 @@ def home(): traceback.print_exc() return render_template('error.html', exception=str(e)) +def sort_spools(spools): + def condition(item): + # Ensure the item has an "extra" key and is a dictionary + if not isinstance(item, dict) or "extra" not in item or not isinstance(item["extra"], dict): + return False + + # Check the specified condition + return item["extra"].get("tag") or item["extra"].get("tag") == "" + + # Sort with the custom condition: False values come first + return sorted(spools, key=lambda spool: bool(condition(spool))) + @app.route("/assign_tag") def assign_tag(): try: - spools = fetchSpools() + spools = sort_spools(fetchSpools()) return render_template('assign_tag.html', spools=spools) except Exception as e: diff --git a/templates/assign_tag.html b/templates/assign_tag.html index dc27837..a142d02 100644 --- a/templates/assign_tag.html +++ b/templates/assign_tag.html @@ -3,70 +3,5 @@ {% block content %}

Assign NFC Tag to Spool

- - -{% if spools|length == 0 or not spools %} - -{% else %} - - -
- {% for spool in spools %} - {% if not spool.extra.get("tag") or spool.extra.get("tag") == "\"\"" %} - - - - -
- - -
- - -
- -
{{ spool.filament.vendor.name }} - {{ spool.filament.material }}
- - {{ spool.filament.name }} -
- - - - Assign - -
- {% endif %} - {% endfor %} - {% for spool in spools %} - {% if spool.extra.get("tag") and spool.extra.get("tag") != "\"\"" %} - - - -
- - -
- - -
- -
{{ spool.filament.vendor.name }} - {{ spool.filament.material }}
- - {{ spool.filament.name }} -
- - - Reassign - -
- {% endif %} - {% endfor %} -
-{% endif %} +{% with action_assign=True %}{% include 'fragments/list_spools.html' %}{% endwith %} {% endblock %} diff --git a/templates/fill.html b/templates/fill.html new file mode 100644 index 0000000..cd2cef3 --- /dev/null +++ b/templates/fill.html @@ -0,0 +1,7 @@ +{% extends 'base.html' %} + +{% block content %} +

Fill slot

+

AMS: {{ ams_id }}, Tray: {{ tray_id }}

+{% with action_fill=True %}{% include 'fragments/list_spools.html' %}{% endwith %} +{% endblock %} diff --git a/templates/fragments/list_spools.html b/templates/fragments/list_spools.html new file mode 100644 index 0000000..d976dc8 --- /dev/null +++ b/templates/fragments/list_spools.html @@ -0,0 +1,51 @@ + +{% if spools|length == 0 or not spools %} + +{% else %} + + +
+ {% for spool in spools %} + + {% if action_fill %}{% endif %} + {% if action_assign %}{% endif %} + +
+ + +
+ + +
+ +
{{ spool.filament.vendor.name }} - {{ spool.filament.material }}
+ + {{ spool.filament.name }} +
+ + {% if action_fill %} + + Fill + + {% endif %} + {% if action_assign %} + + {% if spool.extra.get("tag") or spool.extra.get("tag") == "\"\"" %} + + Reassign + + {% else %} + + Assign + + {% endif %} + {% endif %} + {% if action_fill or action_assign %}
{% endif %} + {% endfor %} +
+{% endif %} diff --git a/templates/fragments/tray.html b/templates/fragments/tray.html new file mode 100644 index 0000000..e961a69 --- /dev/null +++ b/templates/fragments/tray.html @@ -0,0 +1,57 @@ +
+ +
+ {% if tray_data.issue %} + + {% endif %} + {% if not tray_data.tray_type %} + Empty + {% endif %} + Tray {{ tray_data.id }} +
+ +
+ +
+ {{ tray_data.tray_type }} + {% if tray_data.tray_sub_brands %} +
+ {{ tray_data.tray_sub_brands }} + {% endif %} +
+ + + + #{{ tray_data.tray_color | upper }} + + + +
+ Remaining: + {% if AUTO_SPEND and tray_data.matched %} + {{ tray_data.remaining_weight|round }}g + {% else %} + {{ tray_data.remain }}% + {% endif %} +
+
+ +
diff --git a/templates/index.html b/templates/index.html index 0dfa5a0..c5df1fb 100644 --- a/templates/index.html +++ b/templates/index.html @@ -9,7 +9,7 @@
There is a mismatch between printer and SpoolMan
-

TODO: To fix the issue click on the tray with the red exclamation mark

+

Fix issue by clicking "Fix this tray" on tray with

{% endif %} @@ -22,42 +22,7 @@
External Spool
- -
- {% if vt_tray_data.issue %} - - {% endif %} - {% if not vt_tray_data.tray_type %} - Empty - {% endif %} - Tray {{ vt_tray_data.id }} -
- - -
- {{ vt_tray_data.tray_type }} - {% if vt_tray_data.tray_sub_brands %} -
- {{ vt_tray_data.tray_sub_brands }} - {% endif %} -
- - - - #{{ vt_tray_data.tray_color | upper }} - - - -
- Remaining: - {% if AUTO_SPEND and vt_tray_data.matched %} - {{ vt_tray_data.remaining_weight|round }}g - {% else %} - {{ vt_tray_data.remain }}% - {% endif %} -
+ {% with tray_data=vt_tray_data, ams_id=EXTERNAL_SPOOL_AMS_ID, pick_tray=False, tray_id=vt_tray_data.id %} {% include 'fragments/tray.html' %} {% endwith %}
@@ -72,46 +37,7 @@
{% for tray in ams.tray %}
-
- -
- {% if tray.issue %} - - {% endif %} - {% if not tray.tray_type %} - Empty - {% endif %} - Tray {{ tray.id }} -
- - -
- {{ tray.tray_type }} - {% if tray.tray_sub_brands %} -
- {{ tray.tray_sub_brands }} - {% endif %} -
- - {% if tray.tray_color %} - - - #{{ tray.tray_color | upper }} - - {% endif %} - - -
- Remaining: - {% if AUTO_SPEND and tray.matched %} - {{ tray.remaining_weight|round }}g - {% else %} - {{ tray.remain }}% - {% endif %} -
-
+ {% with tray_data=tray, ams_id=ams.id, pick_tray=False, tray_id=tray.id %} {% include 'fragments/tray.html' %} {% endwith %}
{% endfor %}
diff --git a/templates/issue.html b/templates/issue.html new file mode 100644 index 0000000..90f9966 --- /dev/null +++ b/templates/issue.html @@ -0,0 +1,6 @@ +{% extends 'base.html' %} + +{% block content %} +

Solve issue

+

TBD

+{% endblock %} diff --git a/templates/spool_info.html b/templates/spool_info.html index e6dd9a7..2ffb6c0 100644 --- a/templates/spool_info.html +++ b/templates/spool_info.html @@ -46,42 +46,7 @@
External Spool
-
- -
- {% if vt_tray_data.issue %} - - {% endif %} - {% if not vt_tray_data.tray_type %} - Empty - {% endif %} - Tray {{ vt_tray_data.id }} -
- -
- -
- {{ vt_tray_data.tray_type }} - {% if vt_tray_data.tray_sub_brands %} -
- {{ vt_tray_data.tray_sub_brands }} - {% endif %} -
- - - - #{{ vt_tray_data.tray_color | upper }} - - -
- -
+ {% with tray_data=vt_tray_data, ams_id=EXTERNAL_SPOOL_AMS_ID, pick_tray=True, tray_id=vt_tray_data.id %} {% include 'fragments/tray.html' %} {% endwith %}
@@ -96,43 +61,7 @@
{% for tray in ams.tray %}
-
- -
- {% if tray.issue %} - - {% endif %} - {% if not tray.tray_type %} - Empty - {% endif %} - Tray {{ tray.id }} -
-
- -
- {{ tray.tray_type }} - {% if tray.tray_sub_brands %} -
- {{ tray.tray_sub_brands }} - {% endif %} -
- - {% if tray.tray_color %} - - - #{{ tray.tray_color | upper }} - - {% endif %} - -
- -
+ {% with tray_data=tray, ams_id=ams.id, pick_tray=True, tray_id=tray.id %} {% include 'fragments/tray.html' %} {% endwith %}
{% endfor %}