SissiFeng commited on
Commit
a0f3c4e
·
1 Parent(s): 66e5ad0
Files changed (1) hide show
  1. app.py +99 -239
app.py CHANGED
@@ -38,8 +38,8 @@ client = None
38
  latest_data = {
39
  "bed_temperature": "N/A",
40
  "nozzle_temperature": "N/A",
41
- "status": "Disconnected",
42
- "update_time": "Not connected"
43
  }
44
 
45
  # Initialize analysis components
@@ -97,56 +97,20 @@ def create_3mf_package(gcode_content: str, gcode_filename: str = "Metadata/plate
97
  zip_buffer.seek(0)
98
  return zip_buffer
99
 
100
- def create_client(host, port, username, password, max_retries=3):
101
- """Create MQTT client with retry mechanism"""
102
  global client
103
-
104
- for attempt in range(max_retries):
105
- try:
106
- client = mqtt.Client(protocol=mqtt.MQTTv311)
107
- client.username_pw_set(username, password)
108
- client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS)
109
- client.on_connect = on_connect
110
- client.on_message = on_message
111
- client.on_disconnect = on_disconnect
112
-
113
- print(f"Attempting to connect to MQTT broker (attempt {attempt + 1}/{max_retries})")
114
- client.connect(host, port, keepalive=60)
115
- client.loop_start()
116
- return True
117
-
118
- except Exception as e:
119
- print(f"Connection attempt {attempt + 1} failed: {e}")
120
- if client:
121
- client.loop_stop()
122
- client = None
123
- if attempt < max_retries - 1:
124
- time.sleep(5)
125
-
126
- print("Failed to connect to MQTT broker after all attempts")
127
- return False
128
 
129
  def on_connect(client, userdata, flags, rc):
130
- """Callback when connected to MQTT broker"""
131
- if rc == 0:
132
- print("Successfully connected to MQTT broker")
133
- response_topic = f"bambu_a1_mini/response/{PRINTER_SERIAL}"
134
- request_topic = f"bambu_a1_mini/request/{PRINTER_SERIAL}"
135
- client.subscribe(response_topic)
136
- print(f"Subscribed to {response_topic}")
137
-
138
- # Send initial request
139
- client.publish(request_topic, json.dumps("HI"))
140
-
141
- # Update status
142
- global latest_data
143
- latest_data["status"] = "Connected"
144
- latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
145
- else:
146
- print(f"Failed to connect to MQTT broker with code: {rc}")
147
 
148
  def on_message(client, userdata, message):
149
- """Handle incoming MQTT messages"""
150
  global latest_data
151
  print("Received message")
152
  try:
@@ -154,146 +118,45 @@ def on_message(client, userdata, message):
154
  latest_data["bed_temperature"] = data.get("bed_temperature", "N/A")
155
  latest_data["nozzle_temperature"] = data.get("nozzle_temperature", "N/A")
156
  latest_data["status"] = data.get("status", "N/A")
157
- latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
158
  except Exception as e:
159
  print(f"Error parsing MQTT message: {e}")
160
 
161
- def on_disconnect(client, userdata, rc):
162
- """Callback when disconnected from MQTT broker"""
163
- print("Disconnected from MQTT broker")
164
- global latest_data
165
- latest_data["status"] = "Disconnected"
166
- latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S")
167
-
168
- if rc != 0:
169
- print("Unexpected disconnection. Attempting to reconnect...")
170
- create_client(HOST, PORT, USERNAME, PASSWORD)
171
-
172
- def send_print_command(params):
173
- """Send print parameters to Pi 4B"""
174
- command = create_print_command(params)
175
- mqtt_client.publish(TOPICS['printer']['command'], json.dumps(command))
176
- logger.info(f"Print command sent for square {params.get('square_id')}")
177
- return "Print command sent successfully"
178
-
179
- def send_camera_command(square_id: str):
180
- """Send capture command to Pi Zero"""
181
- command = create_capture_command(square_id)
182
- mqtt_client.publish(TOPICS['camera']['command'], json.dumps(command))
183
- logger.info(f"Camera command sent for square {square_id}")
184
- return "Camera command sent successfully"
185
-
186
- def send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed):
187
- """Send new print parameters to printer"""
188
- try:
189
- params = {
190
- 'nozzle_temp': nozzle_temp,
191
- 'bed_temp': bed_temp,
192
- 'print_speed': print_speed,
193
- 'fan_speed': fan_speed
194
- }
195
-
196
- request_topic = f"bambu_a1_mini/request/{PRINTER_SERIAL}"
197
- if client:
198
- client.publish(request_topic, json.dumps({
199
- 'command': 'set_parameters',
200
- 'parameters': params
201
- }))
202
- return "Parameters sent successfully"
203
- return "MQTT not connected"
204
- except Exception as e:
205
- return f"Error sending parameters: {e}"
206
-
207
- # Initialize MQTT client
208
- try:
209
- mqtt_connected = create_client(HOST, PORT, USERNAME, PASSWORD)
210
- if not mqtt_connected:
211
- print("Warning: Starting without MQTT connection")
212
- except Exception as e:
213
- print(f"Warning: Failed to initialize MQTT: {e}")
214
-
215
- def update_status():
216
- """Update printer status display"""
217
  if client is None:
218
- return "N/A", "N/A", "Disconnected", "Not connected"
219
-
220
- try:
221
- request_topic = f"bambu_a1_mini/request/{PRINTER_SERIAL}"
222
- client.publish(request_topic, json.dumps("HI"))
223
-
224
- return (
225
- latest_data["nozzle_temperature"],
226
- latest_data["bed_temperature"],
227
- latest_data["status"],
228
- latest_data["update_time"]
229
- )
230
- except Exception as e:
231
- print(f"Status update error: {e}")
232
- return "N/A", "N/A", "Error", str(e)
233
 
234
- def analyze_print(image, nozzle_temp, bed_temp, print_speed, fan_speed):
235
- """Analyze print quality and return evaluation results"""
236
- if image is None:
237
- return None, 0, 0, 0, 0, 0, 0, 0, 0
238
-
239
- # Package current parameters
240
- current_params = {
241
- 'nozzle_temp': float(nozzle_temp),
242
- 'bed_temp': float(bed_temp),
243
- 'print_speed': float(print_speed),
244
- 'fan_speed': float(fan_speed)
245
- }
246
 
247
- # Analyze print quality
248
- analysis_results = detector.analyze_print(image)
249
 
250
- # Get optimization results
251
- results = optimizer.evaluate_objectives(image, current_params)
252
-
253
- # Calculate quality metrics
254
- metrics = detector.calculate_quality_metrics(image)
255
 
256
  return (
257
- analysis_results['binary_mask'], # Visualization
258
- float(metrics['missing_rate']),
259
- float(metrics['excess_rate']),
260
- float(metrics['stringing_rate']),
261
- float(metrics['uniformity_score']),
262
- float(analysis_results['quality_score']),
263
- float(results['objectives']['speed']),
264
- float(results['objectives']['material']),
265
- float(results['objectives']['total'])
266
  )
267
 
268
  # Gradio interface
269
  with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
270
  gr.Markdown("# Bambu A1 Mini Print Quality Analysis")
271
 
272
- # Current printer parameters display
273
  with gr.Row():
274
- current_nozzle_temp = gr.Textbox(
275
- label="Current Nozzle Temperature",
276
- value="N/A",
277
- interactive=False
278
- )
279
- current_bed_temp = gr.Textbox(
280
- label="Current Bed Temperature",
281
- value="N/A",
282
- interactive=False
283
- )
284
- current_status = gr.Textbox(
285
- label="Printer Status",
286
- value="N/A",
287
- interactive=False
288
- )
289
- last_update = gr.Textbox(
290
- label="Last Update",
291
- value="N/A",
292
- interactive=False
293
- )
294
-
295
  refresh_btn = gr.Button("Refresh Status")
296
-
297
  with gr.Row():
298
  # show S3 image
299
  s3_image = gr.Image(
@@ -305,37 +168,21 @@ with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
305
  label="Current Print Image",
306
  type="numpy"
307
  )
308
-
309
  with gr.Row():
310
  with gr.Column():
311
  # Print parameter inputs
312
- nozzle_temp = gr.Slider(
313
- minimum=180, maximum=250, step=1,
314
- value=200,
315
- label="Nozzle Temperature (°C)"
316
- )
317
- bed_temp = gr.Slider(
318
- minimum=40, maximum=100, step=1,
319
- value=60,
320
- label="Bed Temperature (°C)"
321
- )
322
- print_speed = gr.Slider(
323
- minimum=20, maximum=150, step=1,
324
- value=60,
325
- label="Print Speed (mm/s)"
326
- )
327
- fan_speed = gr.Slider(
328
- minimum=0, maximum=100, step=1,
329
- value=100,
330
- label="Fan Speed (%)"
331
- )
332
 
333
  # Buttons
334
  with gr.Row():
335
  capture_btn = gr.Button("Capture Image")
336
  analyze_btn = gr.Button("Analyze Print")
337
- send_params_btn = gr.Button("Send Print Parameters") # 新增按钮
338
-
339
  with gr.Column():
340
  # Results visualization
341
  result_image = gr.Image(label="Analysis Result")
@@ -398,38 +245,17 @@ with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
398
  )
399
 
400
  # connect refresh button
401
- def update_status():
402
- """Update printer status display"""
403
- return (
404
- latest_data["nozzle_temperature"],
405
- latest_data["bed_temperature"],
406
- latest_data["status"],
407
- latest_data["update_time"]
408
- )
409
-
410
- refresh_btn.click(
411
- fn=update_status,
412
- outputs=[
413
- current_nozzle_temp,
414
- current_bed_temp,
415
- current_status,
416
- last_update
417
- ]
418
- )
419
 
420
  # Auto refresh
421
  def auto_refresh():
422
  while True:
423
- try:
424
- time.sleep(5)
425
- values = update_status()
426
- current_nozzle_temp.value = values[0]
427
- current_bed_temp.value = values[1]
428
- current_status.value = values[2]
429
- last_update.value = values[3]
430
- except Exception as e:
431
- print(f"Auto refresh error: {e}")
432
- continue
433
 
434
  threading.Thread(target=auto_refresh, daemon=True).start()
435
 
@@ -440,27 +266,61 @@ with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
440
  outputs=[current_status]
441
  )
442
 
443
- def handle_print_workflow(params):
444
- """Coordinate print and capture workflow"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
445
  try:
446
- # 1. Send print command to Pi 4B
447
- printer_command = create_print_command(params)
448
- mqtt_client.publish(TOPICS['printer']['command'], json.dumps(printer_command))
449
-
450
- # 2. Wait for printer ready status
451
- # (handle by on_message callback)
452
-
453
- # 3. Send capture command to Pi Zero
454
- camera_command = create_capture_command(params['square_id'])
455
- mqtt_client.publish(TOPICS['camera']['command'], json.dumps(camera_command))
456
-
457
- # 4. Wait for image URL
458
- # (handle by on_message callback)
459
 
460
- return "Workflow started successfully"
 
 
 
 
 
 
 
461
  except Exception as e:
462
- return f"Error: {str(e)}"
463
 
464
  # Launch the app
465
  if __name__ == "__main__":
466
- demo.launch(ssr=False)
 
38
  latest_data = {
39
  "bed_temperature": "N/A",
40
  "nozzle_temperature": "N/A",
41
+ "status": "N/A",
42
+ "update_time": "Waiting for data..."
43
  }
44
 
45
  # Initialize analysis components
 
97
  zip_buffer.seek(0)
98
  return zip_buffer
99
 
100
+ def create_client(host, port, username, password):
 
101
  global client
102
+ client = mqtt.Client()
103
+ client.username_pw_set(username, password)
104
+ client.tls_set(tls_version=mqtt.ssl.PROTOCOL_TLS)
105
+ client.on_connect = on_connect
106
+ client.on_message = on_message
107
+ client.connect(host, port)
108
+ client.loop_start()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
110
  def on_connect(client, userdata, flags, rc):
111
+ print(f"Connected with result code {rc}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
 
113
  def on_message(client, userdata, message):
 
114
  global latest_data
115
  print("Received message")
116
  try:
 
118
  latest_data["bed_temperature"] = data.get("bed_temperature", "N/A")
119
  latest_data["nozzle_temperature"] = data.get("nozzle_temperature", "N/A")
120
  latest_data["status"] = data.get("status", "N/A")
121
+ latest_data["update_time"] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
122
  except Exception as e:
123
  print(f"Error parsing MQTT message: {e}")
124
 
125
+ def get_data():
126
+ """Request data from the MQTT broker."""
127
+ global client
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  if client is None:
129
+ create_client(HOST, PORT, USERNAME, PASSWORD)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
 
131
+ serial = "0309CA471800852"
132
+ request_topic = f"bambu_a1_mini/request/{serial}"
133
+ response_topic = f"bambu_a1_mini/response/{serial}"
 
 
 
 
 
 
 
 
 
134
 
135
+ print(f"Subscribing to {response_topic}")
136
+ client.subscribe(response_topic)
137
 
138
+ # Send a request to get data
139
+ client.publish(request_topic, json.dumps("HI"))
 
 
 
140
 
141
  return (
142
+ latest_data["status"],
143
+ latest_data["bed_temperature"],
144
+ latest_data["nozzle_temperature"],
145
+ latest_data["update_time"]
 
 
 
 
 
146
  )
147
 
148
  # Gradio interface
149
  with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
150
  gr.Markdown("# Bambu A1 Mini Print Quality Analysis")
151
 
 
152
  with gr.Row():
153
+ current_nozzle_temp = gr.Textbox(label="Current Nozzle Temperature", value="N/A", interactive=False)
154
+ current_bed_temp = gr.Textbox(label="Current Bed Temperature", value="N/A", interactive=False)
155
+ current_status = gr.Textbox(label="Printer Status", value="N/A", interactive=False)
156
+ last_update = gr.Textbox(label="Last Update", value="N/A", interactive=False)
157
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  refresh_btn = gr.Button("Refresh Status")
159
+
160
  with gr.Row():
161
  # show S3 image
162
  s3_image = gr.Image(
 
168
  label="Current Print Image",
169
  type="numpy"
170
  )
171
+
172
  with gr.Row():
173
  with gr.Column():
174
  # Print parameter inputs
175
+ nozzle_temp = gr.Slider(minimum=180, maximum=250, step=1, value=200, label="Nozzle Temperature (°C)")
176
+ bed_temp = gr.Slider(minimum=40, maximum=100, step=1, value=60, label="Bed Temperature (°C)")
177
+ print_speed = gr.Slider(minimum=20, maximum=150, step=1, value=60, label="Print Speed (mm/s)")
178
+ fan_speed = gr.Slider(minimum=0, maximum=100, step=1, value=100, label="Fan Speed (%)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
  # Buttons
181
  with gr.Row():
182
  capture_btn = gr.Button("Capture Image")
183
  analyze_btn = gr.Button("Analyze Print")
184
+ send_params_btn = gr.Button("Send Print Parameters")
185
+
186
  with gr.Column():
187
  # Results visualization
188
  result_image = gr.Image(label="Analysis Result")
 
245
  )
246
 
247
  # connect refresh button
248
+ refresh_btn.click(fn=get_data, outputs=[current_status, current_bed_temp, current_nozzle_temp, last_update])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
 
250
  # Auto refresh
251
  def auto_refresh():
252
  while True:
253
+ time.sleep(5)
254
+ status, bed_temp, nozzle_temp, update_time = get_data()
255
+ current_status.value = status
256
+ current_bed_temp.value = bed_temp
257
+ current_nozzle_temp.value = nozzle_temp
258
+ last_update.value = update_time
 
 
 
 
259
 
260
  threading.Thread(target=auto_refresh, daemon=True).start()
261
 
 
266
  outputs=[current_status]
267
  )
268
 
269
+ def analyze_print(image, nozzle_temp, bed_temp, print_speed, fan_speed):
270
+ """Analyze print quality and return evaluation results"""
271
+ if image is None:
272
+ return None, 0, 0, 0, 0, 0, 0, 0, 0
273
+
274
+ # Package current parameters
275
+ current_params = {
276
+ 'nozzle_temp': float(nozzle_temp),
277
+ 'bed_temp': float(bed_temp),
278
+ 'print_speed': float(print_speed),
279
+ 'fan_speed': float(fan_speed)
280
+ }
281
+
282
+ # Analyze print quality
283
+ analysis_results = detector.analyze_print(image)
284
+
285
+ # Get optimization results
286
+ results = optimizer.evaluate_objectives(image, current_params)
287
+
288
+ # Calculate quality metrics
289
+ metrics = detector.calculate_quality_metrics(image)
290
+
291
+ return (
292
+ analysis_results['binary_mask'], # Visualization
293
+ float(metrics['missing_rate']),
294
+ float(metrics['excess_rate']),
295
+ float(metrics['stringing_rate']),
296
+ float(metrics['uniformity_score']),
297
+ float(analysis_results['quality_score']),
298
+ float(results['objectives']['speed']),
299
+ float(results['objectives']['material']),
300
+ float(results['objectives']['total'])
301
+ )
302
+
303
+ def send_print_parameters(nozzle_temp, bed_temp, print_speed, fan_speed):
304
+ """Send new print parameters to printer"""
305
  try:
306
+ params = {
307
+ 'nozzle_temp': nozzle_temp,
308
+ 'bed_temp': bed_temp,
309
+ 'print_speed': print_speed,
310
+ 'fan_speed': fan_speed
311
+ }
 
 
 
 
 
 
 
312
 
313
+ request_topic = f"bambu_a1_mini/request/{PRINTER_SERIAL}"
314
+ if client:
315
+ client.publish(request_topic, json.dumps({
316
+ 'command': 'set_parameters',
317
+ 'parameters': params
318
+ }))
319
+ return "Parameters sent successfully"
320
+ return "MQTT not connected"
321
  except Exception as e:
322
+ return f"Error sending parameters: {e}"
323
 
324
  # Launch the app
325
  if __name__ == "__main__":
326
+ demo.launch()