Code cleanup: Separate spoolman_client
Bugfix: Unchanged extras must be sent to spoolman for them not to disappear Bugfix: Remove active tray from inactive spools Docs: Add note about the Base_URL
This commit is contained in:
parent
a56c78b24a
commit
3a6ecf8e9f
@ -40,11 +40,14 @@ How to setup:
|
||||
- On the website pick the slot you put your filament in
|
||||
- Done
|
||||
|
||||
Notes:
|
||||
- If you change the BASE_URL of this app, you will need to reconfigure all NFC TAGS
|
||||
|
||||
TBD:
|
||||
- Filament remaining in AMS (I have only AMS lite, if you have AMS we can test together)
|
||||
- Filament spending based on printing
|
||||
- Evidently needed GUI improvements
|
||||
- Code cleanup
|
||||
- Deployment as Docker and Helm chart
|
||||
- Easy configuration via env properties
|
||||
- Video showcase
|
||||
- TODOs
|
||||
|
44
app.py
44
app.py
@ -1,16 +1,17 @@
|
||||
import json
|
||||
import uuid
|
||||
|
||||
import requests
|
||||
from flask import Flask, request, render_template_string
|
||||
|
||||
from config import BASE_URL, PRINTER_ID, SPOOLMAN_API_URL
|
||||
from config import BASE_URL
|
||||
from filament import generate_filament_brand_code, generate_filament_temperatures
|
||||
from messages import AMS_FILAMENT_SETTING
|
||||
from mqtt_bambulab import fetchSpools, getLastAMSConfig, publish, getMqttClient
|
||||
from mqtt_bambulab import fetchSpools, getLastAMSConfig, publish, getMqttClient, setActiveTray
|
||||
from spoolman_client import patchExtraTags, getSpoolById
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
||||
@app.route("/spool_info")
|
||||
def spool_info():
|
||||
tag_id = request.args.get("tag_id")
|
||||
@ -68,6 +69,7 @@ def spool_info():
|
||||
|
||||
return render_template_string(html)
|
||||
|
||||
|
||||
@app.route("/tray_load")
|
||||
def tray_load():
|
||||
tag_id = request.args.get("tag_id")
|
||||
@ -80,25 +82,15 @@ def tray_load():
|
||||
|
||||
try:
|
||||
# Update Spoolman with the selected tray
|
||||
response = requests.patch(f"{SPOOLMAN_API_URL}/spool/{spool_id}", json={
|
||||
"extra": {
|
||||
"tag": json.dumps(tag_id),
|
||||
"active_tray": json.dumps(f"{PRINTER_ID}_{ams_id}_{tray_id}"),
|
||||
}
|
||||
})
|
||||
print(response.status_code)
|
||||
print(response.text)
|
||||
spool_data = getSpoolById(spool_id)
|
||||
|
||||
response = requests.get(f"{SPOOLMAN_API_URL}/spool/{spool_id}")
|
||||
print(response.status_code)
|
||||
print(response.text)
|
||||
setActiveTray(spool_id, spool_data["extra"], ams_id, tray_id)
|
||||
|
||||
spool_data = json.loads(response.text)
|
||||
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"
|
||||
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(",")
|
||||
@ -112,11 +104,12 @@ def tray_load():
|
||||
|
||||
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", ""))
|
||||
spool_data["filament"]["vendor"]["name"],
|
||||
spool_data["filament"]["extra"].get("type", ""))
|
||||
ams_message["print"]["tray_info_idx"] = filament_brand_code["brand_code"]
|
||||
|
||||
#ams_message["print"]["tray_sub_brands"] = filament_brand_code["sub_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)
|
||||
@ -129,10 +122,10 @@ def tray_load():
|
||||
except Exception as e:
|
||||
return f"<h1>Error</h1><p>{str(e)}</p>"
|
||||
|
||||
|
||||
@app.route("/")
|
||||
def home():
|
||||
try:
|
||||
# Update Spoolman with the selected tray
|
||||
spools = fetchSpools()
|
||||
|
||||
last_ams_config = getLastAMSConfig()
|
||||
@ -176,6 +169,7 @@ def home():
|
||||
except Exception as e:
|
||||
return f"<h1>Error</h1><p>{str(e)}</p>"
|
||||
|
||||
|
||||
@app.route("/assign_tag")
|
||||
def assign_tag():
|
||||
spool_id = request.args.get("spool_id")
|
||||
@ -185,15 +179,10 @@ def assign_tag():
|
||||
|
||||
myuuid = str(uuid.uuid4())
|
||||
|
||||
resp = requests.patch(f"{SPOOLMAN_API_URL}/spool/{spool_id}", json={
|
||||
"extra": {
|
||||
"tag": json.dumps(myuuid),
|
||||
}
|
||||
patchExtraTags(spool_id, {}, {
|
||||
"tag": json.dumps(myuuid),
|
||||
})
|
||||
|
||||
print(resp.status_code)
|
||||
print(resp.raw)
|
||||
|
||||
return f"""
|
||||
<html>
|
||||
<header>
|
||||
@ -217,6 +206,7 @@ def assign_tag():
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
@app.route('/', methods=['GET'])
|
||||
def health():
|
||||
return "OK", 200
|
||||
|
@ -4,15 +4,16 @@ import traceback
|
||||
from threading import Thread
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import requests
|
||||
|
||||
from config import PRINTER_ID, PRINTER_CODE, PRINTER_IP, SPOOLMAN_API_URL
|
||||
from config import PRINTER_ID, PRINTER_CODE, PRINTER_IP
|
||||
from messages import GET_VERSION, PUSH_ALL
|
||||
from spoolman_client import fetchSpoolList, patchExtraTags
|
||||
|
||||
|
||||
def num2letter(num):
|
||||
return chr(ord("A") + int(num))
|
||||
|
||||
|
||||
def publish(client, msg):
|
||||
result = client.publish(f"device/{PRINTER_ID}/request", json.dumps(msg))
|
||||
status = result[0]
|
||||
@ -23,12 +24,14 @@ def publish(client, msg):
|
||||
print(f"Failed to send message to topic device/{PRINTER_ID}/request")
|
||||
return False
|
||||
|
||||
|
||||
# Inspired by https://github.com/Donkie/Spoolman/issues/217#issuecomment-2303022970
|
||||
def on_message(client, userdata, msg):
|
||||
global LAST_AMS_CONFIG
|
||||
# TODO: Consume spool
|
||||
try:
|
||||
data = json.loads(msg.payload.decode())
|
||||
print(data)
|
||||
if "print" in data and "vt_tray" in data["print"]:
|
||||
print(data)
|
||||
LAST_AMS_CONFIG["vt_tray"] = data["print"]["vt_tray"]
|
||||
@ -42,7 +45,8 @@ def on_message(client, userdata, msg):
|
||||
print(f"AMS [{num2letter(ams['id'])}] (hum: {ams['humidity']}, temp: {ams['temp']}ºC)")
|
||||
for tray in ams["tray"]:
|
||||
if "tray_sub_brands" in tray:
|
||||
print(f" - [{num2letter(ams['id'])}{tray['id']}] {tray['tray_sub_brands']} {tray['tray_color']} ({str(tray['remain']).zfill(3)}%) [[ {tray['tag_uid']} ]]")
|
||||
print(
|
||||
f" - [{num2letter(ams['id'])}{tray['id']}] {tray['tray_sub_brands']} {tray['tray_color']} ({str(tray['remain']).zfill(3)}%) [[ {tray['tag_uid']} ]]")
|
||||
|
||||
found = False
|
||||
for spool in SPOOLS:
|
||||
@ -54,40 +58,45 @@ def on_message(client, userdata, msg):
|
||||
|
||||
found = True
|
||||
|
||||
resp = requests.patch(f"{SPOOLMAN_API_URL}/spool/{spool['id']}", json={
|
||||
"extra": {
|
||||
"tag": spool["extra"]["tag"],
|
||||
"active_tray": json.dumps(f"{PRINTER_ID}_{ams['id']}_{tray['id']}"),
|
||||
}
|
||||
})
|
||||
setActiveTray(spool['id'], spool["extra"], ams['id'], tray["id"])
|
||||
|
||||
print(resp.text)
|
||||
print(resp.status_code)
|
||||
|
||||
#TODO: remove active_tray from inactive spools
|
||||
#Doesn't work for AMS Lite
|
||||
#requests.patch(f"http://{SPOOLMAN_IP}:7912/api/v1/spool/{spool['id']}", json={
|
||||
# TODO: filament remaining - Doesn't work for AMS Lite
|
||||
# requests.patch(f"http://{SPOOLMAN_IP}:7912/api/v1/spool/{spool['id']}", json={
|
||||
# "remaining_weight": tray["remain"] / 100 * tray["tray_weight"]
|
||||
#})
|
||||
# })
|
||||
|
||||
if not found:
|
||||
print(" - Not found. Update spool tag!")
|
||||
if not found:
|
||||
print(" - Not found. Update spool tag!")
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def on_connect(client, userdata, flags, rc):
|
||||
print("Connected with result code "+str(rc))
|
||||
print("Connected with result code " + str(rc))
|
||||
client.subscribe(f"device/{PRINTER_ID}/report")
|
||||
publish(client, GET_VERSION)
|
||||
publish(client, PUSH_ALL)
|
||||
|
||||
|
||||
def setActiveTray(spool_id, spool_extra, ams_id, tray_id):
|
||||
patchExtraTags(spool_id, spool_extra, {
|
||||
"active_tray": json.dumps(f"{PRINTER_ID}_{ams_id}_{tray_id}"),
|
||||
})
|
||||
|
||||
# Remove active tray from inactive spools
|
||||
for old_spool in SPOOLS:
|
||||
if spool_id != old_spool["id"] and old_spool["extra"]["active_tray"] == json.dumps(
|
||||
f"{PRINTER_ID}_{ams_id}_{tray_id}"):
|
||||
patchExtraTags(old_spool["id"], old_spool["extra"], {"active_tray": json.dumps("")})
|
||||
|
||||
|
||||
# Fetch spools from spoolman
|
||||
def fetchSpools():
|
||||
global SPOOLS
|
||||
response = requests.get(f"{SPOOLMAN_API_URL}/spool")
|
||||
SPOOLS = response.json()
|
||||
SPOOLS = fetchSpoolList()
|
||||
return SPOOLS
|
||||
|
||||
|
||||
def async_subscribe():
|
||||
global MQTT_CLIENT
|
||||
MQTT_CLIENT = mqtt.Client()
|
||||
@ -102,18 +111,22 @@ def async_subscribe():
|
||||
MQTT_CLIENT.connect(PRINTER_IP, 8883)
|
||||
MQTT_CLIENT.loop_forever()
|
||||
|
||||
|
||||
# Start the asynchronous processing in a separate thread
|
||||
thread = Thread(target=async_subscribe)
|
||||
thread.start()
|
||||
|
||||
|
||||
def getLastAMSConfig():
|
||||
global LAST_AMS_CONFIG
|
||||
return LAST_AMS_CONFIG
|
||||
|
||||
|
||||
def getMqttClient():
|
||||
global MQTT_CLIENT
|
||||
return MQTT_CLIENT
|
||||
|
||||
MQTT_CLIENT = {} # Global variable storing MQTT Client
|
||||
|
||||
MQTT_CLIENT = {} # Global variable storing MQTT Client
|
||||
LAST_AMS_CONFIG = {} # Global variable storing last AMS configuration
|
||||
SPOOLS = fetchSpools() # Global variable storing latest spool from spoolman
|
||||
SPOOLS = fetchSpools() # Global variable storing latest spool from spoolman
|
||||
|
27
spoolman_client.py
Normal file
27
spoolman_client.py
Normal file
@ -0,0 +1,27 @@
|
||||
import requests
|
||||
from config import SPOOLMAN_API_URL
|
||||
|
||||
|
||||
def patchExtraTags(spool_id, old_extras, new_extras):
|
||||
for key, value in new_extras.items():
|
||||
old_extras[key] = value
|
||||
|
||||
resp = requests.patch(f"{SPOOLMAN_API_URL}/spool/{spool_id}", json={
|
||||
"extra": old_extras
|
||||
})
|
||||
print(resp.text)
|
||||
print(resp.status_code)
|
||||
|
||||
|
||||
def getSpoolById(spool_id):
|
||||
response = requests.get(f"{SPOOLMAN_API_URL}/spool/{spool_id}")
|
||||
print(response.status_code)
|
||||
print(response.text)
|
||||
return response.json()
|
||||
|
||||
|
||||
def fetchSpoolList():
|
||||
response = requests.get(f"{SPOOLMAN_API_URL}/spool")
|
||||
print(response.status_code)
|
||||
print(response.text)
|
||||
return response.json()
|
Loading…
x
Reference in New Issue
Block a user