SissiFeng commited on
Commit
1eca2b8
·
1 Parent(s): 3637706
Files changed (1) hide show
  1. app.py +111 -85
app.py CHANGED
@@ -21,7 +21,7 @@ load_dotenv()
21
 
22
  # MQTT Configuration
23
  HOST = os.getenv("host")
24
- PORT = int(os.getenv("port", 8883))
25
  USERNAME = os.getenv("username")
26
  PASSWORD = os.getenv("password")
27
  PRINTER_SERIAL = os.getenv("PRINTER_SERIAL", "0309CA471800852")
@@ -47,6 +47,63 @@ latest_data = {
47
  optimizer = MOPrintOptimizer()
48
  detector = DefectDetector()
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  def create_3mf_package(gcode_content: str, gcode_filename: str = "Metadata/plate_1.gcode") -> BytesIO:
51
  """Create a 3MF package from G-code content"""
52
  zip_buffer = BytesIO()
@@ -74,71 +131,38 @@ def on_connect(client, userdata, flags, rc):
74
  """MQTT connection callback"""
75
  logger.info(f"Connected with result code {rc}")
76
  if rc == 0:
77
- # Subscribe to printer response topic
78
- response_topic = f"bambu_a1_mini/response/{PRINTER_SERIAL}"
79
  client.subscribe(response_topic)
80
  logger.info(f"Subscribed to {response_topic}")
81
-
82
- # Subscribe to printer status topic
83
- status_topic = f"bambu_a1_mini/status/{PRINTER_SERIAL}"
84
- client.subscribe(status_topic)
85
- logger.info(f"Subscribed to {status_topic}")
86
-
87
- # Subscribe to camera image topic
88
- image_topic = f"bambu_a1_mini/image/{PRINTER_SERIAL}"
89
- client.subscribe(image_topic)
90
- logger.info(f"Subscribed to {image_topic}")
91
 
92
  def on_message(client, userdata, message):
93
- """MQTT message callback"""
94
  try:
95
  data = json.loads(message.payload)
96
-
97
- if "image" in message.topic:
98
- # handle new image URL
99
- image_url = data.get("image_url")
100
- if image_url:
101
- latest_data.update({
102
- "current_image_url": image_url,
103
- "image_timestamp": data.get("timestamp"),
104
- "square_id": data.get("square_id")
105
- })
106
- # update interface display
107
- s3_image.update(value=image_url)
108
-
109
- elif "status" in message.topic:
110
- # update status
111
- latest_data.update({
112
- "status": data.get("status"),
113
- "print_progress": data.get("progress", 0),
114
- "current_square_id": data.get("square_id"),
115
- "print_timestamp": data.get("timestamp"),
116
- "update_time": time.strftime("%Y-%m-%d %H:%M:%S")
117
- })
118
  except Exception as e:
119
  logger.error(f"Error processing message: {e}")
120
 
121
  def send_print_command(params):
122
- """Send print parameters to Pi Zero via MQTT"""
123
- command = {
124
- "action": "print",
125
- "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"),
126
- "square_id": params.get("square_id"), # get from position_manager
127
- "parameters": {
128
- "bed_temp": float(params["bed_temp"]),
129
- "nozzle_temp": float(params["nozzle_temp"]),
130
- "print_speed": float(params["print_speed"]),
131
- "layer_height": float(params["layer_height"]),
132
- "flow_rate": float(params["flow_rate"]),
133
- "retraction_distance": float(params["retraction_distance"]),
134
- "fan_speed": float(params["fan_speed"])
135
- }
136
- }
137
-
138
- command_topic = f"bambu_a1_mini/command/{PRINTER_SERIAL}"
139
- mqtt_client.publish(command_topic, json.dumps(command))
140
  return "Print command sent successfully"
141
 
 
 
 
 
 
 
 
142
  # Initialize MQTT client
143
  mqtt_client = create_client(HOST, PORT, USERNAME, PASSWORD)
144
 
@@ -147,21 +171,18 @@ def update_printer_status():
147
  if mqtt_client is None:
148
  return "MQTT not connected", "No connection"
149
 
150
- status_text = (
 
 
 
 
 
 
151
  f"Status: {latest_data['status']}\n"
152
- f"Progress: {latest_data['print_progress']}%\n"
153
- f"Bed Temp: {latest_data['bed_temperature']}°C\n"
154
- f"Nozzle Temp: {latest_data['nozzle_temperature']}°C\n"
155
  f"Last Update: {latest_data['update_time']}"
156
  )
157
-
158
- job_text = (
159
- f"Square ID: {latest_data.get('current_square_id', 'N/A')}\n"
160
- f"Print Time: {latest_data.get('print_time', 'N/A')}\n"
161
- f"Image Status: {'Captured' if latest_data.get('current_image_url') else 'Waiting'}"
162
- )
163
-
164
- return status_text, job_text
165
 
166
  def analyze_print(image,
167
  nozzle_temp, print_speed, layer_height,
@@ -321,26 +342,10 @@ with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
321
  ]
322
  )
323
 
324
- # add image refresh function
325
- def refresh_images():
326
- """refresh image display"""
327
- image_url = latest_data.get("current_image_url")
328
- if image_url:
329
- return image_url
330
- return None
331
-
332
  # connect refresh button
333
  refresh_btn.click(
334
- fn=lambda: (
335
- update_printer_status()[0],
336
- update_printer_status()[1],
337
- refresh_images()
338
- ),
339
- outputs=[
340
- printer_status,
341
- current_job_status,
342
- s3_image
343
- ]
344
  )
345
 
346
  # Auto-refresh printer status
@@ -351,12 +356,33 @@ with gr.Blocks(title="Bambu A1 Mini Print Analysis") as demo:
351
  printer_status.update(status)
352
  current_job_status.update(job_status)
353
  # update image
354
- image_url = refresh_images()
355
  if image_url:
356
  s3_image.update(image_url)
357
 
358
  threading.Thread(target=auto_refresh, daemon=True).start()
359
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  # Launch the app
361
  if __name__ == "__main__":
362
  demo.launch()
 
21
 
22
  # MQTT Configuration
23
  HOST = os.getenv("host")
24
+ PORT = int(os.getenv("port"))
25
  USERNAME = os.getenv("username")
26
  PASSWORD = os.getenv("password")
27
  PRINTER_SERIAL = os.getenv("PRINTER_SERIAL", "0309CA471800852")
 
47
  optimizer = MOPrintOptimizer()
48
  detector = DefectDetector()
49
 
50
+ # MQTT Topics structure
51
+ TOPICS = {
52
+ 'printer': {
53
+ 'command': 'bambu/printer/command', # HF -> Pi 4B
54
+ 'status': 'bambu/printer/status', # Pi 4B -> HF
55
+ 'response': 'bambu/printer/response' # Pi 4B -> HF
56
+ },
57
+ 'camera': {
58
+ 'command': 'bambu/camera/command', # HF -> Pi Zero
59
+ 'status': 'bambu/camera/status', # Pi Zero -> HF
60
+ 'image': 'bambu/camera/image' # Pi Zero -> HF (S3 URL)
61
+ }
62
+ }
63
+
64
+ # Workflow status tracking
65
+ WORKFLOW_STATUS = {
66
+ 'print_started': False,
67
+ 'print_completed': False,
68
+ 'image_captured': False,
69
+ 'analysis_completed': False,
70
+ 'current_square_id': None,
71
+ 'start_time': None,
72
+ 'completion_time': None
73
+ }
74
+
75
+ def update_workflow_status(status_type: str, value: bool = True):
76
+ """Update workflow status
77
+
78
+ Args:
79
+ status_type: Type of status to update
80
+ value: New status value
81
+ """
82
+ WORKFLOW_STATUS[status_type] = value
83
+ if status_type == 'print_started':
84
+ WORKFLOW_STATUS['start_time'] = time.strftime('%Y-%m-%d %H:%M:%S')
85
+ elif status_type == 'analysis_completed':
86
+ WORKFLOW_STATUS['completion_time'] = time.strftime('%Y-%m-%d %H:%M:%S')
87
+
88
+ # Message formats
89
+ def create_print_command(params):
90
+ return {
91
+ 'type': 'print',
92
+ 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
93
+ 'params': {
94
+ 'nozzle_temp': params['nozzle_temp'],
95
+ 'print_speed': params['print_speed'],
96
+ # ... other params
97
+ }
98
+ }
99
+
100
+ def create_capture_command(square_id):
101
+ return {
102
+ 'type': 'capture',
103
+ 'timestamp': time.strftime('%Y-%m-%d %H:%M:%S'),
104
+ 'square_id': square_id
105
+ }
106
+
107
  def create_3mf_package(gcode_content: str, gcode_filename: str = "Metadata/plate_1.gcode") -> BytesIO:
108
  """Create a 3MF package from G-code content"""
109
  zip_buffer = BytesIO()
 
131
  """MQTT connection callback"""
132
  logger.info(f"Connected with result code {rc}")
133
  if rc == 0:
134
+ serial = os.getenv("PRINTER_SERIAL", "0309CA471800852")
135
+ response_topic = f"bambu_a1_mini/response/{serial}"
136
  client.subscribe(response_topic)
137
  logger.info(f"Subscribed to {response_topic}")
 
 
 
 
 
 
 
 
 
 
138
 
139
  def on_message(client, userdata, message):
140
+ """Handle incoming MQTT messages"""
141
  try:
142
  data = json.loads(message.payload)
143
+ latest_data.update({
144
+ "bed_temperature": data.get("bed_temperature", "N/A"),
145
+ "nozzle_temperature": data.get("nozzle_temperature", "N/A"),
146
+ "status": data.get("status", "N/A"),
147
+ "update_time": time.strftime("%Y-%m-%d %H:%M:%S")
148
+ })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  except Exception as e:
150
  logger.error(f"Error processing message: {e}")
151
 
152
  def send_print_command(params):
153
+ """Send print parameters to Pi 4B"""
154
+ command = create_print_command(params)
155
+ mqtt_client.publish(TOPICS['printer']['command'], json.dumps(command))
156
+ logger.info(f"Print command sent for square {params.get('square_id')}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  return "Print command sent successfully"
158
 
159
+ def send_camera_command(square_id: str):
160
+ """Send capture command to Pi Zero"""
161
+ command = create_capture_command(square_id)
162
+ mqtt_client.publish(TOPICS['camera']['command'], json.dumps(command))
163
+ logger.info(f"Camera command sent for square {square_id}")
164
+ return "Camera command sent successfully"
165
+
166
  # Initialize MQTT client
167
  mqtt_client = create_client(HOST, PORT, USERNAME, PASSWORD)
168
 
 
171
  if mqtt_client is None:
172
  return "MQTT not connected", "No connection"
173
 
174
+ serial = os.getenv("PRINTER_SERIAL", "0309CA471800852")
175
+ request_topic = f"bambu_a1_mini/request/{serial}"
176
+ mqtt_client.publish(request_topic, json.dumps("HI"))
177
+
178
+ time.sleep(1) # Wait for response
179
+
180
+ return (
181
  f"Status: {latest_data['status']}\n"
182
+ f"Bed Temp: {latest_data['bed_temperature']}\n"
183
+ f"Nozzle Temp: {latest_data['nozzle_temperature']}",
 
184
  f"Last Update: {latest_data['update_time']}"
185
  )
 
 
 
 
 
 
 
 
186
 
187
  def analyze_print(image,
188
  nozzle_temp, print_speed, layer_height,
 
342
  ]
343
  )
344
 
 
 
 
 
 
 
 
 
345
  # connect refresh button
346
  refresh_btn.click(
347
+ fn=update_printer_status,
348
+ outputs=[printer_status, current_job_status]
 
 
 
 
 
 
 
 
349
  )
350
 
351
  # Auto-refresh printer status
 
356
  printer_status.update(status)
357
  current_job_status.update(job_status)
358
  # update image
359
+ image_url = latest_data.get("current_image_url")
360
  if image_url:
361
  s3_image.update(image_url)
362
 
363
  threading.Thread(target=auto_refresh, daemon=True).start()
364
 
365
+ def handle_print_workflow(params):
366
+ """Coordinate print and capture workflow"""
367
+ try:
368
+ # 1. Send print command to Pi 4B
369
+ printer_command = create_print_command(params)
370
+ mqtt_client.publish(TOPICS['printer']['command'], json.dumps(printer_command))
371
+
372
+ # 2. Wait for printer ready status
373
+ # (handle by on_message callback)
374
+
375
+ # 3. Send capture command to Pi Zero
376
+ camera_command = create_capture_command(params['square_id'])
377
+ mqtt_client.publish(TOPICS['camera']['command'], json.dumps(camera_command))
378
+
379
+ # 4. Wait for image URL
380
+ # (handle by on_message callback)
381
+
382
+ return "Workflow started successfully"
383
+ except Exception as e:
384
+ return f"Error: {str(e)}"
385
+
386
  # Launch the app
387
  if __name__ == "__main__":
388
  demo.launch()