Update app.py
Browse files
app.py
CHANGED
|
@@ -47,8 +47,9 @@ latest_data = {
|
|
| 47 |
"status": "N/A",
|
| 48 |
"update_time": "Waiting for data...",
|
| 49 |
"image_url": "N/A",
|
| 50 |
-
"
|
| 51 |
-
"
|
|
|
|
| 52 |
}
|
| 53 |
|
| 54 |
bambu_client = None
|
|
@@ -103,30 +104,34 @@ def rpi_on_message(client, userdata, msg):
|
|
| 103 |
payload = msg.payload.decode("utf-8")
|
| 104 |
logger.info(f"Received message from RPI: {payload}")
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 128 |
except Exception as e:
|
| 129 |
-
logger.error(f"Error processing message
|
| 130 |
|
| 131 |
|
| 132 |
def get_data(serial=DEFAULT_SERIAL):
|
|
@@ -198,12 +203,6 @@ def send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed):
|
|
| 198 |
logger.error(f"Error sending parameters: {e}")
|
| 199 |
return f"Error sending parameters: {e}"
|
| 200 |
|
| 201 |
-
|
| 202 |
-
latest_data["status"] = "Sending"
|
| 203 |
-
latest_data["progress"] = 10
|
| 204 |
-
latest_data["message"] = "Sending parameters to printer..."
|
| 205 |
-
|
| 206 |
-
|
| 207 |
|
| 208 |
def get_image_base64(image):
|
| 209 |
if image is None:
|
|
@@ -307,17 +306,6 @@ def capture_image(url=None, use_test_image=False, test_image_name=None):
|
|
| 307 |
else:
|
| 308 |
raise Exception("url is 'N/A'")
|
| 309 |
|
| 310 |
-
def update_print_status():
|
| 311 |
-
global latest_data
|
| 312 |
-
return (
|
| 313 |
-
latest_data["status"],
|
| 314 |
-
latest_data["nozzle_temperature"],
|
| 315 |
-
latest_data["bed_temperature"],
|
| 316 |
-
latest_data["update_time"],
|
| 317 |
-
latest_data.get("progress", 0),
|
| 318 |
-
latest_data.get("message", ""),
|
| 319 |
-
)
|
| 320 |
-
|
| 321 |
|
| 322 |
def health_check():
|
| 323 |
status = {
|
|
@@ -328,17 +316,65 @@ def health_check():
|
|
| 328 |
"latest_update": latest_data["update_time"],
|
| 329 |
}
|
| 330 |
logger.info(f"Health check: {status}")
|
| 331 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 332 |
|
| 333 |
|
| 334 |
demo = gr.Blocks(title="Bambu A1 Mini Print Control")
|
| 335 |
|
| 336 |
with demo:
|
| 337 |
gr.Markdown("# Bambu A1 Mini Print Control")
|
| 338 |
-
|
| 339 |
with gr.Row():
|
| 340 |
refresh_btn = gr.Button("Refresh Status")
|
| 341 |
-
|
| 342 |
with gr.Row():
|
| 343 |
current_status = gr.Textbox(
|
| 344 |
label="Printer Status", value="N/A", interactive=False
|
|
@@ -350,7 +386,7 @@ with demo:
|
|
| 350 |
label="Current Nozzle Temperature", value="N/A", interactive=False
|
| 351 |
)
|
| 352 |
last_update = gr.Textbox(label="Last Update", value="N/A", interactive=False)
|
| 353 |
-
|
| 354 |
with gr.Row():
|
| 355 |
# Left column for image and capture button
|
| 356 |
with gr.Column(scale=2):
|
|
@@ -400,7 +436,7 @@ with demo:
|
|
| 400 |
fn=get_data,
|
| 401 |
outputs=[current_status, current_bed_temp, current_nozzle_temp, last_update],
|
| 402 |
)
|
| 403 |
-
|
| 404 |
capture_btn.click(
|
| 405 |
fn=lambda: gr.update(interactive=False), outputs=capture_btn
|
| 406 |
).then(fn=capture_image, outputs=[captured_image]).then(
|
|
@@ -631,6 +667,26 @@ with demo:
|
|
| 631 |
api_name="health_check",
|
| 632 |
)
|
| 633 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
if __name__ == "__main__":
|
| 635 |
logger.info("Starting Bambu A1 Mini Print Control application")
|
| 636 |
|
|
|
|
| 47 |
"status": "N/A",
|
| 48 |
"update_time": "Waiting for data...",
|
| 49 |
"image_url": "N/A",
|
| 50 |
+
"auto_capture_requested": False,
|
| 51 |
+
"last_capture_job": "None",
|
| 52 |
+
"last_capture_time": "None"
|
| 53 |
}
|
| 54 |
|
| 55 |
bambu_client = None
|
|
|
|
| 104 |
payload = msg.payload.decode("utf-8")
|
| 105 |
logger.info(f"Received message from RPI: {payload}")
|
| 106 |
|
| 107 |
+
try:
|
| 108 |
+
data = json.loads(payload)
|
| 109 |
+
|
| 110 |
+
# 处理状态更新
|
| 111 |
+
if "status" in data:
|
| 112 |
+
latest_data["status"] = data["status"]
|
| 113 |
+
latest_data["update_time"] = data.get("update_time", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
|
| 114 |
+
|
| 115 |
+
if "nozzle_temperature" in data:
|
| 116 |
+
latest_data["nozzle_temperature"] = data["nozzle_temperature"]
|
| 117 |
+
|
| 118 |
+
if "bed_temperature" in data:
|
| 119 |
+
latest_data["bed_temperature"] = data["bed_temperature"]
|
| 120 |
+
|
| 121 |
+
if "error" in data:
|
| 122 |
+
logger.error(f"Error from RPI: {data['error']}")
|
| 123 |
+
|
| 124 |
+
# 添加对自动拍照命令的处理
|
| 125 |
+
if "command" in data and data["command"] == "capture_image" and data.get("auto_triggered", False):
|
| 126 |
+
logger.info("收到自动拍照命令")
|
| 127 |
+
# 异步处理拍照请求,避免阻塞MQTT回调
|
| 128 |
+
threading.Thread(target=handle_auto_capture, args=(data,), daemon=True).start()
|
| 129 |
+
|
| 130 |
+
except json.JSONDecodeError:
|
| 131 |
+
logger.error(f"Invalid JSON in message: {payload}")
|
| 132 |
+
|
| 133 |
except Exception as e:
|
| 134 |
+
logger.error(f"Error processing RPI message: {e}")
|
| 135 |
|
| 136 |
|
| 137 |
def get_data(serial=DEFAULT_SERIAL):
|
|
|
|
| 203 |
logger.error(f"Error sending parameters: {e}")
|
| 204 |
return f"Error sending parameters: {e}"
|
| 205 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 206 |
|
| 207 |
def get_image_base64(image):
|
| 208 |
if image is None:
|
|
|
|
| 306 |
else:
|
| 307 |
raise Exception("url is 'N/A'")
|
| 308 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 309 |
|
| 310 |
def health_check():
|
| 311 |
status = {
|
|
|
|
| 316 |
"latest_update": latest_data["update_time"],
|
| 317 |
}
|
| 318 |
logger.info(f"Health check: {status}")
|
| 319 |
+
|
| 320 |
+
# 修改返回值,确保返回6个值
|
| 321 |
+
return (
|
| 322 |
+
status.get("app", "unknown"),
|
| 323 |
+
"N/A", # 作为nozzle_temperature
|
| 324 |
+
"N/A", # 作为bed_temperature
|
| 325 |
+
status.get("time", "unknown"),
|
| 326 |
+
0, # 作为progress
|
| 327 |
+
f"MQTT: Bambu={status.get('bambu_mqtt_connected')}, RPI={status.get('rpi_mqtt_connected')}" # 作为message
|
| 328 |
+
)
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def update_print_status():
|
| 332 |
+
"""更新打印状态显示"""
|
| 333 |
+
global latest_data
|
| 334 |
+
return (
|
| 335 |
+
latest_data["status"],
|
| 336 |
+
latest_data["nozzle_temperature"],
|
| 337 |
+
latest_data["bed_temperature"],
|
| 338 |
+
latest_data["update_time"],
|
| 339 |
+
latest_data.get("progress", 0),
|
| 340 |
+
latest_data.get("message", ""),
|
| 341 |
+
)
|
| 342 |
+
|
| 343 |
+
|
| 344 |
+
def handle_auto_capture(message):
|
| 345 |
+
"""处理自动拍照请求"""
|
| 346 |
+
try:
|
| 347 |
+
logger.info(f"收到自动拍照请求: {message}")
|
| 348 |
+
|
| 349 |
+
# 提取信息
|
| 350 |
+
print_job = message.get("print_job", "unknown_job")
|
| 351 |
+
timestamp = message.get("timestamp", time.strftime("%Y-%m-%d %H:%M:%S"))
|
| 352 |
+
|
| 353 |
+
# 记录到最新数据中
|
| 354 |
+
latest_data["auto_capture_requested"] = True
|
| 355 |
+
latest_data["last_capture_job"] = print_job
|
| 356 |
+
latest_data["last_capture_time"] = timestamp
|
| 357 |
+
|
| 358 |
+
# 执行拍照操作 - 假设capture_image函数已存在
|
| 359 |
+
image, status = capture_image()
|
| 360 |
+
|
| 361 |
+
# 记录拍照结果
|
| 362 |
+
logger.info(f"自动拍照结果: {status}")
|
| 363 |
+
|
| 364 |
+
return image, status
|
| 365 |
+
except Exception as e:
|
| 366 |
+
logger.error(f"处理自动拍照请求时出错: {e}")
|
| 367 |
+
return None, f"自动拍照失败: {str(e)}"
|
| 368 |
|
| 369 |
|
| 370 |
demo = gr.Blocks(title="Bambu A1 Mini Print Control")
|
| 371 |
|
| 372 |
with demo:
|
| 373 |
gr.Markdown("# Bambu A1 Mini Print Control")
|
| 374 |
+
|
| 375 |
with gr.Row():
|
| 376 |
refresh_btn = gr.Button("Refresh Status")
|
| 377 |
+
|
| 378 |
with gr.Row():
|
| 379 |
current_status = gr.Textbox(
|
| 380 |
label="Printer Status", value="N/A", interactive=False
|
|
|
|
| 386 |
label="Current Nozzle Temperature", value="N/A", interactive=False
|
| 387 |
)
|
| 388 |
last_update = gr.Textbox(label="Last Update", value="N/A", interactive=False)
|
| 389 |
+
|
| 390 |
with gr.Row():
|
| 391 |
# Left column for image and capture button
|
| 392 |
with gr.Column(scale=2):
|
|
|
|
| 436 |
fn=get_data,
|
| 437 |
outputs=[current_status, current_bed_temp, current_nozzle_temp, last_update],
|
| 438 |
)
|
| 439 |
+
|
| 440 |
capture_btn.click(
|
| 441 |
fn=lambda: gr.update(interactive=False), outputs=capture_btn
|
| 442 |
).then(fn=capture_image, outputs=[captured_image]).then(
|
|
|
|
| 667 |
api_name="health_check",
|
| 668 |
)
|
| 669 |
|
| 670 |
+
# 在Camera Control标签页中添加自动拍照状态显示
|
| 671 |
+
with gr.Tab("Camera Control"):
|
| 672 |
+
# 添加自动拍照状态显示
|
| 673 |
+
with gr.Row():
|
| 674 |
+
auto_capture_status = gr.Textbox(label="Auto Capture Status", value="Waiting")
|
| 675 |
+
|
| 676 |
+
# 添加自动刷新,更新自动拍照状态
|
| 677 |
+
def update_capture_status():
|
| 678 |
+
auto_status = "Triggered" if latest_data.get("auto_capture_requested", False) else "Waiting"
|
| 679 |
+
last_time = latest_data.get("last_capture_time", "None")
|
| 680 |
+
last_job = latest_data.get("last_capture_job", "None")
|
| 681 |
+
return f"{auto_status} (Last: {last_job} at {last_time})"
|
| 682 |
+
|
| 683 |
+
demo.load(
|
| 684 |
+
fn=update_capture_status,
|
| 685 |
+
inputs=[],
|
| 686 |
+
outputs=[auto_capture_status],
|
| 687 |
+
every=5 # 每5秒刷新一次
|
| 688 |
+
)
|
| 689 |
+
|
| 690 |
if __name__ == "__main__":
|
| 691 |
logger.info("Starting Bambu A1 Mini Print Control application")
|
| 692 |
|